From 102576cd8c5baa9077e5b1b864b52c83c23c71ae Mon Sep 17 00:00:00 2001 From: Elvendir Date: Sat, 18 Mar 2023 17:53:41 +0100 Subject: [PATCH 001/915] adddede LastPlayed as filter option in beatmap carousel --- .../Select/Carousel/CarouselBeatmap.cs | 1 + osu.Game/Screens/Select/FilterCriteria.cs | 1 + osu.Game/Screens/Select/FilterQueryParser.cs | 53 ++++++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 7e48bc5cdd..5088dfdc02 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -48,6 +48,7 @@ namespace osu.Game.Screens.Select.Carousel match &= !criteria.CircleSize.HasFilter || criteria.CircleSize.IsInRange(BeatmapInfo.Difficulty.CircleSize); match &= !criteria.OverallDifficulty.HasFilter || criteria.OverallDifficulty.IsInRange(BeatmapInfo.Difficulty.OverallDifficulty); match &= !criteria.Length.HasFilter || criteria.Length.IsInRange(BeatmapInfo.Length); + match &= !criteria.LastPlayed.HasFilter || criteria.LastPlayed.IsInRange(BeatmapInfo.LastPlayed); match &= !criteria.BPM.HasFilter || criteria.BPM.IsInRange(BeatmapInfo.BPM); match &= !criteria.BeatDivisor.HasFilter || criteria.BeatDivisor.IsInRange(BeatmapInfo.BeatDivisor); diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 320bfb1b45..a2da98368d 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -31,6 +31,7 @@ namespace osu.Game.Screens.Select public OptionalRange BPM; public OptionalRange BeatDivisor; public OptionalRange OnlineStatus; + public OptionalRange LastPlayed; public OptionalTextFilter Creator; public OptionalTextFilter Artist; diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index c86554ddbc..6b6b2f04a9 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -61,6 +61,10 @@ namespace osu.Game.Screens.Select case "length": return tryUpdateLengthRange(criteria, op, value); + case "played": + case "lastplayed": + return tryUpdateLastPlayedRange(criteria, op, value); + case "divisor": return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt); @@ -109,7 +113,8 @@ namespace osu.Game.Screens.Select value.EndsWith("ms", StringComparison.Ordinal) ? 1 : value.EndsWith('s') ? 1000 : value.EndsWith('m') ? 60000 : - value.EndsWith('h') ? 3600000 : 1000; + value.EndsWith('h') ? 3600000 : + value.EndsWith('d') ? 86400000 : 1000; private static bool tryParseFloatWithPoint(string value, out float result) => float.TryParse(value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result); @@ -368,5 +373,51 @@ namespace osu.Game.Screens.Select return tryUpdateCriteriaRange(ref criteria.Length, op, totalLength, minScale / 2.0); } + + private static bool tryUpdateLastPlayedRange(FilterCriteria criteria, Operator op, string val) + { + List parts = new List(); + + GroupCollection? match = null; + + match ??= tryMatchRegex(val, @"^((?\d+):)?(?\d+):(?\d+)$"); + match ??= tryMatchRegex(val, @"^((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); + match ??= tryMatchRegex(val, @"^(?\d+(\.\d+)?)$"); + + if (match == null) + return false; + + if (match["seconds"].Success) + parts.Add(match["seconds"].Value + "s"); + if (match["minutes"].Success) + parts.Add(match["minutes"].Value + "m"); + if (match["hours"].Success) + parts.Add(match["hours"].Value + "h"); + if (match["days"].Success) + parts.Add(match["days"].Value + "d"); + + + double totalLength = 0; + int minScale = 86400000; + + for (int i = 0; i < parts.Count; i++) + { + string part = parts[i]; + string partNoUnit = part.TrimEnd('m', 's', 'h', 'd') ; + if (!tryParseDoubleWithPoint(partNoUnit, out double length)) + return false; + + if (i != parts.Count - 1 && length >= 60) + return false; + if (i != 0 && partNoUnit.Contains('.')) + return false; + + int scale = getLengthScale(part); + totalLength += length * scale; + minScale = Math.Min(minScale, scale); + } + + return tryUpdateCriteriaRange(ref criteria.LastPlayed, op, totalLength, minScale / 2.0); + } } } From 216a88e18d71f74ddccea1b70aff77305ec88920 Mon Sep 17 00:00:00 2001 From: Elvendir Date: Sat, 18 Mar 2023 21:35:10 +0100 Subject: [PATCH 002/915] limited max Date comparison --- .../Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- osu.Game/Screens/Select/FilterQueryParser.cs | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 5088dfdc02..069d4f36d6 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Select.Carousel match &= !criteria.CircleSize.HasFilter || criteria.CircleSize.IsInRange(BeatmapInfo.Difficulty.CircleSize); match &= !criteria.OverallDifficulty.HasFilter || criteria.OverallDifficulty.IsInRange(BeatmapInfo.Difficulty.OverallDifficulty); match &= !criteria.Length.HasFilter || criteria.Length.IsInRange(BeatmapInfo.Length); - match &= !criteria.LastPlayed.HasFilter || criteria.LastPlayed.IsInRange(BeatmapInfo.LastPlayed); + match &= !criteria.LastPlayed.HasFilter || criteria.LastPlayed.IsInRange(BeatmapInfo.LastPlayed ?? DateTimeOffset.MinValue); match &= !criteria.BPM.HasFilter || criteria.BPM.IsInRange(BeatmapInfo.BPM); match &= !criteria.BeatDivisor.HasFilter || criteria.BeatDivisor.IsInRange(BeatmapInfo.BeatDivisor); diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 6b6b2f04a9..38040c2f79 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -381,7 +381,7 @@ namespace osu.Game.Screens.Select GroupCollection? match = null; match ??= tryMatchRegex(val, @"^((?\d+):)?(?\d+):(?\d+)$"); - match ??= tryMatchRegex(val, @"^((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); + match ??= tryMatchRegex(val, @"^((?\d+(\.\d+)?)d)?((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); match ??= tryMatchRegex(val, @"^(?\d+(\.\d+)?)$"); if (match == null) @@ -403,7 +403,7 @@ namespace osu.Game.Screens.Select for (int i = 0; i < parts.Count; i++) { string part = parts[i]; - string partNoUnit = part.TrimEnd('m', 's', 'h', 'd') ; + string partNoUnit = part.TrimEnd('m', 's', 'h', 'd'); if (!tryParseDoubleWithPoint(partNoUnit, out double length)) return false; @@ -417,7 +417,16 @@ namespace osu.Game.Screens.Select minScale = Math.Min(minScale, scale); } - return tryUpdateCriteriaRange(ref criteria.LastPlayed, op, totalLength, minScale / 2.0); + totalLength += minScale / 2; + + // Limits the date to ~2000 years compared to now + // Might want to do it differently before 4000 A.C. + double limit = 86400000; + limit *= 365 * 2000; + totalLength = Math.Min(totalLength, limit); + + DateTimeOffset dateTimeOffset = DateTimeOffset.Now; + return tryUpdateCriteriaRange(ref criteria.LastPlayed, op, dateTimeOffset.AddMilliseconds(-totalLength)); } } } From 6dead81d211a760e185ff0248a080454e6729197 Mon Sep 17 00:00:00 2001 From: Elvendir Date: Sun, 19 Mar 2023 18:43:17 +0100 Subject: [PATCH 003/915] Generalized tryUpdateLastPlayedRange to tryUpdateDateRange and Added tests --- .../Filtering/FilterQueryParserTest.cs | 82 ++++++++++++++ osu.Game/Screens/Select/FilterQueryParser.cs | 107 ++++++++++++------ 2 files changed, 152 insertions(+), 37 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index da32edb8fb..9460228644 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -316,5 +316,87 @@ namespace osu.Game.Tests.NonVisual.Filtering return false; } } + + //Date criteria testing + + private static readonly object[] correct_date_query_examples = + { + new object[] { "600" }, + new object[] { "120:120" }, + new object[] { "48:0:0" }, + new object[] { "0.5s" }, + new object[] { "120m" }, + new object[] { "48h120s" }, + new object[] { "10y24M" }, + new object[] { "10y60d120s" }, + new object[] { "0.1y0.1M2d" }, + new object[] { "0.99y0.99M2d" } + }; + + [Test] + [TestCaseSource(nameof(correct_date_query_examples))] + public void TestValidDateQueries(string dateQuery) + { + string query = $"played={dateQuery} time"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual(true, filterCriteria.LastPlayed.HasFilter); + } + + private static readonly object[] incorrect_date_query_examples = + { + new object[] { "7m27" }, + new object[] { "7m7m7m" }, + new object[] { "5s6m" }, + new object[] { "7d7y" }, + new object[] { ":0" }, + new object[] { "0:3:" }, + new object[] { "\"three days\"" } + }; + + [Test] + [TestCaseSource(nameof(incorrect_date_query_examples))] + public void TestInvalidDateQueries(string dateQuery) + { + string query = $"played={dateQuery} time"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual(false, filterCriteria.LastPlayed.HasFilter); + } + + private static readonly object[] list_operators = + { + new object[] { "=", false, false, true, true }, + new object[] { ":", false, false, true, true }, + new object[] { "<", false, true, false, false }, + new object[] { "<=", false, true, true, false }, + new object[] { "<:", false, true, true, false }, + new object[] { ">", true, false, false, false }, + new object[] { ">=", true, false, false, true }, + new object[] { ">:", true, false, false, true } + }; + + [Test] + [TestCaseSource(nameof(list_operators))] + public void TestComparisonDateQueries(string ope, bool minIsNull, bool maxIsNull, bool isLowerInclusive, bool isUpperInclusive) + { + string query = $"played{ope}50"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual(isLowerInclusive, filterCriteria.LastPlayed.IsLowerInclusive); + Assert.AreEqual(isUpperInclusive, filterCriteria.LastPlayed.IsUpperInclusive); + Assert.AreEqual(maxIsNull, filterCriteria.LastPlayed.Max == null); + Assert.AreEqual(minIsNull, filterCriteria.LastPlayed.Min == null); + } + + [Test] + public void TestOutofrangeDateQuery() + { + const string query = "played=10000y"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual(true, filterCriteria.LastPlayed.HasFilter); + Assert.AreEqual(DateTimeOffset.MinValue.AddMilliseconds(1), filterCriteria.LastPlayed.Min); + } } } diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 38040c2f79..f66f1bcd1d 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Select case "played": case "lastplayed": - return tryUpdateLastPlayedRange(criteria, op, value); + return tryUpdateDateRange(ref criteria.LastPlayed, op, value); case "divisor": return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt); @@ -374,59 +374,92 @@ namespace osu.Game.Screens.Select return tryUpdateCriteriaRange(ref criteria.Length, op, totalLength, minScale / 2.0); } - private static bool tryUpdateLastPlayedRange(FilterCriteria criteria, Operator op, string val) + private static bool tryUpdateDateRange(ref FilterCriteria.OptionalRange dateRange, Operator op, string val) { - List parts = new List(); - GroupCollection? match = null; match ??= tryMatchRegex(val, @"^((?\d+):)?(?\d+):(?\d+)$"); - match ??= tryMatchRegex(val, @"^((?\d+(\.\d+)?)d)?((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); + match ??= tryMatchRegex(val, @"^((?\d+(\.\d+)?)y)?((?\d+(\.\d+)?)M)?((?\d+(\.\d+)?)d)?((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); match ??= tryMatchRegex(val, @"^(?\d+(\.\d+)?)$"); if (match == null) return false; - if (match["seconds"].Success) - parts.Add(match["seconds"].Value + "s"); - if (match["minutes"].Success) - parts.Add(match["minutes"].Value + "m"); - if (match["hours"].Success) - parts.Add(match["hours"].Value + "h"); - if (match["days"].Success) - parts.Add(match["days"].Value + "d"); + DateTimeOffset dateTimeOffset = DateTimeOffset.Now; - - double totalLength = 0; - int minScale = 86400000; - - for (int i = 0; i < parts.Count; i++) + try { - string part = parts[i]; - string partNoUnit = part.TrimEnd('m', 's', 'h', 'd'); - if (!tryParseDoubleWithPoint(partNoUnit, out double length)) - return false; + List keys = new List { "seconds", "minutes", "hours", "days", "months", "years" }; - if (i != parts.Count - 1 && length >= 60) - return false; - if (i != 0 && partNoUnit.Contains('.')) - return false; + foreach (string key in keys) + { + if (match[key].Success) + { + if (!tryParseDoubleWithPoint(match[key].Value, out double length)) + return false; - int scale = getLengthScale(part); - totalLength += length * scale; - minScale = Math.Min(minScale, scale); + switch (key) + { + case "seconds": + dateTimeOffset = dateTimeOffset.AddSeconds(-length); + break; + + case "minutes": + dateTimeOffset = dateTimeOffset.AddMinutes(-length); + break; + + case "hours": + dateTimeOffset = dateTimeOffset.AddHours(-length); + break; + + case "days": + dateTimeOffset = dateTimeOffset.AddDays(-length); + break; + + case "months": + dateTimeOffset = dateTimeOffset.AddMonths(-(int)Math.Round(length)); + break; + + case "years": + dateTimeOffset = dateTimeOffset.AddYears(-(int)Math.Round(length)); + break; + } + } + } + } + // If DateTime to compare is out-scope put it to Min + catch (Exception) + { + dateTimeOffset = DateTimeOffset.MinValue; + dateTimeOffset = dateTimeOffset.AddMilliseconds(1); } - totalLength += minScale / 2; + return tryUpdateCriteriaRange(ref dateRange, invert(op), dateTimeOffset); + } - // Limits the date to ~2000 years compared to now - // Might want to do it differently before 4000 A.C. - double limit = 86400000; - limit *= 365 * 2000; - totalLength = Math.Min(totalLength, limit); + // Function to reverse an Operator + private static Operator invert(Operator ope) + { + switch (ope) + { + default: + return Operator.Equal; - DateTimeOffset dateTimeOffset = DateTimeOffset.Now; - return tryUpdateCriteriaRange(ref criteria.LastPlayed, op, dateTimeOffset.AddMilliseconds(-totalLength)); + case Operator.Equal: + return Operator.Equal; + + case Operator.Greater: + return Operator.Less; + + case Operator.GreaterOrEqual: + return Operator.LessOrEqual; + + case Operator.Less: + return Operator.Greater; + + case Operator.LessOrEqual: + return Operator.GreaterOrEqual; + } } } } From 4b053b47852ea46ad104156d81a84e3bdaaf3b04 Mon Sep 17 00:00:00 2001 From: Elvendir Date: Sat, 1 Apr 2023 22:58:25 +0200 Subject: [PATCH 004/915] changed regex match to be inline with standard --- .../NonVisual/Filtering/FilterQueryParserTest.cs | 3 +-- osu.Game/Screens/Select/FilterQueryParser.cs | 9 +++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 9460228644..b0cc9146d2 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -322,8 +322,6 @@ namespace osu.Game.Tests.NonVisual.Filtering private static readonly object[] correct_date_query_examples = { new object[] { "600" }, - new object[] { "120:120" }, - new object[] { "48:0:0" }, new object[] { "0.5s" }, new object[] { "120m" }, new object[] { "48h120s" }, @@ -350,6 +348,7 @@ namespace osu.Game.Tests.NonVisual.Filtering new object[] { "5s6m" }, new object[] { "7d7y" }, new object[] { ":0" }, + new object[] { "0:3:6" }, new object[] { "0:3:" }, new object[] { "\"three days\"" } }; diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index f66f1bcd1d..f66b8fd377 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -378,9 +378,8 @@ namespace osu.Game.Screens.Select { GroupCollection? match = null; - match ??= tryMatchRegex(val, @"^((?\d+):)?(?\d+):(?\d+)$"); match ??= tryMatchRegex(val, @"^((?\d+(\.\d+)?)y)?((?\d+(\.\d+)?)M)?((?\d+(\.\d+)?)d)?((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); - match ??= tryMatchRegex(val, @"^(?\d+(\.\d+)?)$"); + match ??= tryMatchRegex(val, @"^(?\d+(\.\d+)?)$"); if (match == null) return false; @@ -417,11 +416,13 @@ namespace osu.Game.Screens.Select break; case "months": - dateTimeOffset = dateTimeOffset.AddMonths(-(int)Math.Round(length)); + dateTimeOffset = dateTimeOffset.AddMonths(-(int)Math.Floor(length)); + dateTimeOffset = dateTimeOffset.AddDays(-30 * (length - Math.Floor(length))); break; case "years": - dateTimeOffset = dateTimeOffset.AddYears(-(int)Math.Round(length)); + dateTimeOffset = dateTimeOffset.AddYears(-(int)Math.Floor(length)); + dateTimeOffset = dateTimeOffset.AddDays(-365 * (length - Math.Floor(length))); break; } } From 52adb99fe5fe4f7f7ea756f0723354f17904203e Mon Sep 17 00:00:00 2001 From: Elvendir <39671719+Elvendir@users.noreply.github.com> Date: Tue, 4 Apr 2023 19:29:37 +0200 Subject: [PATCH 005/915] Update osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index b0cc9146d2..627b44dcd7 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -317,7 +317,6 @@ namespace osu.Game.Tests.NonVisual.Filtering } } - //Date criteria testing private static readonly object[] correct_date_query_examples = { From d6c6507578a0fd3a7a8a502c15febd91b0123069 Mon Sep 17 00:00:00 2001 From: Elvendir <39671719+Elvendir@users.noreply.github.com> Date: Tue, 4 Apr 2023 19:30:13 +0200 Subject: [PATCH 006/915] Update osu.Game/Screens/Select/FilterQueryParser.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Screens/Select/FilterQueryParser.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index f66b8fd377..9582694248 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -428,8 +428,7 @@ namespace osu.Game.Screens.Select } } } - // If DateTime to compare is out-scope put it to Min - catch (Exception) + catch (ArgumentOutOfRangeException) { dateTimeOffset = DateTimeOffset.MinValue; dateTimeOffset = dateTimeOffset.AddMilliseconds(1); From 0c1d6eb89465066285668b619bc73a54c9fa964c Mon Sep 17 00:00:00 2001 From: Elvendir Date: Wed, 5 Apr 2023 11:42:39 +0200 Subject: [PATCH 007/915] - rewrote upper and lower bound tests - removed equality in tests --- .../Filtering/FilterQueryParserTest.cs | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 627b44dcd7..c1678f14a6 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -317,7 +317,6 @@ namespace osu.Game.Tests.NonVisual.Filtering } } - private static readonly object[] correct_date_query_examples = { new object[] { "600" }, @@ -334,7 +333,7 @@ namespace osu.Game.Tests.NonVisual.Filtering [TestCaseSource(nameof(correct_date_query_examples))] public void TestValidDateQueries(string dateQuery) { - string query = $"played={dateQuery} time"; + string query = $"played<{dateQuery} time"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual(true, filterCriteria.LastPlayed.HasFilter); @@ -342,11 +341,11 @@ namespace osu.Game.Tests.NonVisual.Filtering private static readonly object[] incorrect_date_query_examples = { + new object[] { ".5s" }, new object[] { "7m27" }, new object[] { "7m7m7m" }, new object[] { "5s6m" }, new object[] { "7d7y" }, - new object[] { ":0" }, new object[] { "0:3:6" }, new object[] { "0:3:" }, new object[] { "\"three days\"" } @@ -356,41 +355,36 @@ namespace osu.Game.Tests.NonVisual.Filtering [TestCaseSource(nameof(incorrect_date_query_examples))] public void TestInvalidDateQueries(string dateQuery) { - string query = $"played={dateQuery} time"; + string query = $"played<{dateQuery} time"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual(false, filterCriteria.LastPlayed.HasFilter); } - private static readonly object[] list_operators = - { - new object[] { "=", false, false, true, true }, - new object[] { ":", false, false, true, true }, - new object[] { "<", false, true, false, false }, - new object[] { "<=", false, true, true, false }, - new object[] { "<:", false, true, true, false }, - new object[] { ">", true, false, false, false }, - new object[] { ">=", true, false, false, true }, - new object[] { ">:", true, false, false, true } - }; - [Test] - [TestCaseSource(nameof(list_operators))] - public void TestComparisonDateQueries(string ope, bool minIsNull, bool maxIsNull, bool isLowerInclusive, bool isUpperInclusive) + public void TestGreaterDateQuery() { - string query = $"played{ope}50"; + const string query = "played>50"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); - Assert.AreEqual(isLowerInclusive, filterCriteria.LastPlayed.IsLowerInclusive); - Assert.AreEqual(isUpperInclusive, filterCriteria.LastPlayed.IsUpperInclusive); - Assert.AreEqual(maxIsNull, filterCriteria.LastPlayed.Max == null); - Assert.AreEqual(minIsNull, filterCriteria.LastPlayed.Min == null); + Assert.AreEqual(false, filterCriteria.LastPlayed.Max == null); + Assert.AreEqual(true, filterCriteria.LastPlayed.Min == null); + } + + [Test] + public void TestLowerDateQuery() + { + const string query = "played<50"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual(true, filterCriteria.LastPlayed.Max == null); + Assert.AreEqual(false, filterCriteria.LastPlayed.Min == null); } [Test] public void TestOutofrangeDateQuery() { - const string query = "played=10000y"; + const string query = "played<10000y"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual(true, filterCriteria.LastPlayed.HasFilter); From df170517a85ea1949d20b6df1043143ac028ffec Mon Sep 17 00:00:00 2001 From: Elvendir Date: Wed, 5 Apr 2023 11:59:31 +0200 Subject: [PATCH 008/915] -renamed function inverse() to reverseInequalityOperator() for clarity -changed default case of reverseInequalityOperator() to out of range exception --- osu.Game/Screens/Select/FilterQueryParser.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 9582694248..bd4c29e457 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -434,16 +434,16 @@ namespace osu.Game.Screens.Select dateTimeOffset = dateTimeOffset.AddMilliseconds(1); } - return tryUpdateCriteriaRange(ref dateRange, invert(op), dateTimeOffset); + return tryUpdateCriteriaRange(ref dateRange, reverseInequalityOperator(op), dateTimeOffset); } // Function to reverse an Operator - private static Operator invert(Operator ope) + private static Operator reverseInequalityOperator(Operator ope) { switch (ope) { default: - return Operator.Equal; + throw new ArgumentOutOfRangeException(nameof(ope), $"Unsupported operator {ope}"); case Operator.Equal: return Operator.Equal; From c2f225f0253030ea03e710f1647da26f6b106377 Mon Sep 17 00:00:00 2001 From: Elvendir Date: Wed, 5 Apr 2023 21:25:58 +0200 Subject: [PATCH 009/915] Made Operator.Equal not parse for date filter and added corresponding test --- .../NonVisual/Filtering/FilterQueryParserTest.cs | 9 +++++++++ osu.Game/Screens/Select/FilterQueryParser.cs | 3 +++ 2 files changed, 12 insertions(+) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index c1678f14a6..450e6bdde7 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -381,6 +381,15 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.AreEqual(false, filterCriteria.LastPlayed.Min == null); } + [Test] + public void TestEqualDateQuery() + { + const string query = "played=50"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.AreEqual(false, filterCriteria.LastPlayed.HasFilter); + } + [Test] public void TestOutofrangeDateQuery() { diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index bd4c29e457..70893c188d 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -376,6 +376,9 @@ namespace osu.Game.Screens.Select private static bool tryUpdateDateRange(ref FilterCriteria.OptionalRange dateRange, Operator op, string val) { + if (op == Operator.Equal) + return false; + GroupCollection? match = null; match ??= tryMatchRegex(val, @"^((?\d+(\.\d+)?)y)?((?\d+(\.\d+)?)M)?((?\d+(\.\d+)?)d)?((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); From 928145cdeb3b523833ed6b5f3f85c830d91f4dc8 Mon Sep 17 00:00:00 2001 From: Elvendir Date: Wed, 5 Apr 2023 22:12:15 +0200 Subject: [PATCH 010/915] Enforce integer value before y and M Change impacted Tests --- .../NonVisual/Filtering/FilterQueryParserTest.cs | 8 +++++--- osu.Game/Screens/Select/FilterQueryParser.cs | 12 ++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 450e6bdde7..78b428e7c0 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -325,8 +325,8 @@ namespace osu.Game.Tests.NonVisual.Filtering new object[] { "48h120s" }, new object[] { "10y24M" }, new object[] { "10y60d120s" }, - new object[] { "0.1y0.1M2d" }, - new object[] { "0.99y0.99M2d" } + new object[] { "0y0M2d" }, + new object[] { "1y1M2d" } }; [Test] @@ -348,7 +348,9 @@ namespace osu.Game.Tests.NonVisual.Filtering new object[] { "7d7y" }, new object[] { "0:3:6" }, new object[] { "0:3:" }, - new object[] { "\"three days\"" } + new object[] { "\"three days\"" }, + new object[] { "0.1y0.1M2d" }, + new object[] { "0.99y0.99M2d" } }; [Test] diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 70893c188d..b49f0ba057 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -419,13 +419,17 @@ namespace osu.Game.Screens.Select break; case "months": - dateTimeOffset = dateTimeOffset.AddMonths(-(int)Math.Floor(length)); - dateTimeOffset = dateTimeOffset.AddDays(-30 * (length - Math.Floor(length))); + if (match[key].Value.Contains('.')) + return false; + + dateTimeOffset = dateTimeOffset.AddMonths(-(int)length); break; case "years": - dateTimeOffset = dateTimeOffset.AddYears(-(int)Math.Floor(length)); - dateTimeOffset = dateTimeOffset.AddDays(-365 * (length - Math.Floor(length))); + if (match[key].Value.Contains('.')) + return false; + + dateTimeOffset = dateTimeOffset.AddYears(-(int)length); break; } } From 8e156fdb5102af8cd71aaac32d3c36b3c018d382 Mon Sep 17 00:00:00 2001 From: Elvendir Date: Fri, 7 Apr 2023 00:29:46 +0200 Subject: [PATCH 011/915] Enforce integer through regex match instead --- osu.Game/Screens/Select/FilterQueryParser.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index b49f0ba057..348f663b8e 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -381,7 +381,7 @@ namespace osu.Game.Screens.Select GroupCollection? match = null; - match ??= tryMatchRegex(val, @"^((?\d+(\.\d+)?)y)?((?\d+(\.\d+)?)M)?((?\d+(\.\d+)?)d)?((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); + match ??= tryMatchRegex(val, @"^((?\d+)y)?((?\d+)M)?((?\d+(\.\d+)?)d)?((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$"); match ??= tryMatchRegex(val, @"^(?\d+(\.\d+)?)$"); if (match == null) @@ -419,16 +419,10 @@ namespace osu.Game.Screens.Select break; case "months": - if (match[key].Value.Contains('.')) - return false; - dateTimeOffset = dateTimeOffset.AddMonths(-(int)length); break; case "years": - if (match[key].Value.Contains('.')) - return false; - dateTimeOffset = dateTimeOffset.AddYears(-(int)length); break; } From 7c8c6790d017216cd65ad9fd3f3bc35e6231c6cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 13:10:59 +0200 Subject: [PATCH 012/915] Refactor metadata lookup to streamline online metadata application logic --- osu.Game/Beatmaps/APIBeatmapMetadataSource.cs | 78 ++++++ .../Beatmaps/BeatmapUpdaterMetadataLookup.cs | 251 +++--------------- .../Beatmaps/IOnlineBeatmapMetadataSource.cs | 26 ++ .../LocalCachedBeatmapMetadataSource.cs | 176 ++++++++++++ osu.Game/Beatmaps/OnlineBeatmapMetadata.cs | 61 +++++ 5 files changed, 382 insertions(+), 210 deletions(-) create mode 100644 osu.Game/Beatmaps/APIBeatmapMetadataSource.cs create mode 100644 osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs create mode 100644 osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs create mode 100644 osu.Game/Beatmaps/OnlineBeatmapMetadata.cs diff --git a/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs b/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs new file mode 100644 index 0000000000..e1b01aaac5 --- /dev/null +++ b/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs @@ -0,0 +1,78 @@ +// 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.Diagnostics; +using osu.Game.Database; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; + +namespace osu.Game.Beatmaps +{ + public class APIBeatmapMetadataSource : IOnlineBeatmapMetadataSource + { + private readonly IAPIProvider api; + + public APIBeatmapMetadataSource(IAPIProvider api) + { + this.api = api; + } + + public bool Available => api.State.Value == APIState.Online; + + public OnlineBeatmapMetadata? Lookup(BeatmapInfo beatmapInfo) + { + if (!Available) + return null; + + Debug.Assert(beatmapInfo.BeatmapSet != null); + + var req = new GetBeatmapRequest(beatmapInfo); + + try + { + // intentionally blocking to limit web request concurrency + api.Perform(req); + + if (req.CompletionState == APIRequestCompletionState.Failed) + { + logForModel(beatmapInfo.BeatmapSet, $@"Online retrieval failed for {beatmapInfo}"); + return null; + } + + var res = req.Response; + + if (res != null) + { + logForModel(beatmapInfo.BeatmapSet, $@"Online retrieval mapped {beatmapInfo} to {res.OnlineBeatmapSetID} / {res.OnlineID}."); + + return new OnlineBeatmapMetadata + { + BeatmapID = res.OnlineID, + BeatmapSetID = res.OnlineBeatmapSetID, + AuthorID = res.AuthorID, + BeatmapStatus = res.Status, + BeatmapSetStatus = res.BeatmapSet?.Status, + DateRanked = res.BeatmapSet?.Ranked, + DateSubmitted = res.BeatmapSet?.Submitted, + MD5Hash = res.MD5Hash, + LastUpdated = res.LastUpdated + }; + } + } + catch (Exception e) + { + logForModel(beatmapInfo.BeatmapSet, $@"Online retrieval failed for {beatmapInfo} ({e.Message})"); + } + + return null; + } + + private void logForModel(BeatmapSetInfo set, string message) => + RealmArchiveModelImporter.LogForModel(set, $@"[{nameof(APIBeatmapMetadataSource)}] {message}"); + + public void Dispose() + { + } + } +} diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index fac91c23f5..b326e7ad1c 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -1,62 +1,31 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Diagnostics; -using System.IO; using System.Linq; -using System.Threading.Tasks; -using Microsoft.Data.Sqlite; -using osu.Framework.Development; -using osu.Framework.IO.Network; -using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Game.Database; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using SharpCompress.Compressors; -using SharpCompress.Compressors.BZip2; -using SQLitePCL; namespace osu.Game.Beatmaps { /// /// A component which handles population of online IDs for beatmaps using a two part lookup procedure. /// - /// - /// On creating the component, a copy of a database containing metadata for a large subset of beatmaps (stored to ) will be downloaded if not already present locally. - /// This will always be checked before doing a second online query to get required metadata. - /// public class BeatmapUpdaterMetadataLookup : IDisposable { - private readonly IAPIProvider api; - private readonly Storage storage; - - private FileWebRequest cacheDownloadRequest; - - private const string cache_database_name = "online.db"; + private readonly IOnlineBeatmapMetadataSource apiMetadataSource; + private readonly IOnlineBeatmapMetadataSource localCachedMetadataSource; public BeatmapUpdaterMetadataLookup(IAPIProvider api, Storage storage) + : this(new APIBeatmapMetadataSource(api), new LocalCachedBeatmapMetadataSource(storage)) { - try - { - // required to initialise native SQLite libraries on some platforms. - Batteries_V2.Init(); - raw.sqlite3_config(2 /*SQLITE_CONFIG_MULTITHREAD*/); - } - catch - { - // may fail if platform not supported. - } + } - this.api = api; - this.storage = storage; - - // avoid downloading / using cache for unit tests. - if (!DebugUtils.IsNUnitRunning && !storage.Exists(cache_database_name)) - prepareLocalCache(); + internal BeatmapUpdaterMetadataLookup(IOnlineBeatmapMetadataSource apiMetadataSource, IOnlineBeatmapMetadataSource localCachedMetadataSource) + { + this.apiMetadataSource = apiMetadataSource; + this.localCachedMetadataSource = localCachedMetadataSource; } /// @@ -69,196 +38,57 @@ namespace osu.Game.Beatmaps /// Whether metadata from an online source should be preferred. If true, the local cache will be skipped to ensure the freshest data state possible. public void Update(BeatmapSetInfo beatmapSet, bool preferOnlineFetch) { - foreach (var b in beatmapSet.Beatmaps) - lookup(beatmapSet, b, preferOnlineFetch); - } - - private void lookup(BeatmapSetInfo set, BeatmapInfo beatmapInfo, bool preferOnlineFetch) - { - bool apiAvailable = api?.State.Value == APIState.Online; - - bool useLocalCache = !apiAvailable || !preferOnlineFetch; - - if (useLocalCache && checkLocalCache(set, beatmapInfo)) - return; - - if (!apiAvailable) - return; - - var req = new GetBeatmapRequest(beatmapInfo); - - try + foreach (var beatmapInfo in beatmapSet.Beatmaps) { - // intentionally blocking to limit web request concurrency - api.Perform(req); + var res = lookup(beatmapSet, beatmapInfo, preferOnlineFetch); - if (req.CompletionState == APIRequestCompletionState.Failed) + if (res == null) { - logForModel(set, $"Online retrieval failed for {beatmapInfo}"); beatmapInfo.ResetOnlineInfo(); - return; + continue; } - var res = req.Response; + beatmapInfo.OnlineID = res.BeatmapID; + beatmapInfo.OnlineMD5Hash = res.MD5Hash; + beatmapInfo.LastOnlineUpdate = res.LastUpdated; - if (res != null) + Debug.Assert(beatmapInfo.BeatmapSet != null); + beatmapInfo.BeatmapSet.OnlineID = res.BeatmapSetID; + + // Some metadata should only be applied if there's no local changes. + if (shouldSaveOnlineMetadata(beatmapInfo)) { - beatmapInfo.OnlineID = res.OnlineID; - beatmapInfo.OnlineMD5Hash = res.MD5Hash; - beatmapInfo.LastOnlineUpdate = res.LastUpdated; - - Debug.Assert(beatmapInfo.BeatmapSet != null); - beatmapInfo.BeatmapSet.OnlineID = res.OnlineBeatmapSetID; - - // Some metadata should only be applied if there's no local changes. - if (shouldSaveOnlineMetadata(beatmapInfo)) - { - beatmapInfo.Status = res.Status; - beatmapInfo.Metadata.Author.OnlineID = res.AuthorID; - } - - if (beatmapInfo.BeatmapSet.Beatmaps.All(shouldSaveOnlineMetadata)) - { - beatmapInfo.BeatmapSet.Status = res.BeatmapSet?.Status ?? BeatmapOnlineStatus.None; - beatmapInfo.BeatmapSet.DateRanked = res.BeatmapSet?.Ranked; - beatmapInfo.BeatmapSet.DateSubmitted = res.BeatmapSet?.Submitted; - } - - logForModel(set, $"Online retrieval mapped {beatmapInfo} to {res.OnlineBeatmapSetID} / {res.OnlineID}."); + beatmapInfo.Status = res.BeatmapStatus; + beatmapInfo.Metadata.Author.OnlineID = res.AuthorID; + } + + if (beatmapInfo.BeatmapSet.Beatmaps.All(shouldSaveOnlineMetadata)) + { + beatmapInfo.BeatmapSet.Status = res.BeatmapSetStatus ?? BeatmapOnlineStatus.None; + beatmapInfo.BeatmapSet.DateRanked = res.DateRanked; + beatmapInfo.BeatmapSet.DateSubmitted = res.DateSubmitted; } - } - catch (Exception e) - { - logForModel(set, $"Online retrieval failed for {beatmapInfo} ({e.Message})"); - beatmapInfo.ResetOnlineInfo(); } } - private void prepareLocalCache() + private OnlineBeatmapMetadata? lookup(BeatmapSetInfo set, BeatmapInfo beatmapInfo, bool preferOnlineFetch) { - string cacheFilePath = storage.GetFullPath(cache_database_name); - string compressedCacheFilePath = $"{cacheFilePath}.bz2"; + OnlineBeatmapMetadata? result = null; - cacheDownloadRequest = new FileWebRequest(compressedCacheFilePath, $"https://assets.ppy.sh/client-resources/{cache_database_name}.bz2?{DateTimeOffset.UtcNow:yyyyMMdd}"); + bool useLocalCache = !apiMetadataSource.Available || !preferOnlineFetch; - cacheDownloadRequest.Failed += ex => - { - File.Delete(compressedCacheFilePath); - File.Delete(cacheFilePath); + if (useLocalCache) + result = localCachedMetadataSource.Lookup(beatmapInfo); - Logger.Log($"{nameof(BeatmapUpdaterMetadataLookup)}'s online cache download failed: {ex}", LoggingTarget.Database); - }; + if (result != null) + return result; - cacheDownloadRequest.Finished += () => - { - try - { - using (var stream = File.OpenRead(cacheDownloadRequest.Filename)) - using (var outStream = File.OpenWrite(cacheFilePath)) - using (var bz2 = new BZip2Stream(stream, CompressionMode.Decompress, false)) - bz2.CopyTo(outStream); + if (apiMetadataSource.Available) + result = apiMetadataSource.Lookup(beatmapInfo); - // set to null on completion to allow lookups to begin using the new source - cacheDownloadRequest = null; - } - catch (Exception ex) - { - Logger.Log($"{nameof(BeatmapUpdaterMetadataLookup)}'s online cache extraction failed: {ex}", LoggingTarget.Database); - File.Delete(cacheFilePath); - } - finally - { - File.Delete(compressedCacheFilePath); - } - }; - - Task.Run(async () => - { - try - { - await cacheDownloadRequest.PerformAsync().ConfigureAwait(false); - } - catch - { - // Prevent throwing unobserved exceptions, as they will be logged from the network request to the log file anyway. - } - }); + return result; } - private bool checkLocalCache(BeatmapSetInfo set, BeatmapInfo beatmapInfo) - { - // download is in progress (or was, and failed). - if (cacheDownloadRequest != null) - return false; - - // database is unavailable. - if (!storage.Exists(cache_database_name)) - return false; - - if (string.IsNullOrEmpty(beatmapInfo.MD5Hash) - && string.IsNullOrEmpty(beatmapInfo.Path) - && beatmapInfo.OnlineID <= 0) - return false; - - try - { - using (var db = new SqliteConnection(string.Concat("Data Source=", storage.GetFullPath($@"{"online.db"}", true)))) - { - db.Open(); - - using (var cmd = db.CreateCommand()) - { - cmd.CommandText = - "SELECT beatmapset_id, beatmap_id, approved, user_id, checksum, last_update FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineID OR filename = @Path"; - - cmd.Parameters.Add(new SqliteParameter("@MD5Hash", beatmapInfo.MD5Hash)); - cmd.Parameters.Add(new SqliteParameter("@OnlineID", beatmapInfo.OnlineID)); - cmd.Parameters.Add(new SqliteParameter("@Path", beatmapInfo.Path)); - - using (var reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - var status = (BeatmapOnlineStatus)reader.GetByte(2); - - // Some metadata should only be applied if there's no local changes. - if (shouldSaveOnlineMetadata(beatmapInfo)) - { - beatmapInfo.Status = status; - beatmapInfo.Metadata.Author.OnlineID = reader.GetInt32(3); - } - - // TODO: DateSubmitted and DateRanked are not provided by local cache. - beatmapInfo.OnlineID = reader.GetInt32(1); - beatmapInfo.OnlineMD5Hash = reader.GetString(4); - beatmapInfo.LastOnlineUpdate = reader.GetDateTimeOffset(5); - - Debug.Assert(beatmapInfo.BeatmapSet != null); - beatmapInfo.BeatmapSet.OnlineID = reader.GetInt32(0); - - if (beatmapInfo.BeatmapSet.Beatmaps.All(shouldSaveOnlineMetadata)) - { - beatmapInfo.BeatmapSet.Status = status; - } - - logForModel(set, $"Cached local retrieval for {beatmapInfo}."); - return true; - } - } - } - } - } - catch (Exception ex) - { - logForModel(set, $"Cached local retrieval for {beatmapInfo} failed with {ex}."); - } - - return false; - } - - private void logForModel(BeatmapSetInfo set, string message) => - RealmArchiveModelImporter.LogForModel(set, $"[{nameof(BeatmapUpdaterMetadataLookup)}] {message}"); - /// /// Check whether the provided beatmap is in a state where online "ranked" status metadata should be saved against it. /// Handles the case where a user may have locally modified a beatmap in the editor and expects the local status to stick. @@ -267,7 +97,8 @@ namespace osu.Game.Beatmaps public void Dispose() { - cacheDownloadRequest?.Dispose(); + apiMetadataSource.Dispose(); + localCachedMetadataSource.Dispose(); } } } diff --git a/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs b/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs new file mode 100644 index 0000000000..753462d493 --- /dev/null +++ b/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Beatmaps +{ + /// + /// Unifying interface for sources of online beatmap metadata. + /// + public interface IOnlineBeatmapMetadataSource : IDisposable + { + /// + /// Whether this source can currently service lookups. + /// + bool Available { get; } + + /// + /// Looks up the online metadata for the supplied . + /// + /// + /// An instance if the lookup is successful, or if the lookup failed. + /// + OnlineBeatmapMetadata? Lookup(BeatmapInfo beatmapInfo); + } +} diff --git a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs new file mode 100644 index 0000000000..435242aeab --- /dev/null +++ b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs @@ -0,0 +1,176 @@ +// 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.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Data.Sqlite; +using osu.Framework.Development; +using osu.Framework.IO.Network; +using osu.Framework.Logging; +using osu.Framework.Platform; +using osu.Game.Database; +using SharpCompress.Compressors; +using SharpCompress.Compressors.BZip2; +using SQLitePCL; + +namespace osu.Game.Beatmaps +{ + /// + /// + /// + /// + /// On creating the component, a copy of a database containing metadata for a large subset of beatmaps (stored to ) will be downloaded if not already present locally. + /// + public class LocalCachedBeatmapMetadataSource : IOnlineBeatmapMetadataSource + { + private readonly Storage storage; + + private FileWebRequest? cacheDownloadRequest; + + private const string cache_database_name = @"online.db"; + + public LocalCachedBeatmapMetadataSource(Storage storage) + { + try + { + // required to initialise native SQLite libraries on some platforms. + Batteries_V2.Init(); + raw.sqlite3_config(2 /*SQLITE_CONFIG_MULTITHREAD*/); + } + catch + { + // may fail if platform not supported. + } + + this.storage = storage; + + // avoid downloading / using cache for unit tests. + if (!DebugUtils.IsNUnitRunning && !storage.Exists(cache_database_name)) + prepareLocalCache(); + } + + private void prepareLocalCache() + { + string cacheFilePath = storage.GetFullPath(cache_database_name); + string compressedCacheFilePath = $@"{cacheFilePath}.bz2"; + + cacheDownloadRequest = new FileWebRequest(compressedCacheFilePath, $@"https://assets.ppy.sh/client-resources/{cache_database_name}.bz2?{DateTimeOffset.UtcNow:yyyyMMdd}"); + + cacheDownloadRequest.Failed += ex => + { + File.Delete(compressedCacheFilePath); + File.Delete(cacheFilePath); + + Logger.Log($@"{nameof(BeatmapUpdaterMetadataLookup)}'s online cache download failed: {ex}", LoggingTarget.Database); + }; + + cacheDownloadRequest.Finished += () => + { + try + { + using (var stream = File.OpenRead(cacheDownloadRequest.Filename)) + using (var outStream = File.OpenWrite(cacheFilePath)) + using (var bz2 = new BZip2Stream(stream, CompressionMode.Decompress, false)) + bz2.CopyTo(outStream); + + // set to null on completion to allow lookups to begin using the new source + cacheDownloadRequest = null; + } + catch (Exception ex) + { + Logger.Log($@"{nameof(LocalCachedBeatmapMetadataSource)}'s online cache extraction failed: {ex}", LoggingTarget.Database); + File.Delete(cacheFilePath); + } + finally + { + File.Delete(compressedCacheFilePath); + } + }; + + Task.Run(async () => + { + try + { + await cacheDownloadRequest.PerformAsync().ConfigureAwait(false); + } + catch + { + // Prevent throwing unobserved exceptions, as they will be logged from the network request to the log file anyway. + } + }); + } + + public bool Available => + // no download in progress. + cacheDownloadRequest == null + // cached database exists on disk. + && storage.Exists(cache_database_name); + + public OnlineBeatmapMetadata? Lookup(BeatmapInfo beatmapInfo) + { + if (!Available) + return null; + + if (string.IsNullOrEmpty(beatmapInfo.MD5Hash) + && string.IsNullOrEmpty(beatmapInfo.Path) + && beatmapInfo.OnlineID <= 0) + return null; + + Debug.Assert(beatmapInfo.BeatmapSet != null); + + try + { + using (var db = new SqliteConnection(string.Concat(@"Data Source=", storage.GetFullPath(@"online.db", true)))) + { + db.Open(); + + using (var cmd = db.CreateCommand()) + { + cmd.CommandText = + @"SELECT beatmapset_id, beatmap_id, approved, user_id, checksum, last_update FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineID OR filename = @Path"; + + cmd.Parameters.Add(new SqliteParameter(@"@MD5Hash", beatmapInfo.MD5Hash)); + cmd.Parameters.Add(new SqliteParameter(@"@OnlineID", beatmapInfo.OnlineID)); + cmd.Parameters.Add(new SqliteParameter(@"@Path", beatmapInfo.Path)); + + using (var reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + logForModel(beatmapInfo.BeatmapSet, $@"Cached local retrieval for {beatmapInfo}."); + + return new OnlineBeatmapMetadata + { + BeatmapSetID = reader.GetInt32(0), + BeatmapID = reader.GetInt32(1), + BeatmapStatus = (BeatmapOnlineStatus)reader.GetByte(2), + BeatmapSetStatus = (BeatmapOnlineStatus)reader.GetByte(2), + AuthorID = reader.GetInt32(3), + MD5Hash = reader.GetString(4), + LastUpdated = reader.GetDateTimeOffset(5), + // TODO: DateSubmitted and DateRanked are not provided by local cache. + }; + } + } + } + } + } + catch (Exception ex) + { + logForModel(beatmapInfo.BeatmapSet, $@"Cached local retrieval for {beatmapInfo} failed with {ex}."); + } + + return null; + } + + private void logForModel(BeatmapSetInfo set, string message) => + RealmArchiveModelImporter.LogForModel(set, $@"[{nameof(LocalCachedBeatmapMetadataSource)}] {message}"); + + public void Dispose() + { + cacheDownloadRequest?.Dispose(); + } + } +} diff --git a/osu.Game/Beatmaps/OnlineBeatmapMetadata.cs b/osu.Game/Beatmaps/OnlineBeatmapMetadata.cs new file mode 100644 index 0000000000..8640883ca1 --- /dev/null +++ b/osu.Game/Beatmaps/OnlineBeatmapMetadata.cs @@ -0,0 +1,61 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Beatmaps +{ + /// + /// This structure contains parts of beatmap metadata which are involved with the online parts + /// of the game, and therefore must be treated with particular care. + /// This data is retrieved from trusted sources (such as osu-web API, or a locally downloaded sqlite snapshot + /// of osu-web metadata). + /// + public class OnlineBeatmapMetadata + { + /// + /// The online ID of the beatmap. + /// + public int BeatmapID { get; init; } + + /// + /// The online ID of the beatmap set. + /// + public int BeatmapSetID { get; init; } + + /// + /// The online ID of the author. + /// + public int AuthorID { get; init; } + + /// + /// The online status of the beatmap. + /// + public BeatmapOnlineStatus BeatmapStatus { get; init; } + + /// + /// The online status of the associated beatmap set. + /// + public BeatmapOnlineStatus? BeatmapSetStatus { get; init; } + + /// + /// The rank date of the beatmap, if applicable and available. + /// + public DateTimeOffset? DateRanked { get; init; } + + /// + /// The submission date of the beatmap, if available. + /// + public DateTimeOffset? DateSubmitted { get; init; } + + /// + /// The MD5 hash of the beatmap. Used to verify integrity. + /// + public string MD5Hash { get; init; } = string.Empty; + + /// + /// The date when this metadata was last updated. + /// + public DateTimeOffset LastUpdated { get; init; } + } +} From b384a3258d971419b9be5c1ed35c20070c26e1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 13:52:06 +0200 Subject: [PATCH 013/915] Remove unused argument --- osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index b326e7ad1c..98b921e3c7 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -40,7 +40,7 @@ namespace osu.Game.Beatmaps { foreach (var beatmapInfo in beatmapSet.Beatmaps) { - var res = lookup(beatmapSet, beatmapInfo, preferOnlineFetch); + var res = lookup(beatmapInfo, preferOnlineFetch); if (res == null) { @@ -71,7 +71,7 @@ namespace osu.Game.Beatmaps } } - private OnlineBeatmapMetadata? lookup(BeatmapSetInfo set, BeatmapInfo beatmapInfo, bool preferOnlineFetch) + private OnlineBeatmapMetadata? lookup(BeatmapInfo beatmapInfo, bool preferOnlineFetch) { OnlineBeatmapMetadata? result = null; From f0ec264bbc2727d8c84ed6e5f8ac59dd89aeac97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 14:37:34 +0200 Subject: [PATCH 014/915] Add test coverage for metadata lookup process --- .../BeatmapUpdaterMetadataLookupTest.cs | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs diff --git a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs new file mode 100644 index 0000000000..f1eab065c0 --- /dev/null +++ b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs @@ -0,0 +1,125 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Moq; +using NUnit.Framework; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Beatmaps; + +namespace osu.Game.Tests.Beatmaps +{ + [TestFixture] + public class BeatmapUpdaterMetadataLookupTest + { + private Mock apiMetadataSourceMock = null!; + private Mock localCachedMetadataSourceMock = null!; + + private BeatmapUpdaterMetadataLookup metadataLookup = null!; + + [SetUp] + public void SetUp() + { + apiMetadataSourceMock = new Mock(); + localCachedMetadataSourceMock = new Mock(); + + metadataLookup = new BeatmapUpdaterMetadataLookup(apiMetadataSourceMock.Object, localCachedMetadataSourceMock.Object); + } + + [Test] + public void TestLocalCacheQueriedFirst() + { + localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); + apiMetadataSourceMock.Setup(src => src.Available).Returns(true); + + var beatmap = new BeatmapInfo { OnlineID = 123456 }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch: false); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + apiMetadataSourceMock.Verify(src => src.Lookup(It.IsAny()), Times.Never); + } + + [Test] + public void TestAPIQueriedSecond() + { + localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns((OnlineBeatmapMetadata?)null); + apiMetadataSourceMock.Setup(src => src.Available).Returns(true); + apiMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); + + var beatmap = new BeatmapInfo { OnlineID = 123456 }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch: false); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + } + + [Test] + public void TestPreferOnlineFetch() + { + localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); + apiMetadataSourceMock.Setup(src => src.Available).Returns(true); + apiMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Graveyard }); + + var beatmap = new BeatmapInfo { OnlineID = 123456 }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch: true); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Graveyard)); + localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Never); + apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + } + + [Test] + public void TestPreferOnlineFetchFallsBackToLocalCacheIfOnlineSourceUnavailable() + { + localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); + apiMetadataSourceMock.Setup(src => src.Available).Returns(false); + + var beatmap = new BeatmapInfo { OnlineID = 123456 }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch: true); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Never); + } + + [Test] + public void TestMetadataLookupFailed() + { + localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns((OnlineBeatmapMetadata?)null); + apiMetadataSourceMock.Setup(src => src.Available).Returns(true); + apiMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns((OnlineBeatmapMetadata?)null); + + var beatmap = new BeatmapInfo { OnlineID = 123456 }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch: false); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(beatmap.OnlineID, Is.EqualTo(-1)); + localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + } + } +} From af579be0e4d92776f0b6392c878a65e310331e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 15:20:38 +0200 Subject: [PATCH 015/915] Add test coverage for edge cases --- .../BeatmapUpdaterMetadataLookupTest.cs | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs index f1eab065c0..64f44c9922 100644 --- a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs +++ b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs @@ -28,6 +28,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestLocalCacheQueriedFirst() { + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); apiMetadataSourceMock.Setup(src => src.Available).Returns(true); @@ -46,6 +47,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestAPIQueriedSecond() { + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) .Returns((OnlineBeatmapMetadata?)null); apiMetadataSourceMock.Setup(src => src.Available).Returns(true); @@ -66,6 +68,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestPreferOnlineFetch() { + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); apiMetadataSourceMock.Setup(src => src.Available).Returns(true); @@ -86,6 +89,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestPreferOnlineFetchFallsBackToLocalCacheIfOnlineSourceUnavailable() { + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); apiMetadataSourceMock.Setup(src => src.Available).Returns(false); @@ -104,6 +108,7 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestMetadataLookupFailed() { + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) .Returns((OnlineBeatmapMetadata?)null); apiMetadataSourceMock.Setup(src => src.Available).Returns(true); @@ -121,5 +126,52 @@ namespace osu.Game.Tests.Beatmaps localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); } + + /// + /// For the time being, if we fail to find a match in the local cache but online retrieval is not available, we trust the incoming beatmap verbatim wrt online ID. + /// While this is suboptimal as it implicitly trusts the contents of the beatmap, + /// throwing away the online data would be anti-user as it would make all beatmaps imported offline stop working in online. + /// TODO: revisit if/when we have a better flow of queueing metadata retrieval. + /// + [Test] + public void TestLocalMetadataLookupFailedAndOnlineLookupIsUnavailable([Values] bool preferOnlineFetch) + { + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); + localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) + .Returns((OnlineBeatmapMetadata?)null); + apiMetadataSourceMock.Setup(src => src.Available).Returns(false); + + var beatmap = new BeatmapInfo { OnlineID = 123456 }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(beatmap.OnlineID, Is.EqualTo(123456)); + } + + /// + /// For the time being, if there are no available metadata lookup sources, we trust the incoming beatmap verbatim wrt online ID. + /// While this is suboptimal as it implicitly trusts the contents of the beatmap, + /// throwing away the online data would be anti-user as it would make all beatmaps imported offline stop working in online. + /// TODO: revisit if/when we have a better flow of queueing metadata retrieval. + /// + [Test] + public void TestNoAvailableSources() + { + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(false); + apiMetadataSourceMock.Setup(src => src.Available).Returns(false); + + var beatmap = new BeatmapInfo { OnlineID = 123456 }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch: false); + + Assert.That(beatmap.OnlineID, Is.EqualTo(123456)); + localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Never); + apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Never); + } } } From b895d4a42f8c36ef75efba39f72f6bdc409fe634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 15:37:50 +0200 Subject: [PATCH 016/915] Adjust logic to preserve existing desired behaviour --- .../Beatmaps/BeatmapUpdaterMetadataLookup.cs | 43 ++++++++++++++----- .../Beatmaps/IOnlineBeatmapMetadataSource.cs | 2 +- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index 98b921e3c7..3e06907c32 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -40,7 +40,8 @@ namespace osu.Game.Beatmaps { foreach (var beatmapInfo in beatmapSet.Beatmaps) { - var res = lookup(beatmapInfo, preferOnlineFetch); + if (!tryLookup(beatmapInfo, preferOnlineFetch, out var res)) + continue; if (res == null) { @@ -71,22 +72,42 @@ namespace osu.Game.Beatmaps } } - private OnlineBeatmapMetadata? lookup(BeatmapInfo beatmapInfo, bool preferOnlineFetch) + /// + /// Attempts to retrieve the for the given . + /// + /// The beatmap to perform the online lookup for. + /// Whether online sources should be preferred for the lookup. + /// The result of the lookup. Can be if no matching beatmap was found (or the lookup failed). + /// + /// if any of the metadata sources were available and returned a valid . + /// if none of the metadata sources were available, or if there was insufficient data to return a valid . + /// + /// + /// There are two cases wherein this method will return : + /// + /// If neither the local cache or the API are available to query. + /// If the API is not available to query, and a positive match was not made in the local cache. + /// + /// In either case, the online ID read from the .osu file will be preserved, which may not necessarily be what we want. + /// TODO: reconsider this if/when a better flow for queueing online retrieval is implemented. + /// + private bool tryLookup(BeatmapInfo beatmapInfo, bool preferOnlineFetch, out OnlineBeatmapMetadata? result) { - OnlineBeatmapMetadata? result = null; - - bool useLocalCache = !apiMetadataSource.Available || !preferOnlineFetch; - - if (useLocalCache) + if (localCachedMetadataSource.Available && (!apiMetadataSource.Available || !preferOnlineFetch)) + { result = localCachedMetadataSource.Lookup(beatmapInfo); - - if (result != null) - return result; + if (result != null) + return true; + } if (apiMetadataSource.Available) + { result = apiMetadataSource.Lookup(beatmapInfo); + return true; + } - return result; + result = null; + return false; } /// diff --git a/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs b/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs index 753462d493..a068e92f95 100644 --- a/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs @@ -19,7 +19,7 @@ namespace osu.Game.Beatmaps /// Looks up the online metadata for the supplied . /// /// - /// An instance if the lookup is successful, or if the lookup failed. + /// An instance if the lookup is successful, or if the lookup did not return a matching beatmap. /// OnlineBeatmapMetadata? Lookup(BeatmapInfo beatmapInfo); } From 29ce27098d1dda1e9a5c62d1676a41bdb42b78a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 17:49:31 +0200 Subject: [PATCH 017/915] Refactor again to fix test failures --- .../BeatmapUpdaterMetadataLookupTest.cs | 86 ++++++++++++------- osu.Game/Beatmaps/APIBeatmapMetadataSource.cs | 18 ++-- .../Beatmaps/BeatmapUpdaterMetadataLookup.cs | 16 ++-- .../Beatmaps/IOnlineBeatmapMetadataSource.cs | 10 ++- .../LocalCachedBeatmapMetadataSource.cs | 20 +++-- 5 files changed, 94 insertions(+), 56 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs index 64f44c9922..84195f1e7c 100644 --- a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs +++ b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs @@ -28,9 +28,11 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestLocalCacheQueriedFirst() { + var localLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }; localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); - localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); + localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) + .Returns(true); + apiMetadataSourceMock.Setup(src => src.Available).Returns(true); var beatmap = new BeatmapInfo { OnlineID = 123456 }; @@ -40,19 +42,22 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: false); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); - localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); - apiMetadataSourceMock.Verify(src => src.Lookup(It.IsAny()), Times.Never); + localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); + apiMetadataSourceMock.Verify(src => src.TryLookup(It.IsAny(), out It.Ref.IsAny!), Times.Never); } [Test] public void TestAPIQueriedSecond() { + OnlineBeatmapMetadata? localLookupResult = null; localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); - localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns((OnlineBeatmapMetadata?)null); + localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) + .Returns(false); + + var onlineLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }; apiMetadataSourceMock.Setup(src => src.Available).Returns(true); - apiMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); + apiMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out onlineLookupResult)) + .Returns(true); var beatmap = new BeatmapInfo { OnlineID = 123456 }; var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); @@ -61,19 +66,22 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: false); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); - localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); - apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); + apiMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); } [Test] public void TestPreferOnlineFetch() { + var localLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }; localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); - localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); + localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) + .Returns(true); + + var onlineLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Graveyard }; apiMetadataSourceMock.Setup(src => src.Available).Returns(true); - apiMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Graveyard }); + apiMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out onlineLookupResult)) + .Returns(true); var beatmap = new BeatmapInfo { OnlineID = 123456 }; var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); @@ -82,16 +90,18 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: true); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Graveyard)); - localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Never); - apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Never); + apiMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); } [Test] public void TestPreferOnlineFetchFallsBackToLocalCacheIfOnlineSourceUnavailable() { + var localLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }; localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); - localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns(new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }); + localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) + .Returns(true); + apiMetadataSourceMock.Setup(src => src.Available).Returns(false); var beatmap = new BeatmapInfo { OnlineID = 123456 }; @@ -101,19 +111,22 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: true); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); - localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); - apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Never); + localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); + apiMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Never); } [Test] public void TestMetadataLookupFailed() { + OnlineBeatmapMetadata? lookupResult = null; + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); - localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns((OnlineBeatmapMetadata?)null); + localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out lookupResult)) + .Returns(false); + apiMetadataSourceMock.Setup(src => src.Available).Returns(true); - apiMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns((OnlineBeatmapMetadata?)null); + apiMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out lookupResult)) + .Returns(true); var beatmap = new BeatmapInfo { OnlineID = 123456 }; var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); @@ -123,8 +136,8 @@ namespace osu.Game.Tests.Beatmaps Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); Assert.That(beatmap.OnlineID, Is.EqualTo(-1)); - localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); - apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Once); + localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); + apiMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); } /// @@ -134,11 +147,13 @@ namespace osu.Game.Tests.Beatmaps /// TODO: revisit if/when we have a better flow of queueing metadata retrieval. /// [Test] - public void TestLocalMetadataLookupFailedAndOnlineLookupIsUnavailable([Values] bool preferOnlineFetch) + public void TestLocalMetadataLookupReturnedNoMatchAndOnlineLookupIsUnavailable([Values] bool preferOnlineFetch) { + OnlineBeatmapMetadata? localLookupResult = null; localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); - localCachedMetadataSourceMock.Setup(src => src.Lookup(It.IsAny())) - .Returns((OnlineBeatmapMetadata?)null); + localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) + .Returns(false); + apiMetadataSourceMock.Setup(src => src.Available).Returns(false); var beatmap = new BeatmapInfo { OnlineID = 123456 }; @@ -158,20 +173,25 @@ namespace osu.Game.Tests.Beatmaps /// TODO: revisit if/when we have a better flow of queueing metadata retrieval. /// [Test] - public void TestNoAvailableSources() + public void TestNoAvailableSources([Values] bool preferOnlineFetch) { + OnlineBeatmapMetadata? lookupResult = null; + localCachedMetadataSourceMock.Setup(src => src.Available).Returns(false); + localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out lookupResult)) + .Returns(false); + apiMetadataSourceMock.Setup(src => src.Available).Returns(false); + apiMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out lookupResult)) + .Returns(false); var beatmap = new BeatmapInfo { OnlineID = 123456 }; var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); beatmap.BeatmapSet = beatmapSet; - metadataLookup.Update(beatmapSet, preferOnlineFetch: false); + metadataLookup.Update(beatmapSet, preferOnlineFetch); Assert.That(beatmap.OnlineID, Is.EqualTo(123456)); - localCachedMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Never); - apiMetadataSourceMock.Verify(src => src.Lookup(beatmap), Times.Never); } } } diff --git a/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs b/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs index e1b01aaac5..9f76aaf02c 100644 --- a/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs @@ -20,10 +20,13 @@ namespace osu.Game.Beatmaps public bool Available => api.State.Value == APIState.Online; - public OnlineBeatmapMetadata? Lookup(BeatmapInfo beatmapInfo) + public bool TryLookup(BeatmapInfo beatmapInfo, out OnlineBeatmapMetadata? onlineMetadata) { if (!Available) - return null; + { + onlineMetadata = null; + return false; + } Debug.Assert(beatmapInfo.BeatmapSet != null); @@ -37,7 +40,8 @@ namespace osu.Game.Beatmaps if (req.CompletionState == APIRequestCompletionState.Failed) { logForModel(beatmapInfo.BeatmapSet, $@"Online retrieval failed for {beatmapInfo}"); - return null; + onlineMetadata = null; + return true; } var res = req.Response; @@ -46,7 +50,7 @@ namespace osu.Game.Beatmaps { logForModel(beatmapInfo.BeatmapSet, $@"Online retrieval mapped {beatmapInfo} to {res.OnlineBeatmapSetID} / {res.OnlineID}."); - return new OnlineBeatmapMetadata + onlineMetadata = new OnlineBeatmapMetadata { BeatmapID = res.OnlineID, BeatmapSetID = res.OnlineBeatmapSetID, @@ -58,14 +62,18 @@ namespace osu.Game.Beatmaps MD5Hash = res.MD5Hash, LastUpdated = res.LastUpdated }; + return true; } } catch (Exception e) { logForModel(beatmapInfo.BeatmapSet, $@"Online retrieval failed for {beatmapInfo} ({e.Message})"); + onlineMetadata = null; + return false; } - return null; + onlineMetadata = null; + return false; } private void logForModel(BeatmapSetInfo set, string message) => diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index 3e06907c32..b32310990c 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -93,18 +93,12 @@ namespace osu.Game.Beatmaps /// private bool tryLookup(BeatmapInfo beatmapInfo, bool preferOnlineFetch, out OnlineBeatmapMetadata? result) { - if (localCachedMetadataSource.Available && (!apiMetadataSource.Available || !preferOnlineFetch)) - { - result = localCachedMetadataSource.Lookup(beatmapInfo); - if (result != null) - return true; - } - - if (apiMetadataSource.Available) - { - result = apiMetadataSource.Lookup(beatmapInfo); + bool useLocalCache = !apiMetadataSource.Available || !preferOnlineFetch; + if (useLocalCache && localCachedMetadataSource.TryLookup(beatmapInfo, out result)) + return true; + + if (apiMetadataSource.TryLookup(beatmapInfo, out result)) return true; - } result = null; return false; diff --git a/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs b/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs index a068e92f95..8230ef40ac 100644 --- a/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs @@ -18,9 +18,15 @@ namespace osu.Game.Beatmaps /// /// Looks up the online metadata for the supplied . /// + /// The to look up. + /// + /// An instance if the lookup is successful. + /// if a mismatch between the local instance and the looked-up data was detected. + /// The returned value is only valid if the return value of the method is . + /// /// - /// An instance if the lookup is successful, or if the lookup did not return a matching beatmap. + /// Whether the lookup was performed. /// - OnlineBeatmapMetadata? Lookup(BeatmapInfo beatmapInfo); + bool TryLookup(BeatmapInfo beatmapInfo, out OnlineBeatmapMetadata? onlineMetadata); } } diff --git a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs index 435242aeab..7a179b281f 100644 --- a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs @@ -108,15 +108,21 @@ namespace osu.Game.Beatmaps // cached database exists on disk. && storage.Exists(cache_database_name); - public OnlineBeatmapMetadata? Lookup(BeatmapInfo beatmapInfo) + public bool TryLookup(BeatmapInfo beatmapInfo, out OnlineBeatmapMetadata? onlineMetadata) { if (!Available) - return null; + { + onlineMetadata = null; + return false; + } if (string.IsNullOrEmpty(beatmapInfo.MD5Hash) && string.IsNullOrEmpty(beatmapInfo.Path) && beatmapInfo.OnlineID <= 0) - return null; + { + onlineMetadata = null; + return false; + } Debug.Assert(beatmapInfo.BeatmapSet != null); @@ -141,7 +147,7 @@ namespace osu.Game.Beatmaps { logForModel(beatmapInfo.BeatmapSet, $@"Cached local retrieval for {beatmapInfo}."); - return new OnlineBeatmapMetadata + onlineMetadata = new OnlineBeatmapMetadata { BeatmapSetID = reader.GetInt32(0), BeatmapID = reader.GetInt32(1), @@ -152,6 +158,7 @@ namespace osu.Game.Beatmaps LastUpdated = reader.GetDateTimeOffset(5), // TODO: DateSubmitted and DateRanked are not provided by local cache. }; + return true; } } } @@ -160,9 +167,12 @@ namespace osu.Game.Beatmaps catch (Exception ex) { logForModel(beatmapInfo.BeatmapSet, $@"Cached local retrieval for {beatmapInfo} failed with {ex}."); + onlineMetadata = null; + return false; } - return null; + onlineMetadata = null; + return false; } private void logForModel(BeatmapSetInfo set, string message) => From c930ec97d6681fbe34afe37ba01a7dd08127c01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 19:18:59 +0200 Subject: [PATCH 018/915] Polish xmldocs --- osu.Game/Beatmaps/APIBeatmapMetadataSource.cs | 3 +++ osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs | 2 +- osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs | 6 ++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs b/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs index 9f76aaf02c..a2eebe6161 100644 --- a/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/APIBeatmapMetadataSource.cs @@ -9,6 +9,9 @@ using osu.Game.Online.API.Requests; namespace osu.Game.Beatmaps { + /// + /// Performs online metadata lookups using the osu-web API. + /// public class APIBeatmapMetadataSource : IOnlineBeatmapMetadataSource { private readonly IAPIProvider api; diff --git a/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs b/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs index 8230ef40ac..5bf5381f2a 100644 --- a/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/IOnlineBeatmapMetadataSource.cs @@ -6,7 +6,7 @@ using System; namespace osu.Game.Beatmaps { /// - /// Unifying interface for sources of online beatmap metadata. + /// Unifying interface for sources of . /// public interface IOnlineBeatmapMetadataSource : IDisposable { diff --git a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs index 7a179b281f..ff88fecd86 100644 --- a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs @@ -18,11 +18,9 @@ using SQLitePCL; namespace osu.Game.Beatmaps { /// - /// + /// Performs online metadata lookups using a copy of a database containing metadata for a large subset of beatmaps (stored to ). + /// The database will be asynchronously downloaded - if not already present locally - when this component is constructed. /// - /// - /// On creating the component, a copy of a database containing metadata for a large subset of beatmaps (stored to ) will be downloaded if not already present locally. - /// public class LocalCachedBeatmapMetadataSource : IOnlineBeatmapMetadataSource { private readonly Storage storage; From 85e303ec54cd60b75f6b3cc4d0a457caafda4afc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Nov 2023 20:00:09 +0900 Subject: [PATCH 019/915] Add two factor step to api state flow --- osu.Game/Online/API/APIAccess.cs | 5 +++++ osu.Game/Online/API/DummyAPIAccess.cs | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 4f586c8fff..a3ceb14a40 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -540,6 +540,11 @@ namespace osu.Game.Online.API /// Failing, + /// + /// Waiting on second factor authentication. + /// + RequiresAuthentication, + /// /// We are in the process of (re-)connecting. /// diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index d585124db6..4cf2152193 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -55,6 +55,7 @@ namespace osu.Game.Online.API private bool shouldFailNextLogin; private bool stayConnectingNextLogin; + private bool requiresTwoFactor; /// /// The current connectivity state of the API. @@ -115,7 +116,13 @@ namespace osu.Game.Online.API Id = DUMMY_USER_ID, }; - state.Value = APIState.Online; + if (requiresTwoFactor) + { + state.Value = APIState.RequiresAuthentication; + requiresTwoFactor = false; + } + else + state.Value = APIState.Online; } public void Logout() @@ -142,6 +149,8 @@ namespace osu.Game.Online.API IBindableList IAPIProvider.Friends => Friends; IBindable IAPIProvider.Activity => Activity; + public void RequireTwoFactor() => requiresTwoFactor = true; + /// /// During the next simulated login, the process will fail immediately. /// From 80c879e5ebed1d1d15b8d44de47f1b15ea77470c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Nov 2023 16:37:12 +0900 Subject: [PATCH 020/915] Adjust member ordering in `LoginForm` --- osu.Game/Overlays/Login/LoginForm.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index 0eef55162f..80dfca93d2 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -32,13 +32,7 @@ namespace osu.Game.Overlays.Login public Action? RequestHide; - private void performLogin() - { - if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) - api.Login(username.Text, password.Text); - else - shakeSignIn.Shake(); - } + public override bool AcceptsFocus => true; [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuConfigManager config, AccountCreationOverlay accountCreation) @@ -144,7 +138,13 @@ namespace osu.Game.Overlays.Login } } - public override bool AcceptsFocus => true; + private void performLogin() + { + if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) + api.Login(username.Text, password.Text); + else + shakeSignIn.Shake(); + } protected override bool OnClick(ClickEvent e) => true; From e9d4cf2e24de488c75b9cd0a52e2b524dfca5248 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Nov 2023 20:00:22 +0900 Subject: [PATCH 021/915] Setup basic form flow --- .../Visual/Menus/TestSceneLoginOverlay.cs | 13 +++++++++++++ osu.Game/Overlays/Login/LoginForm.cs | 5 +++++ osu.Game/Overlays/Login/LoginPanel.cs | 6 +++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index 0bc71924ce..30c0f6644e 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -36,6 +36,19 @@ namespace osu.Game.Tests.Visual.Menus AddStep("show login overlay", () => loginOverlay.Show()); } + [Test] + public void TestLoginTwoFactorSuccess() + { + AddStep("logout", () => + { + API.Logout(); + ((DummyAPIAccess)API).RequireTwoFactor(); + }); + + AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); + AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + } + [Test] public void TestLoginSuccess() { diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index 80dfca93d2..291e92883b 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -21,6 +21,11 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Login { + public partial class AccountVerificationForm : FillFlowContainer + { + + } + public partial class LoginForm : FillFlowContainer { private TextBox username = null!; diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 71ecf2e75a..59b9c6ab9f 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Login { private bool bounding = true; - private LoginForm? form; + private Drawable? form; [Resolved] private OsuColour colours { get; set; } = null!; @@ -81,6 +81,10 @@ namespace osu.Game.Overlays.Login }; break; + case APIState.RequiresAuthentication: + Child = form = new AccountVerificationForm(); + break; + case APIState.Failing: case APIState.Connecting: LinkFlowContainer linkFlow; From c4e461ba447eea892668e12967af659e17689b1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Nov 2023 11:49:49 +0900 Subject: [PATCH 022/915] Add two factor auth form --- .../Overlays/Login/AccountVerificationForm.cs | 92 +++++++++++++++++++ osu.Game/Overlays/Login/LoginForm.cs | 5 - 2 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Overlays/Login/AccountVerificationForm.cs diff --git a/osu.Game/Overlays/Login/AccountVerificationForm.cs b/osu.Game/Overlays/Login/AccountVerificationForm.cs new file mode 100644 index 0000000000..a27cc01ed2 --- /dev/null +++ b/osu.Game/Overlays/Login/AccountVerificationForm.cs @@ -0,0 +1,92 @@ +// 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.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; +using osuTK; + +namespace osu.Game.Overlays.Login +{ + public partial class AccountVerificationForm : FillFlowContainer + { + private OsuTextBox code = null!; + private LinkFlowContainer explainText = null!; + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Spacing = new Vector2(0, SettingsSection.ITEM_SPACING); + + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0f, SettingsSection.ITEM_SPACING), + Children = new Drawable[] + { + new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Regular)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = "An email has been sent to you with a verification code. Enter the code.", + }, + code = new OsuTextBox + { + PlaceholderText = "Enter code", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this + }, + explainText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Regular)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = 0, + }, + }, + }, + new LinkFlowContainer + { + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + }; + + explainText.AddParagraph("Make sure to check your spam folder if you can't find the email."); + explainText.AddParagraph("If you can't access your email or have forgotten what you used, please follow the "); + explainText.AddLink("email recovery process here", () => { }); + explainText.AddText(". You can also "); + explainText.AddLink("request another code", () => { }); + explainText.AddText(" or "); + explainText.AddLink("sign out", () => { }); + explainText.AddText("."); + } + + public override bool AcceptsFocus => true; + + protected override bool OnClick(ClickEvent e) => true; + + protected override void OnFocus(FocusEvent e) + { + Schedule(() => { GetContainingInputManager().ChangeFocus(code); }); + } + } +} diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index 291e92883b..80dfca93d2 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -21,11 +21,6 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Login { - public partial class AccountVerificationForm : FillFlowContainer - { - - } - public partial class LoginForm : FillFlowContainer { private TextBox username = null!; From 0e4244a692227d6f08a6ec2a928ee3dcec69d4ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Nov 2023 16:38:07 +0900 Subject: [PATCH 023/915] Add `APIAccess` flow for 2fa --- osu.Game/Online/API/APIAccess.cs | 40 +++++++++++++++++++++++++-- osu.Game/Online/API/DummyAPIAccess.cs | 7 ++++- osu.Game/Online/API/IAPIProvider.cs | 6 ++++ osu.Game/Overlays/Login/LoginPanel.cs | 2 +- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index a3ceb14a40..f9dd97a8f2 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -48,6 +48,8 @@ namespace osu.Game.Online.API public string ProvidedUsername { get; private set; } + public string SecondFactorCode { get; private set; } + private string password; public IBindable LocalUser => localUser; @@ -183,6 +185,7 @@ namespace osu.Game.Online.API /// /// /// This method takes control of and transitions from to either + /// - (pending 2fa) /// - (successful connection) /// - (failed connection but retrying) /// - (failed and can't retry, clear credentials and require user interaction) @@ -190,8 +193,6 @@ namespace osu.Game.Online.API /// Whether the connection attempt was successful. private void attemptConnect() { - state.Value = APIState.Connecting; - if (localUser.IsDefault) { // Show a placeholder user if saved credentials are available. @@ -208,11 +209,14 @@ namespace osu.Game.Online.API if (!authentication.HasValidAccessToken) { + state.Value = APIState.Connecting; LastLoginError = null; try { authentication.AuthenticateWithLogin(ProvidedUsername, password); + state.Value = APIState.RequiresSecondFactorAuth; + return; } catch (Exception e) { @@ -225,6 +229,28 @@ namespace osu.Game.Online.API } } + if (state.Value == APIState.RequiresSecondFactorAuth) + { + if (string.IsNullOrEmpty(SecondFactorCode)) + return; + + state.Value = APIState.Connecting; + LastLoginError = null; + + // TODO: use code to ensure second factor authentication completed. + Thread.Sleep(1000); + bool success = SecondFactorCode == "00000000"; + SecondFactorCode = null; + + if (!success) + { + state.Value = APIState.RequiresSecondFactorAuth; + LastLoginError = new InvalidOperationException("Second factor auth failed"); + SecondFactorCode = null; + return; + } + } + var userReq = new GetUserRequest(); userReq.Failure += ex => { @@ -307,6 +333,13 @@ namespace osu.Game.Online.API this.password = password; } + public void AuthenticateSecondFactor(string code) + { + Debug.Assert(State.Value == APIState.RequiresSecondFactorAuth); + + SecondFactorCode = code; + } + public IHubClientConnector GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => new HubClientConnector(clientName, endpoint, this, versionHash, preferMessagePack); @@ -493,6 +526,7 @@ namespace osu.Game.Online.API public void Logout() { password = null; + SecondFactorCode = null; authentication.Clear(); // Scheduled prior to state change such that the state changed event is invoked with the correct user and their friends present @@ -543,7 +577,7 @@ namespace osu.Game.Online.API /// /// Waiting on second factor authentication. /// - RequiresAuthentication, + RequiresSecondFactorAuth, /// /// We are in the process of (re-)connecting. diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 4cf2152193..bd833d39dd 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -118,13 +118,18 @@ namespace osu.Game.Online.API if (requiresTwoFactor) { - state.Value = APIState.RequiresAuthentication; + state.Value = APIState.RequiresSecondFactorAuth; requiresTwoFactor = false; } else state.Value = APIState.Online; } + public void AuthenticateSecondFactor(string code) + { + state.Value = APIState.Online; + } + public void Logout() { state.Value = APIState.Offline; diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index a1d7006c8c..5f99ad2f4d 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -106,6 +106,12 @@ namespace osu.Game.Online.API /// The user's password. void Login(string username, string password); + /// + /// Provide a second-factor authentication code for authentication. + /// + /// The 2FA code. + void AuthenticateSecondFactor(string code); + /// /// Log out the current user. /// diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 59b9c6ab9f..f896d03231 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -81,7 +81,7 @@ namespace osu.Game.Overlays.Login }; break; - case APIState.RequiresAuthentication: + case APIState.RequiresSecondFactorAuth: Child = form = new AccountVerificationForm(); break; From 285f740e2a2aa3754445141fa2e974fa4b1d9cd4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Nov 2023 16:53:37 +0900 Subject: [PATCH 024/915] Update various components to handle new state --- osu.Game/Overlays/Login/LoginPanel.cs | 2 +- ...icationForm.cs => SecondFactorAuthForm.cs} | 32 +++++++++++++++---- .../Overlays/Toolbar/ToolbarUserButton.cs | 1 + 3 files changed, 28 insertions(+), 7 deletions(-) rename osu.Game/Overlays/Login/{AccountVerificationForm.cs => SecondFactorAuthForm.cs} (78%) diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index f896d03231..ce0b0a5a48 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -82,7 +82,7 @@ namespace osu.Game.Overlays.Login break; case APIState.RequiresSecondFactorAuth: - Child = form = new AccountVerificationForm(); + Child = form = new SecondFactorAuthForm(); break; case APIState.Failing: diff --git a/osu.Game/Overlays/Login/AccountVerificationForm.cs b/osu.Game/Overlays/Login/SecondFactorAuthForm.cs similarity index 78% rename from osu.Game/Overlays/Login/AccountVerificationForm.cs rename to osu.Game/Overlays/Login/SecondFactorAuthForm.cs index a27cc01ed2..cfec46c599 100644 --- a/osu.Game/Overlays/Login/AccountVerificationForm.cs +++ b/osu.Game/Overlays/Login/SecondFactorAuthForm.cs @@ -8,15 +8,20 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Overlays.Settings; using osuTK; namespace osu.Game.Overlays.Login { - public partial class AccountVerificationForm : FillFlowContainer + public partial class SecondFactorAuthForm : FillFlowContainer { - private OsuTextBox code = null!; + private OsuTextBox codeTextBox = null!; private LinkFlowContainer explainText = null!; + private ErrorTextFlowContainer errorText = null!; + + [Resolved] + private IAPIProvider api { get; set; } = null!; [BackgroundDependencyLoader] private void load() @@ -43,18 +48,18 @@ namespace osu.Game.Overlays.Login AutoSizeAxes = Axes.Y, Text = "An email has been sent to you with a verification code. Enter the code.", }, - code = new OsuTextBox + codeTextBox = new OsuTextBox { PlaceholderText = "Enter code", RelativeSizeAxes = Axes.X, - TabbableContentContainer = this + TabbableContentContainer = this, }, explainText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Regular)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }, - new ErrorTextFlowContainer + errorText = new ErrorTextFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -78,6 +83,21 @@ namespace osu.Game.Overlays.Login explainText.AddText(" or "); explainText.AddLink("sign out", () => { }); explainText.AddText("."); + + codeTextBox.Current.BindValueChanged(code => + { + if (code.NewValue.Length == 8) + { + api.AuthenticateSecondFactor(code.NewValue); + codeTextBox.Current.Disabled = true; + } + }); + + if (api.LastLoginError?.Message is string error) + { + errorText.Alpha = 1; + errorText.AddErrors(new[] { error }); + } } public override bool AcceptsFocus => true; @@ -86,7 +106,7 @@ namespace osu.Game.Overlays.Login protected override void OnFocus(FocusEvent e) { - Schedule(() => { GetContainingInputManager().ChangeFocus(code); }); + Schedule(() => { GetContainingInputManager().ChangeFocus(codeTextBox); }); } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 028decea1e..f0b5aed3cf 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -101,6 +101,7 @@ namespace osu.Game.Overlays.Toolbar switch (state.NewValue) { + case APIState.RequiresSecondFactorAuth: case APIState.Connecting: TooltipText = ToolbarStrings.Connecting; spinner.Show(); From f7fa9c90d66c9ba05f4bc50c1bc78274caa2c8cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Nov 2023 18:16:02 +0900 Subject: [PATCH 025/915] Add test coverage of 2FA flow --- .../Visual/Menus/TestSceneLoginOverlay.cs | 24 +++++++++---------- osu.Game/Online/API/DummyAPIAccess.cs | 13 ++++++---- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index 30c0f6644e..0c5f5a321c 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays; +using osu.Game.Overlays.Login; using osu.Game.Users.Drawables; using osuTK.Input; @@ -36,28 +37,25 @@ namespace osu.Game.Tests.Visual.Menus AddStep("show login overlay", () => loginOverlay.Show()); } - [Test] - public void TestLoginTwoFactorSuccess() - { - AddStep("logout", () => - { - API.Logout(); - ((DummyAPIAccess)API).RequireTwoFactor(); - }); - - AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); - AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); - } - [Test] public void TestLoginSuccess() { AddStep("logout", () => API.Logout()); + assertAPIState(APIState.Offline); AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + + assertAPIState(APIState.RequiresSecondFactorAuth); + AddUntilStep("wait for second factor auth form", () => loginOverlay.ChildrenOfType().SingleOrDefault(), () => Is.Not.Null); + + AddStep("enter code", () => loginOverlay.ChildrenOfType().First().Text = "88800088"); + assertAPIState(APIState.Online); } + private void assertAPIState(APIState expected) => + AddUntilStep($"login state is {expected}", () => API.State.Value, () => Is.EqualTo(expected)); + [Test] public void TestLoginFailure() { diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index bd833d39dd..bd462ac23e 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -55,7 +55,7 @@ namespace osu.Game.Online.API private bool shouldFailNextLogin; private bool stayConnectingNextLogin; - private bool requiresTwoFactor; + private bool requiredSecondFactorAuth = true; /// /// The current connectivity state of the API. @@ -116,13 +116,15 @@ namespace osu.Game.Online.API Id = DUMMY_USER_ID, }; - if (requiresTwoFactor) + if (requiredSecondFactorAuth) { state.Value = APIState.RequiresSecondFactorAuth; - requiresTwoFactor = false; } else + { state.Value = APIState.Online; + requiredSecondFactorAuth = true; + } } public void AuthenticateSecondFactor(string code) @@ -154,7 +156,10 @@ namespace osu.Game.Online.API IBindableList IAPIProvider.Friends => Friends; IBindable IAPIProvider.Activity => Activity; - public void RequireTwoFactor() => requiresTwoFactor = true; + /// + /// Skip 2FA requirement for next login. + /// + public void SkipSecondFactor() => requiredSecondFactorAuth = false; /// /// During the next simulated login, the process will fail immediately. From 167f5b4ef401317b3721187147ec7a591288e092 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Nov 2023 18:21:06 +0900 Subject: [PATCH 026/915] Tidy up localisations and connect missing links --- osu.Game/Overlays/Login/SecondFactorAuthForm.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Login/SecondFactorAuthForm.cs b/osu.Game/Overlays/Login/SecondFactorAuthForm.cs index cfec46c599..60c04eedee 100644 --- a/osu.Game/Overlays/Login/SecondFactorAuthForm.cs +++ b/osu.Game/Overlays/Login/SecondFactorAuthForm.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays.Settings; +using osu.Game.Resources.Localisation.Web; using osuTK; namespace osu.Game.Overlays.Login @@ -75,13 +76,17 @@ namespace osu.Game.Overlays.Login }, }; - explainText.AddParagraph("Make sure to check your spam folder if you can't find the email."); + explainText.AddParagraph(UserVerificationStrings.BoxInfoCheckSpam); + // We can't support localisable strings with nested links yet. Not sure if we even can (probably need to allow markdown link formatting or something). explainText.AddParagraph("If you can't access your email or have forgotten what you used, please follow the "); - explainText.AddLink("email recovery process here", () => { }); + explainText.AddLink(UserVerificationStrings.BoxInfoRecoverLink, $"{api.WebsiteRootUrl}/home/password-reset"); explainText.AddText(". You can also "); - explainText.AddLink("request another code", () => { }); + explainText.AddLink(UserVerificationStrings.BoxInfoReissueLink, () => + { + // TODO: request another code. + }); explainText.AddText(" or "); - explainText.AddLink("sign out", () => { }); + explainText.AddLink(UserVerificationStrings.BoxInfoLogoutLink, () => { api.Logout(); }); explainText.AddText("."); codeTextBox.Current.BindValueChanged(code => From 7472dc9bb5e1e410023ab98d778c5380d1d2f958 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Nov 2023 20:39:23 +0900 Subject: [PATCH 027/915] Update `APIState` checks --- osu.Game/Online/OnlineViewContainer.cs | 5 +++++ osu.Game/Overlays/AccountCreationOverlay.cs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 46f64fbb61..824da152b2 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -79,10 +80,14 @@ namespace osu.Game.Online case APIState.Failing: case APIState.Connecting: + case APIState.RequiresSecondFactorAuth: PopContentOut(Content); LoadingSpinner.Show(); placeholder.FadeOut(transform_duration / 2, Easing.OutQuint); break; + + default: + throw new ArgumentOutOfRangeException(); } }); diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index ef2e055eae..576ee92b48 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -118,12 +119,16 @@ namespace osu.Game.Overlays break; case APIState.Connecting: + case APIState.RequiresSecondFactorAuth: break; case APIState.Online: scheduledHide?.Cancel(); scheduledHide = Schedule(Hide); break; + + default: + throw new ArgumentOutOfRangeException(); } } } From 3b58f6a7e78d8244a6e60bf8b27078c84845fb3c Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Thu, 21 Dec 2023 21:07:12 -0500 Subject: [PATCH 028/915] Implement difficulty statistics --- global.json | 8 +- .../Drawables/DifficultyIconTooltip.cs | 100 +++++++++++++++++- 2 files changed, 103 insertions(+), 5 deletions(-) diff --git a/global.json b/global.json index 5dcd5f425a..7835999220 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "6.0.100", - "rollForward": "latestFeature" + "version": "6.0.0", + "rollForward": "latestFeature", + "allowPrerelease": true } -} - +} \ No newline at end of file diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 3fa24bcc3e..7ea2c6a0a2 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -19,6 +20,13 @@ namespace osu.Game.Beatmaps.Drawables { private OsuSpriteText difficultyName; private StarRatingDisplay starRating; + private OsuSpriteText overallDifficulty; + private OsuSpriteText drainRate; + private OsuSpriteText circleSize; + private OsuSpriteText approachRate; + private OsuSpriteText BPM; + private OsuSpriteText maxCombo; + private OsuSpriteText length; [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -35,6 +43,7 @@ namespace osu.Game.Beatmaps.Drawables Colour = colours.Gray3, RelativeSizeAxes = Axes.Both }, + // Headers new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -55,6 +64,84 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, + }, + // Difficulty stats + new FillFlowContainer() + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), + }, + overallDifficulty = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14), + }, + drainRate = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14), + }, + circleSize = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14), + }, + approachRate = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14), + }, + } + }, + // Misc stats + new FillFlowContainer() + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), + }, + length = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14), + }, + BPM = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14), + }, + maxCombo = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 14), + }, + } } } } @@ -68,10 +155,21 @@ namespace osu.Game.Beatmaps.Drawables if (displayedContent != null) starRating.Current.UnbindFrom(displayedContent.Difficulty); + // Header row displayedContent = content; - starRating.Current.BindTarget = displayedContent.Difficulty; difficultyName.Text = displayedContent.BeatmapInfo.DifficultyName; + + // Difficulty row + overallDifficulty.Text = "OD: " + displayedContent.BeatmapInfo.Difficulty.OverallDifficulty.ToString("0.##"); + drainRate.Text = "| HP: " + displayedContent.BeatmapInfo.Difficulty.DrainRate.ToString("0.##"); + circleSize.Text = "| CS: " + displayedContent.BeatmapInfo.Difficulty.CircleSize.ToString("0.##"); + approachRate.Text = "| AR: " + displayedContent.BeatmapInfo.Difficulty.ApproachRate.ToString("0.##"); + + // Misc row + length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length).ToString("mm\\:ss"); + BPM.Text = "| BPM: " + displayedContent.BeatmapInfo.BPM; + maxCombo.Text = "| Max Combo: " + displayedContent.BeatmapInfo.TotalObjectCount; } public void Move(Vector2 pos) => Position = pos; From 803329c5d8aa3a73ef9a58875adb8255f241a0ec Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Fri, 22 Dec 2023 15:58:41 -0500 Subject: [PATCH 029/915] rollback my accidental global.json change --- global.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/global.json b/global.json index 7835999220..d6c2c37f77 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,6 @@ { "sdk": { - "version": "6.0.0", - "rollForward": "latestFeature", - "allowPrerelease": true + "version": "6.0.100", + "rollForward": "latestFeature" } } \ No newline at end of file From f7c1e66165b5415a3779961f852677fca073c3d5 Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:28:02 -0500 Subject: [PATCH 030/915] Make the difficulty stats change based on the currently applied mods --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 10 ++- .../Drawables/DifficultyIconTooltip.cs | 61 ++++++++++++++----- .../OnlinePlay/DrawableRoomPlaylistItem.cs | 2 +- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 1665ec52fa..44981003f2 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osuTK; using osuTK.Graphics; @@ -39,6 +40,8 @@ namespace osu.Game.Beatmaps.Drawables private readonly IRulesetInfo ruleset; + private readonly Mod[]? mods; + private Drawable background = null!; private readonly Container iconContainer; @@ -58,11 +61,14 @@ namespace osu.Game.Beatmaps.Drawables /// Creates a new . Will use provided beatmap's for initial value. /// /// The beatmap to be displayed in the tooltip, and to be used for the initial star rating value. + /// The mods type beat /// An optional ruleset to be used for the icon display, in place of the beatmap's ruleset. - public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null) + public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null, Mod[]? mods = null) : this(ruleset ?? beatmap.Ruleset) { this.beatmap = beatmap; + this.mods = mods; + Current.Value = new StarDifficulty(beatmap.StarRating, 0); } @@ -128,6 +134,6 @@ namespace osu.Game.Beatmaps.Drawables GetCustomTooltip() => new DifficultyIconTooltip(); DifficultyIconTooltipContent IHasCustomTooltip. - TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current) : null)!; + TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods) : null)!; } } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 7ea2c6a0a2..0f5c94ac1d 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -12,6 +13,8 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osuTK; namespace osu.Game.Beatmaps.Drawables @@ -24,7 +27,7 @@ namespace osu.Game.Beatmaps.Drawables private OsuSpriteText drainRate; private OsuSpriteText circleSize; private OsuSpriteText approachRate; - private OsuSpriteText BPM; + private OsuSpriteText bpm; private OsuSpriteText maxCombo; private OsuSpriteText length; @@ -66,7 +69,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, }, // Difficulty stats - new FillFlowContainer() + new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -81,7 +84,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), }, - overallDifficulty = new OsuSpriteText + circleSize = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -93,13 +96,13 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 14), }, - circleSize = new OsuSpriteText + approachRate = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 14), }, - approachRate = new OsuSpriteText + overallDifficulty = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -108,7 +111,7 @@ namespace osu.Game.Beatmaps.Drawables } }, // Misc stats - new FillFlowContainer() + new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -129,7 +132,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 14), }, - BPM = new OsuSpriteText + bpm = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -155,20 +158,44 @@ namespace osu.Game.Beatmaps.Drawables if (displayedContent != null) starRating.Current.UnbindFrom(displayedContent.Difficulty); - // Header row displayedContent = content; + + // Header row starRating.Current.BindTarget = displayedContent.Difficulty; difficultyName.Text = displayedContent.BeatmapInfo.DifficultyName; + double rate = 1; + + if (displayedContent.Mods != null) + { + foreach (var mod in displayedContent.Mods.OfType()) + rate = mod.ApplyToRate(0, rate); + } + + double bpmAdjusted = displayedContent.BeatmapInfo.BPM * rate; + + BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(displayedContent.BeatmapInfo.Difficulty); + + if (displayedContent.Mods != null) + { + foreach (var mod in displayedContent.Mods.OfType()) + { + mod.ApplyToDifficulty(originalDifficulty); + } + } + + Ruleset ruleset = displayedContent.Ruleset.CreateInstance(); + BeatmapDifficulty adjustedDifficulty = ruleset.GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); + // Difficulty row - overallDifficulty.Text = "OD: " + displayedContent.BeatmapInfo.Difficulty.OverallDifficulty.ToString("0.##"); - drainRate.Text = "| HP: " + displayedContent.BeatmapInfo.Difficulty.DrainRate.ToString("0.##"); - circleSize.Text = "| CS: " + displayedContent.BeatmapInfo.Difficulty.CircleSize.ToString("0.##"); - approachRate.Text = "| AR: " + displayedContent.BeatmapInfo.Difficulty.ApproachRate.ToString("0.##"); + circleSize.Text = "CS: " + adjustedDifficulty.CircleSize.ToString("0.##"); + drainRate.Text = "| HP: " + adjustedDifficulty.DrainRate.ToString("0.##"); + approachRate.Text = "| AR: " + adjustedDifficulty.ApproachRate.ToString("0.##"); + overallDifficulty.Text = "| OD: " + adjustedDifficulty.OverallDifficulty.ToString("0.##"); // Misc row - length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length).ToString("mm\\:ss"); - BPM.Text = "| BPM: " + displayedContent.BeatmapInfo.BPM; + length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length / rate).ToString("mm\\:ss"); + bpm.Text = "| BPM: " + bpmAdjusted; maxCombo.Text = "| Max Combo: " + displayedContent.BeatmapInfo.TotalObjectCount; } @@ -183,11 +210,15 @@ namespace osu.Game.Beatmaps.Drawables { public readonly IBeatmapInfo BeatmapInfo; public readonly IBindable Difficulty; + public readonly IRulesetInfo Ruleset; + public readonly Mod[] Mods; - public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty) + public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[] mods) { BeatmapInfo = beatmapInfo; Difficulty = difficulty; + Ruleset = rulesetInfo; + Mods = mods; } } } diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 8f405399a7..eb23ed6f8f 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -283,7 +283,7 @@ namespace osu.Game.Screens.OnlinePlay } if (beatmap != null) - difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset) { Size = new Vector2(icon_height) }; + difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods) { Size = new Vector2(icon_height) }; else difficultyIconContainer.Clear(); From 1d4db3b7a95b894604a0717920fc2771fd7ef352 Mon Sep 17 00:00:00 2001 From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com> Date: Tue, 26 Dec 2023 11:08:21 -0800 Subject: [PATCH 031/915] Fix `SkinEditorOverlay` freezing when `ReplayPlayer` screen exits early Originally when popping in, the ReplayPlayer was loaded first (if previous screen was MainMenu), and afterwards the SkinEditor component was loaded asynchronously. However, if the ReplayPlayer screen exits quickly (like in the event the beatmap has no objects), the skin editor component has not finished initializing (this is before it was even added to the component tree, so it's still not marked `Visible`), then the screen exiting will cause `OsuGame` to call SetTarget(newScreen) -> setTarget(...) which sees that the cached `skinEditor` is not visible yet, and hides/nulls the field. This is the point where LoadComponentAsync(editor, ...) finishes, and the callback sees that the cached skinEditor field is now different (null) than the one that was loaded, and never adds it to the component tree. This occurrence is unhandled and as such the SkinEditorOverlay never hides itself, consuming all input infinitely. This PR changes the loading to start loading the ReplayPlayer *after* the SkinEditor has been loaded and added to the component tree. Additionally, this lowers the exit delay for ReplayPlayer and changes the "no hit objects" notification to not be an error since it's a controlled exit. --- osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs | 8 ++++---- osu.Game/Screens/Play/Player.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index bedaf12c9b..880921ca64 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -100,9 +100,6 @@ namespace osu.Game.Overlays.SkinEditor { globallyDisableBeatmapSkinSetting(); - if (lastTargetScreen is MainMenu) - PresentGameplay(); - if (skinEditor != null) { skinEditor.Show(); @@ -122,6 +119,9 @@ namespace osu.Game.Overlays.SkinEditor AddInternal(editor); + if (lastTargetScreen is MainMenu) + PresentGameplay(); + Debug.Assert(lastTargetScreen != null); SetTarget(lastTargetScreen); @@ -316,7 +316,7 @@ namespace osu.Game.Overlays.SkinEditor base.LoadComplete(); if (!LoadedBeatmapSuccessfully) - Scheduler.AddDelayed(this.Exit, 3000); + Scheduler.AddDelayed(this.Exit, RESULTS_DISPLAY_DELAY); } protected override void Update() diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c960ac357f..08d77d60d8 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -547,7 +547,7 @@ namespace osu.Game.Screens.Play if (playable.HitObjects.Count == 0) { - Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Error); + Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Important); return null; } } From 85a768d0c806d5c4579b762ae98e938eee135fe7 Mon Sep 17 00:00:00 2001 From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:46:50 -0800 Subject: [PATCH 032/915] Don't reuse results delay const --- osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index 880921ca64..10a032193f 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -316,7 +316,7 @@ namespace osu.Game.Overlays.SkinEditor base.LoadComplete(); if (!LoadedBeatmapSuccessfully) - Scheduler.AddDelayed(this.Exit, RESULTS_DISPLAY_DELAY); + Scheduler.AddDelayed(this.Exit, 1000); } protected override void Update() From 0c8b551c6618668902ae1f92e0828f24fd1427f2 Mon Sep 17 00:00:00 2001 From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com> Date: Wed, 27 Dec 2023 14:45:56 -0800 Subject: [PATCH 033/915] SkinEditor lifetime fix & show gameplay If the SkinEditor was created already but not finished initializing, wait for it to initialize before handling a screen change, which could possibly null the skin editor. Additionally, in the case the skin editor is already loaded but hidden, make sure to show gameplay. --- osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index 10a032193f..5f5323b584 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -103,6 +103,10 @@ namespace osu.Game.Overlays.SkinEditor if (skinEditor != null) { skinEditor.Show(); + + if (lastTargetScreen is MainMenu) + PresentGameplay(); + return; } @@ -252,7 +256,7 @@ namespace osu.Game.Overlays.SkinEditor Debug.Assert(skinEditor != null); - if (!target.IsLoaded) + if (!target.IsLoaded || !skinEditor.IsLoaded) { Scheduler.AddOnce(setTarget, target); return; From 75b9d0fe6666eba914fc87f5428414d8003c3edf Mon Sep 17 00:00:00 2001 From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com> Date: Wed, 27 Dec 2023 23:02:45 -0800 Subject: [PATCH 034/915] Make flashlight scale with playfield When the playfield is shrunk with mods such as BarrelRoll, flashlight does not account for this, making it significantly easier to play. This makes it scale along with the playfield. --- .../Mods/TestSceneOsuModFlashlight.cs | 26 +++++++++++++++++++ osu.Game/Rulesets/Mods/ModFlashlight.cs | 13 +++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs index a353914cd5..2438038951 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs @@ -1,8 +1,13 @@ // 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.Utils; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { @@ -21,5 +26,26 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods [Test] public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new OsuModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true }); + + [Test] + public void TestPlayfieldBasedSize() + { + ModFlashlight mod = new OsuModFlashlight(); + CreateModTest(new ModTestData + { + Mod = mod, + PassCondition = () => + { + var flashlightOverlay = Player.DrawableRuleset.Overlays + .OfType.Flashlight>() + .First(); + + return Precision.AlmostEquals(mod.DefaultFlashlightSize * .5f, flashlightOverlay.GetSize()); + } + }); + + AddStep("adjust playfield scale", () => + Player.DrawableRuleset.Playfield.Scale = new Vector2(.5f)); + } } } diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 95406cc9e6..d714cd3c85 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -86,6 +86,7 @@ namespace osu.Game.Rulesets.Mods flashlight.Depth = float.MinValue; flashlight.Combo.BindTo(Combo); + flashlight.GetPlayfieldScale = () => drawableRuleset.Playfield.Scale; drawableRuleset.Overlays.Add(flashlight); } @@ -102,6 +103,8 @@ namespace osu.Game.Rulesets.Mods public override bool RemoveCompletedTransforms => false; + internal Func? GetPlayfieldScale; + private readonly float defaultFlashlightSize; private readonly float sizeMultiplier; private readonly bool comboBasedSize; @@ -141,10 +144,18 @@ namespace osu.Game.Rulesets.Mods protected abstract string FragmentShader { get; } - protected float GetSize() + public float GetSize() { float size = defaultFlashlightSize * sizeMultiplier; + if (GetPlayfieldScale != null) + { + Vector2 playfieldScale = GetPlayfieldScale(); + float rulesetScaleAvg = (playfieldScale.X + playfieldScale.Y) / 2f; + + size *= rulesetScaleAvg; + } + if (isBreakTime.Value) size *= 2.5f; else if (comboBasedSize) From d2efa2e56a34a28a2656ca30885046aa33cd06f7 Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Sun, 14 Jan 2024 15:47:50 -0500 Subject: [PATCH 035/915] peppy said he prefers the version without pipes so ill remove the pipes --- osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 0f5c94ac1d..a4ba2a27f6 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -189,14 +189,14 @@ namespace osu.Game.Beatmaps.Drawables // Difficulty row circleSize.Text = "CS: " + adjustedDifficulty.CircleSize.ToString("0.##"); - drainRate.Text = "| HP: " + adjustedDifficulty.DrainRate.ToString("0.##"); - approachRate.Text = "| AR: " + adjustedDifficulty.ApproachRate.ToString("0.##"); - overallDifficulty.Text = "| OD: " + adjustedDifficulty.OverallDifficulty.ToString("0.##"); + drainRate.Text = " HP: " + adjustedDifficulty.DrainRate.ToString("0.##"); + approachRate.Text = " AR: " + adjustedDifficulty.ApproachRate.ToString("0.##"); + overallDifficulty.Text = " OD: " + adjustedDifficulty.OverallDifficulty.ToString("0.##"); // Misc row length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length / rate).ToString("mm\\:ss"); - bpm.Text = "| BPM: " + bpmAdjusted; - maxCombo.Text = "| Max Combo: " + displayedContent.BeatmapInfo.TotalObjectCount; + bpm.Text = " BPM: " + bpmAdjusted; + maxCombo.Text = " Max Combo: " + displayedContent.BeatmapInfo.TotalObjectCount; } public void Move(Vector2 pos) => Position = pos; From 0237c9c6d712ee07a9f877b589e80bcf53591045 Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Sun, 14 Jan 2024 15:57:16 -0500 Subject: [PATCH 036/915] peppy said he prefers the version without pipes so ill remove the pipes --- global.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/global.json b/global.json index d6c2c37f77..5dcd5f425a 100644 --- a/global.json +++ b/global.json @@ -3,4 +3,5 @@ "version": "6.0.100", "rollForward": "latestFeature" } -} \ No newline at end of file +} + From b6422bc8bdb88a5b19b41992fb90bec6a966368d Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Wed, 17 Jan 2024 09:07:17 -0500 Subject: [PATCH 037/915] Apply suggested changes - Change difficultyicon mods parameter docstring to be more professional - Add a parameter for controlling whether the difficulty statistics show or not. Defaults to false - Round the BPM in the tooltip to make sure it displays correctly --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 10 ++++-- .../Drawables/DifficultyIconTooltip.cs | 34 ++++++++++--------- .../OnlinePlay/DrawableRoomPlaylistItem.cs | 2 +- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 44981003f2..9c2a435cb0 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -42,6 +42,8 @@ namespace osu.Game.Beatmaps.Drawables private readonly Mod[]? mods; + private readonly bool showTooltip; + private Drawable background = null!; private readonly Container iconContainer; @@ -61,13 +63,15 @@ namespace osu.Game.Beatmaps.Drawables /// Creates a new . Will use provided beatmap's for initial value. /// /// The beatmap to be displayed in the tooltip, and to be used for the initial star rating value. - /// The mods type beat + /// An array of mods to account for in the calculations /// An optional ruleset to be used for the icon display, in place of the beatmap's ruleset. - public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null, Mod[]? mods = null) + /// Whether to display a tooltip on hover. Defaults to false. + public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null, Mod[]? mods = null, bool showTooltip = false) : this(ruleset ?? beatmap.Ruleset) { this.beatmap = beatmap; this.mods = mods; + this.showTooltip = showTooltip; Current.Value = new StarDifficulty(beatmap.StarRating, 0); } @@ -134,6 +138,6 @@ namespace osu.Game.Beatmaps.Drawables GetCustomTooltip() => new DifficultyIconTooltip(); DifficultyIconTooltipContent IHasCustomTooltip. - TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods) : null)!; + TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods, showTooltip) : null)!; } } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index a4ba2a27f6..c5e276e6b4 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -31,6 +31,9 @@ namespace osu.Game.Beatmaps.Drawables private OsuSpriteText maxCombo; private OsuSpriteText length; + private FillFlowContainer difficultyFillFlowContainer; + private FillFlowContainer miscFillFlowContainer; + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -69,21 +72,16 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, }, // Difficulty stats - new FillFlowContainer + difficultyFillFlowContainer = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Alpha = 0, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(5), Children = new Drawable[] { - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), - }, circleSize = new OsuSpriteText { Anchor = Anchor.Centre, @@ -111,21 +109,16 @@ namespace osu.Game.Beatmaps.Drawables } }, // Misc stats - new FillFlowContainer + miscFillFlowContainer = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Alpha = 0, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(5), Children = new Drawable[] { - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), - }, length = new OsuSpriteText { Anchor = Anchor.Centre, @@ -164,6 +157,13 @@ namespace osu.Game.Beatmaps.Drawables starRating.Current.BindTarget = displayedContent.Difficulty; difficultyName.Text = displayedContent.BeatmapInfo.DifficultyName; + // Don't show difficulty stats if showTooltip is false + if (!displayedContent.ShowTooltip) return; + + // Show the difficulty stats if showTooltip is true + difficultyFillFlowContainer.Show(); + miscFillFlowContainer.Show(); + double rate = 1; if (displayedContent.Mods != null) @@ -195,7 +195,7 @@ namespace osu.Game.Beatmaps.Drawables // Misc row length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length / rate).ToString("mm\\:ss"); - bpm.Text = " BPM: " + bpmAdjusted; + bpm.Text = " BPM: " + Math.Round(bpmAdjusted, 0); maxCombo.Text = " Max Combo: " + displayedContent.BeatmapInfo.TotalObjectCount; } @@ -212,13 +212,15 @@ namespace osu.Game.Beatmaps.Drawables public readonly IBindable Difficulty; public readonly IRulesetInfo Ruleset; public readonly Mod[] Mods; + public readonly bool ShowTooltip; - public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[] mods) + public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[] mods, bool showTooltip = false) { BeatmapInfo = beatmapInfo; Difficulty = difficulty; Ruleset = rulesetInfo; Mods = mods; + ShowTooltip = showTooltip; } } } diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index eb23ed6f8f..2a6387871f 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -283,7 +283,7 @@ namespace osu.Game.Screens.OnlinePlay } if (beatmap != null) - difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods) { Size = new Vector2(icon_height) }; + difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods, true) { Size = new Vector2(icon_height) }; else difficultyIconContainer.Clear(); From 9a6541356eb32899ffc54bd1db2a151e3db5b42e Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Wed, 17 Jan 2024 13:31:23 -0500 Subject: [PATCH 038/915] Refactor the extended tooltip variables to be more descriptive --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 10 +++++----- osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 9c2a435cb0..7a9b2fe389 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -42,7 +42,7 @@ namespace osu.Game.Beatmaps.Drawables private readonly Mod[]? mods; - private readonly bool showTooltip; + private readonly bool showExtendedTooltip; private Drawable background = null!; @@ -65,13 +65,13 @@ namespace osu.Game.Beatmaps.Drawables /// The beatmap to be displayed in the tooltip, and to be used for the initial star rating value. /// An array of mods to account for in the calculations /// An optional ruleset to be used for the icon display, in place of the beatmap's ruleset. - /// Whether to display a tooltip on hover. Defaults to false. - public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null, Mod[]? mods = null, bool showTooltip = false) + /// Whether to include the difficulty stats in the tooltip or not. Defaults to false + public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null, Mod[]? mods = null, bool showExtendedTooltip = false) : this(ruleset ?? beatmap.Ruleset) { this.beatmap = beatmap; this.mods = mods; - this.showTooltip = showTooltip; + this.showExtendedTooltip = showExtendedTooltip; Current.Value = new StarDifficulty(beatmap.StarRating, 0); } @@ -138,6 +138,6 @@ namespace osu.Game.Beatmaps.Drawables GetCustomTooltip() => new DifficultyIconTooltip(); DifficultyIconTooltipContent IHasCustomTooltip. - TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods, showTooltip) : null)!; + TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods, showExtendedTooltip) : null)!; } } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index c5e276e6b4..fae4100473 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -157,10 +157,10 @@ namespace osu.Game.Beatmaps.Drawables starRating.Current.BindTarget = displayedContent.Difficulty; difficultyName.Text = displayedContent.BeatmapInfo.DifficultyName; - // Don't show difficulty stats if showTooltip is false - if (!displayedContent.ShowTooltip) return; + // Don't show difficulty stats if showExtendedTooltip is false + if (!displayedContent.ShowExtendedTooltip) return; - // Show the difficulty stats if showTooltip is true + // Show the difficulty stats if showExtendedTooltip is true difficultyFillFlowContainer.Show(); miscFillFlowContainer.Show(); @@ -212,15 +212,15 @@ namespace osu.Game.Beatmaps.Drawables public readonly IBindable Difficulty; public readonly IRulesetInfo Ruleset; public readonly Mod[] Mods; - public readonly bool ShowTooltip; + public readonly bool ShowExtendedTooltip; - public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[] mods, bool showTooltip = false) + public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[] mods, bool showExtendedTooltip = false) { BeatmapInfo = beatmapInfo; Difficulty = difficulty; Ruleset = rulesetInfo; Mods = mods; - ShowTooltip = showTooltip; + ShowExtendedTooltip = showExtendedTooltip; } } } From 060ea1d4fd82899991eae7b9cdd8468c18dc551c Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:04:13 -0500 Subject: [PATCH 039/915] Switch from using a constructor argument to using a public field for ShowExtendedTooltip --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 13 +++++++------ .../Screens/OnlinePlay/DrawableRoomPlaylistItem.cs | 8 +++++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 7a9b2fe389..fc78d6f322 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -36,14 +36,17 @@ namespace osu.Game.Beatmaps.Drawables /// public bool ShowTooltip { get; set; } = true; + /// + /// Whether to include the difficulty stats in the tooltip or not. Defaults to false. Has no effect if is false. + /// + public bool ShowExtendedTooltip { get; set; } + private readonly IBeatmapInfo? beatmap; private readonly IRulesetInfo ruleset; private readonly Mod[]? mods; - private readonly bool showExtendedTooltip; - private Drawable background = null!; private readonly Container iconContainer; @@ -65,13 +68,11 @@ namespace osu.Game.Beatmaps.Drawables /// The beatmap to be displayed in the tooltip, and to be used for the initial star rating value. /// An array of mods to account for in the calculations /// An optional ruleset to be used for the icon display, in place of the beatmap's ruleset. - /// Whether to include the difficulty stats in the tooltip or not. Defaults to false - public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null, Mod[]? mods = null, bool showExtendedTooltip = false) + public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null, Mod[]? mods = null) : this(ruleset ?? beatmap.Ruleset) { this.beatmap = beatmap; this.mods = mods; - this.showExtendedTooltip = showExtendedTooltip; Current.Value = new StarDifficulty(beatmap.StarRating, 0); } @@ -138,6 +139,6 @@ namespace osu.Game.Beatmaps.Drawables GetCustomTooltip() => new DifficultyIconTooltip(); DifficultyIconTooltipContent IHasCustomTooltip. - TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods, showExtendedTooltip) : null)!; + TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods, ShowExtendedTooltip) : null)!; } } diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 2a6387871f..8cfdc2e0e2 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -283,7 +283,13 @@ namespace osu.Game.Screens.OnlinePlay } if (beatmap != null) - difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods, true) { Size = new Vector2(icon_height) }; + { + difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods) + { + Size = new Vector2(icon_height), + ShowExtendedTooltip = true + }; + } else difficultyIconContainer.Clear(); From d80a5d44eedca57e8be969d771152edb4fe4b229 Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Thu, 18 Jan 2024 03:17:37 -0500 Subject: [PATCH 040/915] Add tests for DifficultyIcon --- .../Beatmaps/TestSceneDifficultyIcon.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs new file mode 100644 index 0000000000..aa2543eea1 --- /dev/null +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Platform; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Tests.Visual.Beatmaps +{ + public partial class TestSceneDifficultyIcon : OsuTestScene + { + [Test] + public void createDifficultyIcon() + { + DifficultyIcon difficultyIcon = null; + + AddStep("create difficulty icon", () => + { + Child = difficultyIcon = new DifficultyIcon(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, new OsuRuleset().RulesetInfo) + { + ShowTooltip = true, + ShowExtendedTooltip = true + }; + }); + + AddStep("hide extended tooltip", () => difficultyIcon.ShowExtendedTooltip = false); + + AddStep("hide tooltip", () => difficultyIcon.ShowTooltip = false); + + AddStep("show tooltip", () => difficultyIcon.ShowTooltip = true); + + AddStep("show extended tooltip", () => difficultyIcon.ShowExtendedTooltip = true); + } + } +} From 5c70c786b4581d91c5b2d069e04b9d774cf79351 Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Thu, 18 Jan 2024 03:18:44 -0500 Subject: [PATCH 041/915] Fix extended tooltip content still being shown despite ShowExtendedTooltip being false --- osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index fae4100473..fe23b49346 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -158,7 +158,12 @@ namespace osu.Game.Beatmaps.Drawables difficultyName.Text = displayedContent.BeatmapInfo.DifficultyName; // Don't show difficulty stats if showExtendedTooltip is false - if (!displayedContent.ShowExtendedTooltip) return; + if (!displayedContent.ShowExtendedTooltip) + { + difficultyFillFlowContainer.Hide(); + miscFillFlowContainer.Hide(); + return; + } // Show the difficulty stats if showExtendedTooltip is true difficultyFillFlowContainer.Show(); From c9945b41c1007ab2ff18900d1d70686598e57b9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 Jan 2024 18:36:25 +0900 Subject: [PATCH 042/915] Remove rounding of slider velocity (when applied as scroll speed) This affects both osu!taiko and osu!mania. Closes https://github.com/ppy/osu/issues/25862. --- osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 7edf892f35..0138ac7569 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -21,7 +21,6 @@ namespace osu.Game.Beatmaps.ControlPoints /// public readonly BindableDouble ScrollSpeedBindable = new BindableDouble(1) { - Precision = 0.01, MinValue = 0.01, MaxValue = 10 }; From 87369f8a808b29e3da0bde82027a439e763532dc Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:16:03 -0500 Subject: [PATCH 043/915] Conform to code style & remove unused imports --- osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs index aa2543eea1..79f9aec2e3 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs @@ -4,11 +4,7 @@ #nullable disable using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Platform; using osu.Game.Beatmaps.Drawables; -using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Tests.Beatmaps; @@ -17,7 +13,7 @@ namespace osu.Game.Tests.Visual.Beatmaps public partial class TestSceneDifficultyIcon : OsuTestScene { [Test] - public void createDifficultyIcon() + public void CreateDifficultyIcon() { DifficultyIcon difficultyIcon = null; From ce4fd6aca51690455f9a1f02ada35d95269883ed Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 19 Jan 2024 23:48:05 +0300 Subject: [PATCH 044/915] Rename `DEFAULT_HEIGHT` to `BASE_HEIGHT` --- .../Edit/Blueprints/HitPlacementBlueprint.cs | 2 +- .../Edit/Blueprints/TaikoSpanPlacementBlueprint.cs | 6 +++--- osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs | 2 +- .../Skinning/Legacy/TaikoLegacyHitTarget.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs index 8b1a4f688c..329fff5b42 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { InternalChild = piece = new HitPiece { - Size = new Vector2(TaikoHitObject.DEFAULT_SIZE * TaikoPlayfield.DEFAULT_HEIGHT) + Size = new Vector2(TaikoHitObject.DEFAULT_SIZE * TaikoPlayfield.BASE_HEIGHT) }; } diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs index b0919417a4..cd52398086 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs @@ -39,15 +39,15 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { headPiece = new HitPiece { - Size = new Vector2(TaikoHitObject.DEFAULT_SIZE * TaikoPlayfield.DEFAULT_HEIGHT) + Size = new Vector2(TaikoHitObject.DEFAULT_SIZE * TaikoPlayfield.BASE_HEIGHT) }, lengthPiece = new LengthPiece { - Height = TaikoHitObject.DEFAULT_SIZE * TaikoPlayfield.DEFAULT_HEIGHT + Height = TaikoHitObject.DEFAULT_SIZE * TaikoPlayfield.BASE_HEIGHT }, tailPiece = new HitPiece { - Size = new Vector2(TaikoHitObject.DEFAULT_SIZE * TaikoPlayfield.DEFAULT_HEIGHT) + Size = new Vector2(TaikoHitObject.DEFAULT_SIZE * TaikoPlayfield.BASE_HEIGHT) } }; } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index 733772e21f..26bbb6d71b 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Mods /// private Vector2 adjustSizeForPlayfieldAspectRatio(float size) { - return new Vector2(0, size * taikoPlayfield.DrawHeight / TaikoPlayfield.DEFAULT_HEIGHT); + return new Vector2(0, size * taikoPlayfield.DrawHeight / TaikoPlayfield.BASE_HEIGHT); } protected override void UpdateFlashlightSize(float size) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs index 492782f0d1..2f845adcd8 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy // Relying on RelativeSizeAxes.Both + FillMode.Fit doesn't work due to the precise pixel layout requirements. // This is a bit ugly but makes the non-legacy implementations a lot cleaner to implement. - content.Scale = new Vector2(DrawHeight / TaikoPlayfield.DEFAULT_HEIGHT); + content.Scale = new Vector2(DrawHeight / TaikoPlayfield.BASE_HEIGHT); } } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 7e3ed7a4d4..af4ed0557a 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -28,9 +28,9 @@ namespace osu.Game.Rulesets.Taiko.UI public partial class TaikoPlayfield : ScrollingPlayfield { /// - /// Default height of a when inside a . + /// Base height of a when inside a . /// - public const float DEFAULT_HEIGHT = 200; + public const float BASE_HEIGHT = 200; /// /// Whether the hit target should be nudged further towards the left area, matching the stable "classic" position. From 3e17d01cebc88c56615f67c0deea7351168a46b1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 19 Jan 2024 23:49:14 +0300 Subject: [PATCH 045/915] Rewrite taiko playfield adjustment container to keep height constant --- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 54608b77de..1bc9f7d89c 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -5,23 +5,31 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.UI; +using osuTK; namespace osu.Game.Rulesets.Taiko.UI { public partial class TaikoPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { - private const float default_relative_height = TaikoPlayfield.DEFAULT_HEIGHT / 768; - public const float MAXIMUM_ASPECT = 16f / 9f; public const float MINIMUM_ASPECT = 5f / 4f; public readonly IBindable LockPlayfieldAspectRange = new BindableBool(true); + public TaikoPlayfieldAdjustmentContainer() + { + RelativeSizeAxes = Axes.X; + RelativePositionAxes = Axes.Y; + Height = TaikoPlayfield.BASE_HEIGHT; + } + protected override void Update() { base.Update(); - float height = default_relative_height; + const float base_relative_height = TaikoPlayfield.BASE_HEIGHT / 768; + + float relativeHeight = base_relative_height; // Players coming from stable expect to be able to change the aspect ratio regardless of the window size. // We originally wanted to limit this more, but there was considerable pushback from the community. @@ -33,19 +41,20 @@ namespace osu.Game.Rulesets.Taiko.UI float currentAspect = Parent!.ChildSize.X / Parent!.ChildSize.Y; if (currentAspect > MAXIMUM_ASPECT) - height *= currentAspect / MAXIMUM_ASPECT; + relativeHeight *= currentAspect / MAXIMUM_ASPECT; else if (currentAspect < MINIMUM_ASPECT) - height *= currentAspect / MINIMUM_ASPECT; + relativeHeight *= currentAspect / MINIMUM_ASPECT; } // Limit the maximum relative height of the playfield to one-third of available area to avoid it masking out on extreme resolutions. - height = Math.Min(height, 1f / 3f); - Height = height; + relativeHeight = Math.Min(relativeHeight, 1f / 3f); // Position the taiko playfield exactly one playfield from the top of the screen, if there is enough space for it. // Note that the relative height cannot exceed one-third - if that limit is hit, the playfield will be exactly centered. - RelativePositionAxes = Axes.Y; - Y = height; + Y = relativeHeight; + + Scale = new Vector2(Math.Max(relativeHeight / base_relative_height, 1f)); + Width = 1 / Scale.X; } } } From f5ce9eaf7512b27c9df3b03adb8d8a76b7462969 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 19 Jan 2024 23:58:55 +0300 Subject: [PATCH 046/915] Refactor taiko playfield layout to use constant values --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 38 ++++++++------------ 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index af4ed0557a..4e1691ffe0 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -21,7 +21,6 @@ using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Skinning; -using osuTK; namespace osu.Game.Rulesets.Taiko.UI { @@ -44,7 +43,6 @@ namespace osu.Game.Rulesets.Taiko.UI private JudgementContainer judgementContainer = null!; private ScrollingHitObjectContainer drumRollHitContainer = null!; internal Drawable HitTarget = null!; - private SkinnableDrawable mascot = null!; private JudgementPooler judgementPooler = null!; private readonly IDictionary explosionPools = new Dictionary(); @@ -59,13 +57,11 @@ namespace osu.Game.Rulesets.Taiko.UI /// private BarLinePlayfield barLinePlayfield = null!; - private Container barLineContent = null!; - private Container hitObjectContent = null!; - private Container overlayContent = null!; - [BackgroundDependencyLoader] private void load(OsuColour colours) { + const float hit_target_width = BASE_HEIGHT; + inputDrum = new InputDrum { Anchor = Anchor.CentreLeft, @@ -89,7 +85,7 @@ namespace osu.Game.Rulesets.Taiko.UI inputDrum.CreateProxy(), } }, - mascot = new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.Mascot), _ => Empty()) + new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.Mascot), _ => Empty()) { Origin = Anchor.BottomLeft, Anchor = Anchor.TopLeft, @@ -101,14 +97,13 @@ namespace osu.Game.Rulesets.Taiko.UI { Name = "Right area", RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Both, Children = new Drawable[] { new Container { - Name = "Elements before hit objects", - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, + Name = "Elements behind hit objects", + RelativeSizeAxes = Axes.Y, + Width = hit_target_width, Children = new[] { new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.KiaiGlow), _ => Empty()) @@ -125,10 +120,11 @@ namespace osu.Game.Rulesets.Taiko.UI } } }, - barLineContent = new Container + new Container { Name = "Bar line content", RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = hit_target_width / 2 }, Children = new Drawable[] { UnderlayElements = new Container @@ -138,17 +134,19 @@ namespace osu.Game.Rulesets.Taiko.UI barLinePlayfield = new BarLinePlayfield(), } }, - hitObjectContent = new Container + new Container { Name = "Masked hit objects content", RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = hit_target_width / 2 }, Masking = true, Child = HitObjectContainer, }, - overlayContent = new Container + new Container { - Name = "Elements after hit objects", + Name = "Overlay content", RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = hit_target_width / 2 }, Children = new Drawable[] { drumRollHitContainer = new DrumRollHitContainer(), @@ -226,14 +224,8 @@ namespace osu.Game.Rulesets.Taiko.UI { base.Update(); - // Padding is required to be updated for elements which are based on "absolute" X sized elements. - // This is basically allowing for correct alignment as relative pieces move around them. - rightArea.Padding = new MarginPadding { Left = inputDrum.Width }; - barLineContent.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 }; - hitObjectContent.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 }; - overlayContent.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 }; - - mascot.Scale = new Vector2(DrawHeight / DEFAULT_HEIGHT); + // todo: input drum width should be constant. + rightArea.Padding = new MarginPadding { Left = inputDrum.DrawWidth }; } #region Pooling support From fa2c33c64173d51d5ad14654e12e3f956f17cac8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 20 Jan 2024 00:20:43 +0300 Subject: [PATCH 047/915] Upscale playfield by difference in game height as well I honestly don't have much clue about this one but doing so matches master. --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 1bc9f7d89c..57722b8065 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Taiko.UI // Note that the relative height cannot exceed one-third - if that limit is hit, the playfield will be exactly centered. Y = relativeHeight; - Scale = new Vector2(Math.Max(relativeHeight / base_relative_height, 1f)); + Scale = new Vector2(Math.Max((Parent!.ChildSize.Y / 768f) * (relativeHeight / base_relative_height), 1f)); Width = 1 / Scale.X; } } From 0c03326eaf1bb5954b118c8f58ba721b8058fc8b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 20 Jan 2024 01:25:04 +0300 Subject: [PATCH 048/915] Update remaining usages of playfield height --- osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs | 2 +- .../Skinning/Legacy/TaikoLegacyHitTarget.cs | 14 +------------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index 26bbb6d71b..64f2f4c18a 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Mods /// private Vector2 adjustSizeForPlayfieldAspectRatio(float size) { - return new Vector2(0, size * taikoPlayfield.DrawHeight / TaikoPlayfield.BASE_HEIGHT); + return new Vector2(0, size * taikoPlayfield.Parent!.Scale.Y); } protected override void UpdateFlashlightSize(float size) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs index 2f845adcd8..cf9d8dd52e 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Game.Rulesets.Taiko.UI; using osu.Game.Skinning; using osuTK; @@ -13,14 +12,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { public partial class TaikoLegacyHitTarget : CompositeDrawable { - private Container content = null!; - [BackgroundDependencyLoader] private void load(ISkinSource skin) { RelativeSizeAxes = Axes.Both; - InternalChild = content = new Container + InternalChild = new Container { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, @@ -46,14 +43,5 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy } }; } - - protected override void Update() - { - base.Update(); - - // Relying on RelativeSizeAxes.Both + FillMode.Fit doesn't work due to the precise pixel layout requirements. - // This is a bit ugly but makes the non-legacy implementations a lot cleaner to implement. - content.Scale = new Vector2(DrawHeight / TaikoPlayfield.BASE_HEIGHT); - } } } From d4fef99e1f677fa3af1e1822ff9d9f2116a4be59 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 19 Jan 2024 23:26:35 +0300 Subject: [PATCH 049/915] Define constant input drum width for osu!taiko --- .../Skinning/TestSceneInputDrum.cs | 7 +++-- .../Skinning/Argon/ArgonInputDrum.cs | 2 +- .../Skinning/Default/DefaultInputDrum.cs | 2 +- .../Skinning/Legacy/LegacyInputDrum.cs | 28 ++++++------------- osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 9 +----- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 20 +++++-------- 6 files changed, 24 insertions(+), 44 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs index 3c6319ddf9..900d6523cf 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs @@ -30,8 +30,11 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(200), - Child = new InputDrum() + Size = new Vector2(180f, 200f), + Child = new InputDrum + { + RelativeSizeAxes = Axes.Both, + } } }); } diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs index f7b7105bdc..f22c7bf017 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon public ArgonInputDrum() { - RelativeSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs index 60bacf6413..3eb4f6b8a6 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default { public DefaultInputDrum() { - RelativeSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs index 8ad419f8bd..07a7f237ba 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Taiko.UI; using osu.Game.Skinning; using osuTK; @@ -18,22 +19,20 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy /// internal partial class LegacyInputDrum : Container { - private Container content = null!; private LegacyHalfDrum left = null!; private LegacyHalfDrum right = null!; public LegacyInputDrum() { - RelativeSizeAxes = Axes.Y; - AutoSizeAxes = Axes.X; + RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load(ISkinSource skin) { - Child = content = new Container + Child = new Container { - Size = new Vector2(180, 200), + RelativeSizeAxes = Axes.Both, Children = new Drawable[] { new Sprite @@ -66,33 +65,24 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy const float ratio = 1.6f; // 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; + const float negative_scale_adjust = TaikoPlayfield.INPUT_DRUM_WIDTH / ratio; 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; + right.Centre.Position = new Vector2(negative_scale_adjust - 56, taiko_bar_y) * ratio; left.Rim.Position = new Vector2(0, taiko_bar_y) * ratio; - right.Rim.Position = new Vector2(negativeScaleAdjust - 56, taiko_bar_y) * ratio; + right.Rim.Position = new Vector2(negative_scale_adjust - 56, taiko_bar_y) * ratio; } else { left.Centre.Position = new Vector2(18, taiko_bar_y + 31) * ratio; - right.Centre.Position = new Vector2(negativeScaleAdjust - 54, taiko_bar_y + 31) * ratio; + right.Centre.Position = new Vector2(negative_scale_adjust - 54, taiko_bar_y + 31) * ratio; left.Rim.Position = new Vector2(8, taiko_bar_y + 23) * ratio; - right.Rim.Position = new Vector2(negativeScaleAdjust - 53, taiko_bar_y + 23) * ratio; + right.Rim.Position = new Vector2(negative_scale_adjust - 53, taiko_bar_y + 23) * ratio; } } - protected override void Update() - { - base.Update(); - - // Relying on RelativeSizeAxes.Both + FillMode.Fit doesn't work due to the precise pixel layout requirements. - // This is a bit ugly but makes the non-legacy implementations a lot cleaner to implement. - content.Scale = new Vector2(DrawHeight / content.Size.Y); - } - /// /// A half-drum. Contains one centre and one rim hit. /// diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 725857ed34..d0a8cf647d 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -14,12 +14,6 @@ namespace osu.Game.Rulesets.Taiko.UI /// internal partial class InputDrum : Container { - public InputDrum() - { - AutoSizeAxes = Axes.X; - RelativeSizeAxes = Axes.Y; - } - [BackgroundDependencyLoader] private void load() { @@ -27,8 +21,7 @@ namespace osu.Game.Rulesets.Taiko.UI { new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.InputDrum), _ => new DefaultInputDrum()) { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Both, }, }; } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 4e1691ffe0..95907bcb8b 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -31,6 +31,8 @@ namespace osu.Game.Rulesets.Taiko.UI /// public const float BASE_HEIGHT = 200; + public const float INPUT_DRUM_WIDTH = 180f; + /// /// Whether the hit target should be nudged further towards the left area, matching the stable "classic" position. /// @@ -49,7 +51,6 @@ namespace osu.Game.Rulesets.Taiko.UI private ProxyContainer topLevelHitContainer = null!; private InputDrum inputDrum = null!; - private Container rightArea = null!; /// /// is purposefully not called on this to prevent i.e. being able to interact @@ -66,8 +67,8 @@ namespace osu.Game.Rulesets.Taiko.UI { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.X, RelativeSizeAxes = Axes.Y, + Width = INPUT_DRUM_WIDTH, }; InternalChildren = new[] @@ -76,8 +77,8 @@ namespace osu.Game.Rulesets.Taiko.UI new Container { Name = "Left overlay", - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Y, + Width = INPUT_DRUM_WIDTH, BorderColour = colours.Gray0, Children = new[] { @@ -93,10 +94,11 @@ namespace osu.Game.Rulesets.Taiko.UI RelativeSizeAxes = Axes.None, Y = 0.2f }, - rightArea = new Container + new Container { Name = "Right area", RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = INPUT_DRUM_WIDTH }, Children = new Drawable[] { new Container @@ -220,14 +222,6 @@ namespace osu.Game.Rulesets.Taiko.UI topLevelHitContainer.Add(taikoObject.CreateProxiedContent()); } - protected override void Update() - { - base.Update(); - - // todo: input drum width should be constant. - rightArea.Padding = new MarginPadding { Left = inputDrum.DrawWidth }; - } - #region Pooling support public override void Add(HitObject h) From 2f618b7f35514f1025d4750cb3726e670f4aa2d8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 20 Jan 2024 00:28:26 +0300 Subject: [PATCH 050/915] Change taiko hit position to always match stable --- osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs | 3 --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 14 +++++--------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs index cdeaafde10..f63d6c2673 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs @@ -16,9 +16,6 @@ namespace osu.Game.Rulesets.Taiko.Mods { var drawableTaikoRuleset = (DrawableTaikoRuleset)drawableRuleset; drawableTaikoRuleset.LockPlayfieldAspectRange.Value = false; - - var playfield = (TaikoPlayfield)drawableRuleset.Playfield; - playfield.ClassicHitTargetPosition.Value = true; } public void ApplyToDrawableHitObject(DrawableHitObject drawable) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 95907bcb8b..0510f08068 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -33,11 +32,6 @@ namespace osu.Game.Rulesets.Taiko.UI public const float INPUT_DRUM_WIDTH = 180f; - /// - /// Whether the hit target should be nudged further towards the left area, matching the stable "classic" position. - /// - public Bindable ClassicHitTargetPosition = new BindableBool(); - public Container UnderlayElements { get; private set; } = null!; private Container hitExplosionContainer = null!; @@ -62,6 +56,7 @@ namespace osu.Game.Rulesets.Taiko.UI private void load(OsuColour colours) { const float hit_target_width = BASE_HEIGHT; + const float hit_target_offset = -24f; inputDrum = new InputDrum { @@ -106,6 +101,7 @@ namespace osu.Game.Rulesets.Taiko.UI Name = "Elements behind hit objects", RelativeSizeAxes = Axes.Y, Width = hit_target_width, + X = hit_target_offset, Children = new[] { new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.KiaiGlow), _ => Empty()) @@ -126,7 +122,7 @@ namespace osu.Game.Rulesets.Taiko.UI { Name = "Bar line content", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = hit_target_width / 2 }, + Padding = new MarginPadding { Left = hit_target_width / 2 + hit_target_offset }, Children = new Drawable[] { UnderlayElements = new Container @@ -140,7 +136,7 @@ namespace osu.Game.Rulesets.Taiko.UI { Name = "Masked hit objects content", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = hit_target_width / 2 }, + Padding = new MarginPadding { Left = hit_target_width / 2 + hit_target_offset }, Masking = true, Child = HitObjectContainer, }, @@ -148,7 +144,7 @@ namespace osu.Game.Rulesets.Taiko.UI { Name = "Overlay content", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = hit_target_width / 2 }, + Padding = new MarginPadding { Left = hit_target_width / 2 + hit_target_offset }, Children = new Drawable[] { drumRollHitContainer = new DrumRollHitContainer(), From d8cba1cbfdee1b39b1403e90bcad33444d4e1acb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 20 Jan 2024 00:22:32 +0300 Subject: [PATCH 051/915] Move taiko playfield down a nudge to visually match stable --- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 57722b8065..9a5fc90a05 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -51,7 +51,12 @@ namespace osu.Game.Rulesets.Taiko.UI // Position the taiko playfield exactly one playfield from the top of the screen, if there is enough space for it. // Note that the relative height cannot exceed one-third - if that limit is hit, the playfield will be exactly centered. - Y = relativeHeight; + float playfieldPosition = relativeHeight; + + // arbitrary offset to make playfield position match stable. + playfieldPosition += 0.022f; + + Y = playfieldPosition; Scale = new Vector2(Math.Max((Parent!.ChildSize.Y / 768f) * (relativeHeight / base_relative_height), 1f)); Width = 1 / Scale.X; From f12be60d8d33471fc8acb4ee54c369f4f4e928e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jan 2024 17:18:22 +0900 Subject: [PATCH 052/915] Make test actually test multiple icons --- .../Beatmaps/TestSceneDifficultyIcon.cs | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs index 79f9aec2e3..80320c138b 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs @@ -4,27 +4,58 @@ #nullable disable using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; using osu.Game.Beatmaps.Drawables; using osu.Game.Rulesets.Osu; using osu.Game.Tests.Beatmaps; +using osuTK; namespace osu.Game.Tests.Visual.Beatmaps { public partial class TestSceneDifficultyIcon : OsuTestScene { + private FillFlowContainer fill; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Child = fill = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 300, + Direction = FillDirection.Full, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + } + [Test] public void CreateDifficultyIcon() { DifficultyIcon difficultyIcon = null; - AddStep("create difficulty icon", () => + AddRepeatStep("create difficulty icon", () => { - Child = difficultyIcon = new DifficultyIcon(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, new OsuRuleset().RulesetInfo) + var rulesetInfo = new OsuRuleset().RulesetInfo; + var beatmapInfo = new TestBeatmap(rulesetInfo).BeatmapInfo; + + beatmapInfo.Difficulty.ApproachRate = RNG.Next(0, 10); + beatmapInfo.Difficulty.CircleSize = RNG.Next(0, 10); + beatmapInfo.Difficulty.OverallDifficulty = RNG.Next(0, 10); + beatmapInfo.Difficulty.DrainRate = RNG.Next(0, 10); + beatmapInfo.StarRating = RNG.NextSingle(0, 10); + beatmapInfo.BPM = RNG.Next(60, 300); + + fill.Add(difficultyIcon = new DifficultyIcon(beatmapInfo, rulesetInfo) { + Scale = new Vector2(2), ShowTooltip = true, ShowExtendedTooltip = true - }; - }); + }); + }, 10); AddStep("hide extended tooltip", () => difficultyIcon.ShowExtendedTooltip = false); From 2305a53a02b23185d83a9740ce876350adc711cc Mon Sep 17 00:00:00 2001 From: smallketchup82 <69545310+smallketchup82@users.noreply.github.com> Date: Mon, 22 Jan 2024 08:59:37 -0500 Subject: [PATCH 053/915] Remove max combo reading & remove unnecessary commas --- .../Drawables/DifficultyIconTooltip.cs | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index fe23b49346..7fe0080e89 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -28,7 +28,6 @@ namespace osu.Game.Beatmaps.Drawables private OsuSpriteText circleSize; private OsuSpriteText approachRate; private OsuSpriteText bpm; - private OsuSpriteText maxCombo; private OsuSpriteText length; private FillFlowContainer difficultyFillFlowContainer; @@ -64,12 +63,12 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold), + Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold) }, starRating = new StarRatingDisplay(default, StarRatingDisplaySize.Small) { Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Origin = Anchor.Centre }, // Difficulty stats difficultyFillFlowContainer = new FillFlowContainer @@ -86,26 +85,26 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14), + Font = OsuFont.GetFont(size: 14) }, drainRate = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14), + Font = OsuFont.GetFont(size: 14) }, approachRate = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14), + Font = OsuFont.GetFont(size: 14) }, overallDifficulty = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14), - }, + Font = OsuFont.GetFont(size: 14) + } } }, // Misc stats @@ -123,19 +122,13 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14), + Font = OsuFont.GetFont(size: 14) }, bpm = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14), - }, - maxCombo = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14), + Font = OsuFont.GetFont(size: 14) }, } } @@ -201,7 +194,6 @@ namespace osu.Game.Beatmaps.Drawables // Misc row length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length / rate).ToString("mm\\:ss"); bpm.Text = " BPM: " + Math.Round(bpmAdjusted, 0); - maxCombo.Text = " Max Combo: " + displayedContent.BeatmapInfo.TotalObjectCount; } public void Move(Vector2 pos) => Position = pos; From d0d09a86578854c30e802083dd4d977a967db1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 23 Jan 2024 16:55:00 +0100 Subject: [PATCH 054/915] Fix login overlay test not clearing second auth factor --- osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index 0c5f5a321c..0c0edca995 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -89,6 +89,12 @@ namespace osu.Game.Tests.Visual.Menus AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + assertAPIState(APIState.RequiresSecondFactorAuth); + AddUntilStep("wait for second factor auth form", () => loginOverlay.ChildrenOfType().SingleOrDefault(), () => Is.Not.Null); + + AddStep("enter code", () => loginOverlay.ChildrenOfType().First().Text = "88800088"); + assertAPIState(APIState.Online); + AddStep("click on flag", () => { InputManager.MoveMouseTo(loginOverlay.ChildrenOfType().First()); From d7e957087ebb348df86692c7ab525f27df8bf4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 23 Jan 2024 16:56:39 +0100 Subject: [PATCH 055/915] Fix account creation overlay test not clearing second auth factor --- .../Visual/Online/TestSceneAccountCreationOverlay.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index 0f920643f0..79fb063ea9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.AccountCreation; @@ -59,7 +60,11 @@ namespace osu.Game.Tests.Visual.Online AddStep("click button", () => accountCreation.ChildrenOfType().Single().TriggerClick()); AddUntilStep("warning screen is present", () => accountCreation.ChildrenOfType().SingleOrDefault()?.IsPresent == true); - AddStep("log back in", () => API.Login("dummy", "password")); + AddStep("log back in", () => + { + API.Login("dummy", "password"); + ((DummyAPIAccess)API).AuthenticateSecondFactor("abcdefgh"); + }); AddUntilStep("overlay is hidden", () => accountCreation.State.Value == Visibility.Hidden); } } From 5d26afc53175678fc241379dcde7d286b72e91c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 23 Jan 2024 17:00:07 +0100 Subject: [PATCH 056/915] Fix `OsuGameTestScene` not clearing second auth factor --- osu.Game/Tests/Visual/OsuGameTestScene.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Tests/Visual/OsuGameTestScene.cs b/osu.Game/Tests/Visual/OsuGameTestScene.cs index 947305439e..6069fe4fb0 100644 --- a/osu.Game/Tests/Visual/OsuGameTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGameTestScene.cs @@ -178,6 +178,7 @@ namespace osu.Game.Tests.Visual LocalConfig.SetValue(OsuSetting.ShowFirstRunSetup, false); API.Login("Rhythm Champion", "osu!"); + ((DummyAPIAccess)API).AuthenticateSecondFactor("abcdefgh"); Dependencies.Get().SetValue(Static.MutedAudioNotificationShownOnce, true); From 0d7834af5fc5f4f8dc7f67903cced787b39416df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 23 Jan 2024 18:04:41 +0100 Subject: [PATCH 057/915] Ensure all remaining test usages of `IAPIAccess.Login()` also authenticate with second factor --- .../Gameplay/TestScenePlayerLocalScoreImport.cs | 6 +++++- .../Visual/Menus/TestSceneToolbarUserButton.cs | 12 ++++++++---- .../Visual/Online/TestSceneCommentActions.cs | 1 + .../Visual/Online/TestSceneFavouriteButton.cs | 13 +++++++++++-- .../Visual/Online/TestSceneSoloStatisticsWatcher.cs | 6 +++++- .../Visual/Online/TestSceneUserProfileOverlay.cs | 12 ++++++++++-- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 7 ++++++- .../Visual/UserInterface/TestSceneCommentEditor.cs | 6 +++++- 8 files changed, 51 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs index fafd1330cc..22422a685e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs @@ -184,7 +184,11 @@ namespace osu.Game.Tests.Visual.Gameplay CreateTest(); AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); - AddStep("log back in", () => API.Login("username", "password")); + AddStep("log back in", () => + { + API.Login("username", "password"); + ((DummyAPIAccess)API).AuthenticateSecondFactor("abcdefgh"); + }); AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs index 2bdfc8959d..f0506ed35c 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs @@ -16,6 +16,8 @@ namespace osu.Game.Tests.Visual.Menus [TestFixture] public partial class TestSceneToolbarUserButton : OsuManualInputManagerTestScene { + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + public TestSceneToolbarUserButton() { Container mainContainer; @@ -69,18 +71,20 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestLoginLogout() { - AddStep("Log out", () => ((DummyAPIAccess)API).Logout()); - AddStep("Log in", () => ((DummyAPIAccess)API).Login("wang", "jang")); + AddStep("Log out", () => dummyAPI.Logout()); + AddStep("Log in", () => dummyAPI.Login("wang", "jang")); + AddStep("Authenticate via second factor", () => dummyAPI.AuthenticateSecondFactor("abcdefgh")); } [Test] public void TestStates() { - AddStep("Log in", () => ((DummyAPIAccess)API).Login("wang", "jang")); + AddStep("Log in", () => dummyAPI.Login("wang", "jang")); + AddStep("Authenticate via second factor", () => dummyAPI.AuthenticateSecondFactor("abcdefgh")); foreach (var state in Enum.GetValues()) { - AddStep($"Change state to {state}", () => ((DummyAPIAccess)API).SetState(state)); + AddStep($"Change state to {state}", () => dummyAPI.SetState(state)); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs index 10fdffb8e1..f47322b9e0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs @@ -67,6 +67,7 @@ namespace osu.Game.Tests.Visual.Online Schedule(() => { API.Login("test", "test"); + dummyAPI.AuthenticateSecondFactor("abcdefgh"); Child = commentsContainer = new CommentsContainer(); }); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs index 3954fd5cff..0acf8336e3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing; +using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Buttons; using osuTK; @@ -34,14 +35,22 @@ namespace osu.Game.Tests.Visual.Online AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new APIBeatmapSet { OnlineID = 88 }); AddStep("log out", () => API.Logout()); checkEnabled(false); - AddStep("log in", () => API.Login("test", "test")); + AddStep("log in", () => + { + API.Login("test", "test"); + ((DummyAPIAccess)API).AuthenticateSecondFactor("abcdefgh"); + }); checkEnabled(true); } [Test] public void TestBeatmapChange() { - AddStep("log in", () => API.Login("test", "test")); + AddStep("log in", () => + { + API.Login("test", "test"); + ((DummyAPIAccess)API).AuthenticateSecondFactor("abcdefgh"); + }); AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new APIBeatmapSet { OnlineID = 88 }); checkEnabled(true); AddStep("set invalid beatmap", () => favourite.BeatmapSet.Value = new APIBeatmapSet()); diff --git a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs index be819afa3e..bb78cf9fd4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs @@ -177,7 +177,11 @@ namespace osu.Game.Tests.Visual.Online AddWaitStep("wait a bit", 5); AddAssert("update not received", () => update == null); - AddStep("log in user", () => dummyAPI.Login("user", "password")); + AddStep("log in user", () => + { + dummyAPI.Login("user", "password"); + dummyAPI.AuthenticateSecondFactor("abcdefgh"); + }); } [Test] diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 1375689075..bc8f75d4ce 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -52,7 +52,11 @@ namespace osu.Game.Tests.Visual.Online AddStep("show user", () => profile.ShowUser(new APIUser { Id = 1 })); AddToggleStep("toggle visibility", visible => profile.State.Value = visible ? Visibility.Visible : Visibility.Hidden); AddStep("log out", () => dummyAPI.Logout()); - AddStep("log back in", () => dummyAPI.Login("username", "password")); + AddStep("log back in", () => + { + dummyAPI.Login("username", "password"); + dummyAPI.AuthenticateSecondFactor("abcdefgh"); + }); } [Test] @@ -98,7 +102,11 @@ namespace osu.Game.Tests.Visual.Online }); AddStep("logout", () => dummyAPI.Logout()); AddStep("show user", () => profile.ShowUser(new APIUser { Id = 1 })); - AddStep("login", () => dummyAPI.Login("username", "password")); + AddStep("login", () => + { + dummyAPI.Login("username", "password"); + dummyAPI.AuthenticateSecondFactor("abcdefgh"); + }); AddWaitStep("wait some", 3); AddStep("complete request", () => pendingRequest.TriggerSuccess(TEST_USER)); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index ce1a9ac6a7..488902c417 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -11,6 +11,7 @@ using osu.Framework.Allocation; using osu.Game.Overlays; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; namespace osu.Game.Tests.Visual.Online { @@ -72,7 +73,11 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Login overlay is visible", () => login.State.Value == Visibility.Visible); } - private void logIn() => API.Login("localUser", "password"); + private void logIn() + { + API.Login("localUser", "password"); + ((DummyAPIAccess)API).AuthenticateSecondFactor("abcdefgh"); + } private Comment getUserComment() => new Comment { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs index b17024ae8f..e1d40882be 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs @@ -125,7 +125,11 @@ namespace osu.Game.Tests.Visual.UserInterface assertLoggedOutState(); // moving from logged out -> logged in - AddStep("log back in", () => dummyAPI.Login("username", "password")); + AddStep("log back in", () => + { + dummyAPI.Login("username", "password"); + dummyAPI.AuthenticateSecondFactor("abcdefgh"); + }); assertLoggedInState(); } From 7c140408ea20fdc8122fabe92fdff93501d16d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 Jan 2024 13:53:40 +0100 Subject: [PATCH 058/915] Add request structures for verification endpoints --- .../ReissueVerificationCodeRequest.cs | 22 ++++++++++++++ .../API/Requests/VerifySessionRequest.cs | 30 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 osu.Game/Online/API/Requests/ReissueVerificationCodeRequest.cs create mode 100644 osu.Game/Online/API/Requests/VerifySessionRequest.cs diff --git a/osu.Game/Online/API/Requests/ReissueVerificationCodeRequest.cs b/osu.Game/Online/API/Requests/ReissueVerificationCodeRequest.cs new file mode 100644 index 0000000000..f2a3cf0a16 --- /dev/null +++ b/osu.Game/Online/API/Requests/ReissueVerificationCodeRequest.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Net.Http; +using osu.Framework.IO.Network; + +namespace osu.Game.Online.API.Requests +{ + public class ReissueVerificationCodeRequest : APIRequest + { + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.Method = HttpMethod.Post; + + return req; + } + + protected override string Target => @"session/verify/reissue"; + } +} diff --git a/osu.Game/Online/API/Requests/VerifySessionRequest.cs b/osu.Game/Online/API/Requests/VerifySessionRequest.cs new file mode 100644 index 0000000000..b39ec5b79a --- /dev/null +++ b/osu.Game/Online/API/Requests/VerifySessionRequest.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Net.Http; +using osu.Framework.IO.Network; + +namespace osu.Game.Online.API.Requests +{ + public class VerifySessionRequest : APIRequest + { + public readonly string VerificationKey; + + public VerifySessionRequest(string verificationKey) + { + VerificationKey = verificationKey; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.Method = HttpMethod.Post; + req.AddParameter(@"verification_key", VerificationKey); + + return req; + } + + protected override string Target => @"session/verify"; + } +} From 7b4721565702a71aa35e4ede372b3468bd72fb52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 Jan 2024 14:22:57 +0100 Subject: [PATCH 059/915] Split `/me` request from `/users` requests Them being together always bothered me and led to the abject failure that is `APIUser` and its sprawl. Now that I'm about to add a flag that is unique to `/me` for verification purposes, I'm not repeating the errors of the past by adding yet another flag to `APIUser` that is never present outside of a single usage context. --- osu.Game/Online/API/APIAccess.cs | 2 +- osu.Game/Online/API/Requests/GetMeRequest.cs | 24 +++++++++++++++++++ .../Online/API/Requests/GetUserRequest.cs | 19 ++++----------- .../Online/API/Requests/Responses/APIMe.cs | 9 +++++++ 4 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 osu.Game/Online/API/Requests/GetMeRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIMe.cs diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 51472dab30..42cf39414e 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -266,7 +266,7 @@ namespace osu.Game.Online.API } } - var userReq = new GetUserRequest(); + var userReq = new GetMeRequest(); userReq.Failure += ex => { if (ex is APIException) diff --git a/osu.Game/Online/API/Requests/GetMeRequest.cs b/osu.Game/Online/API/Requests/GetMeRequest.cs new file mode 100644 index 0000000000..aab7d7b2f1 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetMeRequest.cs @@ -0,0 +1,24 @@ +// 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.Online.API.Requests.Responses; +using osu.Game.Rulesets; + +namespace osu.Game.Online.API.Requests +{ + public class GetMeRequest : APIRequest + { + public readonly IRulesetInfo? Ruleset; + + /// + /// Gets the currently logged-in user. + /// + /// The ruleset to get the user's info for. + public GetMeRequest(IRulesetInfo? ruleset = null) + { + Ruleset = ruleset; + } + + protected override string Target => $@"me/{Ruleset?.ShortName}"; + } +} diff --git a/osu.Game/Online/API/Requests/GetUserRequest.cs b/osu.Game/Online/API/Requests/GetUserRequest.cs index 7dcf75950e..90d3268e75 100644 --- a/osu.Game/Online/API/Requests/GetUserRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRequest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; @@ -11,24 +9,17 @@ namespace osu.Game.Online.API.Requests public class GetUserRequest : APIRequest { public readonly string Lookup; - public readonly IRulesetInfo Ruleset; + public readonly IRulesetInfo? Ruleset; private readonly LookupType lookupType; - /// - /// Gets the currently logged-in user. - /// - public GetUserRequest() - { - } - /// /// Gets a user from their ID. /// /// The user to get. /// The ruleset to get the user's info for. - public GetUserRequest(long? userId = null, IRulesetInfo ruleset = null) + public GetUserRequest(long? userId = null, IRulesetInfo? ruleset = null) { - Lookup = userId.ToString(); + Lookup = userId.ToString()!; lookupType = LookupType.Id; Ruleset = ruleset; } @@ -38,14 +29,14 @@ namespace osu.Game.Online.API.Requests /// /// The user to get. /// The ruleset to get the user's info for. - public GetUserRequest(string username = null, IRulesetInfo ruleset = null) + public GetUserRequest(string username, IRulesetInfo? ruleset = null) { Lookup = username; lookupType = LookupType.Username; Ruleset = ruleset; } - protected override string Target => Lookup != null ? $@"users/{Lookup}/{Ruleset?.ShortName}?key={lookupType.ToString().ToLowerInvariant()}" : $@"me/{Ruleset?.ShortName}"; + protected override string Target => $@"users/{Lookup}/{Ruleset?.ShortName}?key={lookupType.ToString().ToLowerInvariant()}"; private enum LookupType { diff --git a/osu.Game/Online/API/Requests/Responses/APIMe.cs b/osu.Game/Online/API/Requests/Responses/APIMe.cs new file mode 100644 index 0000000000..e4c4e8ce4f --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIMe.cs @@ -0,0 +1,9 @@ +// 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.Online.API.Requests.Responses +{ + public class APIMe : APIUser + { + } +} From ddc2bbeb9bd6ca5fef3050ff690b53e2ac01cd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 Jan 2024 14:24:33 +0100 Subject: [PATCH 060/915] Add `session_verified` attribute to `/me` response --- osu.Game/Online/API/Requests/Responses/APIMe.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Online/API/Requests/Responses/APIMe.cs b/osu.Game/Online/API/Requests/Responses/APIMe.cs index e4c4e8ce4f..3cbddbe5e7 100644 --- a/osu.Game/Online/API/Requests/Responses/APIMe.cs +++ b/osu.Game/Online/API/Requests/Responses/APIMe.cs @@ -1,9 +1,13 @@ // 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; + namespace osu.Game.Online.API.Requests.Responses { public class APIMe : APIUser { + [JsonProperty("session_verified")] + public bool SessionVerified { get; set; } } } From d2775680e66129c34297246ce047914d2b94fd90 Mon Sep 17 00:00:00 2001 From: Chandler Stowell Date: Wed, 24 Jan 2024 13:13:45 -0500 Subject: [PATCH 061/915] use stack to pass action state when applying hit results this removes closure allocations --- .../Drawables/DrawableEmptyFreeformHitObject.cs | 2 +- .../Drawables/DrawablePippidonHitObject.cs | 7 ++++++- .../Drawables/DrawableEmptyScrollingHitObject.cs | 2 +- .../Drawables/DrawablePippidonHitObject.cs | 7 ++++++- .../Objects/Drawables/DrawableCatchHitObject.cs | 7 ++++++- .../Objects/Drawables/DrawableHoldNote.cs | 2 +- .../Objects/Drawables/DrawableHoldNoteBody.cs | 2 +- .../Objects/Drawables/DrawableManiaHitObject.cs | 2 +- .../Objects/Drawables/DrawableNote.cs | 4 ++-- .../Objects/Drawables/DrawableHitCircle.cs | 15 ++++++++------- .../Objects/Drawables/DrawableOsuHitObject.cs | 4 ++-- .../Objects/Drawables/DrawableSlider.cs | 13 ++++++++----- .../Objects/Drawables/DrawableSpinner.cs | 12 ++++++------ .../Objects/Drawables/DrawableSpinnerTick.cs | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 7 +++++-- .../Objects/Drawables/DrawableDrumRollTick.cs | 11 +++++++---- .../Objects/Drawables/DrawableFlyingHit.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 12 ++++++------ .../Objects/Drawables/DrawableStrongNestedHit.cs | 2 +- .../Objects/Drawables/DrawableSwell.cs | 8 ++++++-- .../Objects/Drawables/DrawableSwellTick.cs | 5 ++++- .../Objects/Drawables/DrawableHitObject.cs | 13 +++++++++++-- 22 files changed, 91 insertions(+), 50 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs index 744e207b57..e8f511bc4b 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Objects.Drawables { if (timeOffset >= 0) // todo: implement judgement logic - ApplyResult(r => r.Type = HitResult.Perfect); + ApplyResult(static r => r.Type = HitResult.Perfect); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index c5ada4288d..a8bb57ba18 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -49,7 +49,12 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables protected override void CheckForResult(bool userTriggered, double timeOffset) { if (timeOffset >= 0) - ApplyResult(r => r.Type = IsHovered ? HitResult.Perfect : HitResult.Miss); + { + ApplyResult(static (r, isHovered) => + { + r.Type = isHovered ? HitResult.Perfect : HitResult.Miss; + }, IsHovered); + } } protected override double InitialLifetimeOffset => time_preempt; diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs index a3c3b89105..070a802aea 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.EmptyScrolling.Objects.Drawables { if (timeOffset >= 0) // todo: implement judgement logic - ApplyResult(r => r.Type = HitResult.Perfect); + ApplyResult(static r => r.Type = HitResult.Perfect); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index d198fa81cb..9983ec20b0 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -49,7 +49,12 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables protected override void CheckForResult(bool userTriggered, double timeOffset) { if (timeOffset >= 0) - ApplyResult(r => r.Type = currentLane.Value == HitObject.Lane ? HitResult.Perfect : HitResult.Miss); + { + ApplyResult(static (r, pippidonHitObject) => + { + r.Type = pippidonHitObject.currentLane.Value == pippidonHitObject.HitObject.Lane ? HitResult.Perfect : HitResult.Miss; + }, this); + } } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 7f8c17861d..5a921f36f5 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -63,7 +63,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables if (CheckPosition == null) return; if (timeOffset >= 0 && Result != null) - ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? r.Judgement.MaxResult : r.Judgement.MinResult); + { + ApplyResult(static (r, state) => + { + r.Type = state.CheckPosition.Invoke(state.HitObject) ? r.Judgement.MaxResult : r.Judgement.MinResult; + }, this); + } } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 3490d50871..e5056d5167 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -265,7 +265,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (Tail.AllJudged) { if (Tail.IsHit) - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static r => r.Type = r.Judgement.MaxResult); else MissForcefully(); } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs index 1b2efbafdf..317da0580c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { if (AllJudged) return; - ApplyResult(r => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(static (r, hit) => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult, hit); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 8498fd36de..dea0817869 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Causes this to get missed, disregarding all conditions in implementations of . /// - public virtual void MissForcefully() => ApplyResult(r => r.Type = r.Judgement.MinResult); + public virtual void MissForcefully() => ApplyResult(static r => r.Type = r.Judgement.MinResult); } public abstract partial class DrawableManiaHitObject : DrawableManiaHitObject diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 680009bc4c..985007f905 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); return; } @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables result = GetCappedResult(result); - ApplyResult(r => r.Type = result); + ApplyResult(static (r, result) => r.Type = result, result); } /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 0d665cad0c..8284229d82 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -155,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); return; } @@ -169,19 +169,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (result == HitResult.None || clickAction != ClickAction.Hit) return; - ApplyResult(r => + ApplyResult(static (r, state) => { + var (hitCircle, hitResult) = state; var circleResult = (OsuHitCircleJudgementResult)r; // Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss. - if (result.IsHit()) + if (hitResult.IsHit()) { - var localMousePosition = ToLocalSpace(inputManager.CurrentState.Mouse.Position); - circleResult.CursorPositionAtHit = HitObject.StackedPosition + (localMousePosition - DrawSize / 2); + var localMousePosition = hitCircle.ToLocalSpace(hitCircle.inputManager.CurrentState.Mouse.Position); + circleResult.CursorPositionAtHit = hitCircle.HitObject.StackedPosition + (localMousePosition - hitCircle.DrawSize / 2); } - circleResult.Type = result; - }); + circleResult.Type = hitResult; + }, (this, result)); } /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 5b379a0d90..cc06d009c9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -100,12 +100,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// /// Causes this to get hit, disregarding all conditions in implementations of . /// - public void HitForcefully() => ApplyResult(r => r.Type = r.Judgement.MaxResult); + public void HitForcefully() => ApplyResult(static r => r.Type = r.Judgement.MaxResult); /// /// Causes this to get missed, disregarding all conditions in implementations of . /// - public void MissForcefully() => ApplyResult(r => r.Type = r.Judgement.MinResult); + public void MissForcefully() => ApplyResult(static r => r.Type = r.Judgement.MinResult); private RectangleF parentScreenSpaceRectangle => ((DrawableOsuHitObject)ParentHitObject)?.parentScreenSpaceRectangle ?? Parent!.ScreenSpaceDrawQuad.AABBFloat; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index baec200107..3c298cc6af 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -292,10 +292,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (HitObject.ClassicSliderBehaviour) { // Classic behaviour means a slider is judged proportionally to the number of nested hitobjects hit. This is the classic osu!stable scoring. - ApplyResult(r => + ApplyResult(static (r, nestedHitObjects) => { - int totalTicks = NestedHitObjects.Count; - int hitTicks = NestedHitObjects.Count(h => h.IsHit); + int totalTicks = nestedHitObjects.Count; + int hitTicks = nestedHitObjects.Count(h => h.IsHit); if (hitTicks == totalTicks) r.Type = HitResult.Great; @@ -306,13 +306,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables double hitFraction = (double)hitTicks / totalTicks; r.Type = hitFraction >= 0.5 ? HitResult.Ok : HitResult.Meh; } - }); + }, NestedHitObjects); } else { // If only the nested hitobjects are judged, then the slider's own judgement is ignored for scoring purposes. // But the slider needs to still be judged with a reasonable hit/miss result for visual purposes (hit/miss transforms, etc). - ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(static (r, nestedHitObjects) => + { + r.Type = nestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult; + }, NestedHitObjects); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index bf4b07eaab..d21d02c8ce 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -258,17 +258,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables foreach (var tick in ticks.Where(t => !t.Result.HasResult)) tick.TriggerResult(false); - ApplyResult(r => + ApplyResult(static (r, spinner) => { - if (Progress >= 1) + if (spinner.Progress >= 1) r.Type = HitResult.Great; - else if (Progress > .9) + else if (spinner.Progress > .9) r.Type = HitResult.Ok; - else if (Progress > .75) + else if (spinner.Progress > .75) r.Type = HitResult.Meh; - else if (Time.Current >= HitObject.EndTime) + else if (spinner.Time.Current >= spinner.HitObject.EndTime) r.Type = r.Judgement.MinResult; - }); + }, this); } protected override void Update() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs index 5b55533edd..1c3ff29118 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs @@ -35,6 +35,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// Apply a judgement result. /// /// Whether this tick was reached. - internal void TriggerResult(bool hit) => ApplyResult(r => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult); + internal void TriggerResult(bool hit) => ApplyResult(static (r, hit) => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult, hit); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 2bf0c04adf..d3fe363857 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (timeOffset < 0) return; - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static r => r.Type = r.Judgement.MaxResult); } protected override void UpdateHitStateTransforms(ArmedState state) @@ -192,7 +192,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!ParentHitObject.Judged) return; - ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(static (r, parentHitObject) => + { + r.Type = parentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; + }, ParentHitObject); } public override bool OnPressed(KeyBindingPressEvent e) => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index c900165d34..de9a3a31c5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (timeOffset > HitObject.HitWindow) - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); return; } if (Math.Abs(timeOffset) > HitObject.HitWindow) return; - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static r => r.Type = r.Judgement.MaxResult); } public override void OnKilled() @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables base.OnKilled(); if (Time.Current > HitObject.GetEndTime() && !Judged) - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); } protected override void UpdateHitStateTransforms(ArmedState state) @@ -105,7 +105,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!ParentHitObject.Judged) return; - ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(static (r, parentHitObject) => + { + r.Type = parentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; + }, ParentHitObject); } public override bool OnPressed(KeyBindingPressEvent e) => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs index a039ce3407..1332b9e950 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void LoadComplete() { base.LoadComplete(); - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static r => r.Type = r.Judgement.MaxResult); } protected override void LoadSamples() diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 1ef426854e..c3bd76bf81 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); return; } @@ -108,9 +108,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return; if (!validActionPressed) - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); else - ApplyResult(r => r.Type = result); + ApplyResult(static (r, result) => r.Type = result, result); } public override bool OnPressed(KeyBindingPressEvent e) @@ -209,19 +209,19 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!ParentHitObject.Result.IsHit) { - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); return; } if (!userTriggered) { if (timeOffset - ParentHitObject.Result.TimeOffset > SECOND_HIT_WINDOW) - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); return; } if (Math.Abs(timeOffset - ParentHitObject.Result.TimeOffset) <= SECOND_HIT_WINDOW) - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static r => r.Type = r.Judgement.MaxResult); } public override bool OnPressed(KeyBindingPressEvent e) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index 724d59edcd..4080c14066 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // it can happen that the hit window of the nested strong hit extends past the lifetime of the parent object. // this is a safety to prevent such cases from causing the nested hit to never be judged and as such prevent gameplay from completing. if (!Judged && Time.Current > ParentHitObject?.HitObject.GetEndTime()) - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static r => r.Type = r.Judgement.MinResult); } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index e4a083f218..d48b78283b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -206,7 +206,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint); if (numHits == HitObject.RequiredHits) - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static r => r.Type = r.Judgement.MaxResult); } else { @@ -227,7 +227,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables tick.TriggerResult(false); } - ApplyResult(r => r.Type = numHits == HitObject.RequiredHits ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(static (r, state) => + { + var (numHits, hitObject) = state; + r.Type = numHits == hitObject.RequiredHits ? r.Judgement.MaxResult : r.Judgement.MinResult; + }, (numHits, HitObject)); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 3a5c006962..ad1d09bc7b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -30,7 +30,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public void TriggerResult(bool hit) { HitObject.StartTime = Time.Current; - ApplyResult(r => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult); + ApplyResult(static (r, hit) => + { + r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult; + }, hit); } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index bce28361cb..9acd7b3c0f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -687,12 +687,14 @@ namespace osu.Game.Rulesets.Objects.Drawables /// the of the . /// /// The callback that applies changes to the . - protected void ApplyResult(Action application) + /// The state passed to the callback. + /// The type of the state information that is passed to the callback method. + protected void ApplyResult(Action application, TState state) { if (Result.HasResult) throw new InvalidOperationException("Cannot apply result on a hitobject that already has a result."); - application?.Invoke(Result); + application?.Invoke(Result, state); if (!Result.HasResult) throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}."); @@ -714,6 +716,13 @@ namespace osu.Game.Rulesets.Objects.Drawables OnNewResult?.Invoke(this, Result); } + /// + /// Applies the of this , notifying responders such as + /// the of the . + /// + /// The callback that applies changes to the . + protected void ApplyResult(Action application) => ApplyResult((r, _) => application?.Invoke(r), null); + /// /// Processes this , checking if a scoring result has occurred. /// From 445a7450e015458aaf071643ba024ca55da57ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 Jan 2024 15:57:40 +0100 Subject: [PATCH 062/915] Implement verification from within client --- osu.Game/Online/API/APIAccess.cs | 61 +++++++++++++++++--------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 42cf39414e..389816fcf8 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -230,8 +230,6 @@ namespace osu.Game.Online.API try { authentication.AuthenticateWithLogin(ProvidedUsername, password); - state.Value = APIState.RequiresSecondFactorAuth; - return; } catch (Exception e) { @@ -244,28 +242,6 @@ namespace osu.Game.Online.API } } - if (state.Value == APIState.RequiresSecondFactorAuth) - { - if (string.IsNullOrEmpty(SecondFactorCode)) - return; - - state.Value = APIState.Connecting; - LastLoginError = null; - - // TODO: use code to ensure second factor authentication completed. - Thread.Sleep(1000); - bool success = SecondFactorCode == "00000000"; - SecondFactorCode = null; - - if (!success) - { - state.Value = APIState.RequiresSecondFactorAuth; - LastLoginError = new InvalidOperationException("Second factor auth failed"); - SecondFactorCode = null; - return; - } - } - var userReq = new GetMeRequest(); userReq.Failure += ex => { @@ -285,14 +261,13 @@ namespace osu.Game.Online.API state.Value = APIState.Failing; } }; - userReq.Success += user => + userReq.Success += me => { - user.Status.Value = configStatus.Value ?? UserStatus.Online; + me.Status.Value = configStatus.Value ?? UserStatus.Online; - setLocalUser(user); + setLocalUser(me); - // we're connected! - state.Value = APIState.Online; + state.Value = me.SessionVerified ? APIState.Online : APIState.RequiresSecondFactorAuth; failureCount = 0; }; @@ -302,6 +277,34 @@ namespace osu.Game.Online.API return; } + if (state.Value == APIState.RequiresSecondFactorAuth) + { + if (string.IsNullOrEmpty(SecondFactorCode)) + return; + + state.Value = APIState.Connecting; + LastLoginError = null; + + var verificationRequest = new VerifySessionRequest(SecondFactorCode); + + verificationRequest.Success += () => state.Value = APIState.Online; + verificationRequest.Failure += ex => + { + state.Value = APIState.RequiresSecondFactorAuth; + LastLoginError = ex; + SecondFactorCode = null; + }; + + if (!handleRequest(verificationRequest)) + { + state.Value = APIState.Failing; + return; + } + + if (state.Value != APIState.Online) + return; + } + var friendsReq = new GetFriendsRequest(); friendsReq.Failure += _ => state.Value = APIState.Failing; friendsReq.Success += res => From 602c3bc2d90e57f84c6cf40e64eb6df1e168d945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 Jan 2024 16:17:13 +0100 Subject: [PATCH 063/915] Hook up reissue request --- osu.Game/Overlays/Login/SecondFactorAuthForm.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Login/SecondFactorAuthForm.cs b/osu.Game/Overlays/Login/SecondFactorAuthForm.cs index 60c04eedee..566587a541 100644 --- a/osu.Game/Overlays/Login/SecondFactorAuthForm.cs +++ b/osu.Game/Overlays/Login/SecondFactorAuthForm.cs @@ -5,10 +5,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Framework.Logging; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Overlays.Settings; using osu.Game.Resources.Localisation.Web; using osuTK; @@ -83,7 +85,9 @@ namespace osu.Game.Overlays.Login explainText.AddText(". You can also "); explainText.AddLink(UserVerificationStrings.BoxInfoReissueLink, () => { - // TODO: request another code. + var reissueRequest = new ReissueVerificationCodeRequest(); + reissueRequest.Failure += ex => Logger.Error(ex, @"Failed to retrieve new verification code."); + api.Perform(reissueRequest); }); explainText.AddText(" or "); explainText.AddLink(UserVerificationStrings.BoxInfoLogoutLink, () => { api.Logout(); }); From 62a0c236bc2eb706bb1f2840e80f7ed7df9c3b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 Jan 2024 20:58:23 +0100 Subject: [PATCH 064/915] Split out raw websocket logic from conjoined notifications client contrivance --- .../WebSocket/OsuClientWebSocket.cs | 154 ++++++++++++++++++ .../WebSocket/WebSocketNotificationsClient.cs | 94 +---------- .../WebSocketNotificationsClientConnector.cs | 11 +- 3 files changed, 163 insertions(+), 96 deletions(-) create mode 100644 osu.Game/Online/Notifications/WebSocket/OsuClientWebSocket.cs diff --git a/osu.Game/Online/Notifications/WebSocket/OsuClientWebSocket.cs b/osu.Game/Online/Notifications/WebSocket/OsuClientWebSocket.cs new file mode 100644 index 0000000000..965f606bdc --- /dev/null +++ b/osu.Game/Online/Notifications/WebSocket/OsuClientWebSocket.cs @@ -0,0 +1,154 @@ +// 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.Diagnostics; +using System.Net; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using osu.Framework.Extensions.TypeExtensions; +using osu.Framework.Logging; +using osu.Game.Online.API; + +namespace osu.Game.Online.Notifications.WebSocket +{ + public class OsuClientWebSocket : IAsyncDisposable + { + public event Func? MessageReceived; + public event Func? Closed; + + private readonly string endpoint; + private readonly ClientWebSocket socket; + + private CancellationTokenSource? linkedTokenSource = null; + + public OsuClientWebSocket(IAPIProvider api, string endpoint) + { + socket = new ClientWebSocket(); + socket.Options.SetRequestHeader(@"Authorization", @$"Bearer {api.AccessToken}"); + socket.Options.Proxy = WebRequest.DefaultWebProxy; + if (socket.Options.Proxy != null) + socket.Options.Proxy.Credentials = CredentialCache.DefaultCredentials; + + this.endpoint = endpoint; + } + + public async Task ConnectAsync(CancellationToken cancellationToken) + { + if (socket.State == WebSocketState.Connecting || socket.State == WebSocketState.Open) + throw new InvalidOperationException("Connection is already opened"); + + Debug.Assert(linkedTokenSource == null); + linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + + await socket.ConnectAsync(new Uri(endpoint), linkedTokenSource.Token).ConfigureAwait(false); + runReadLoop(linkedTokenSource.Token); + } + + private void runReadLoop(CancellationToken cancellationToken) => Task.Factory.StartNew(async () => + { + byte[] buffer = new byte[1024]; + StringBuilder messageResult = new StringBuilder(); + + while (!cancellationToken.IsCancellationRequested) + { + try + { + WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false); + + switch (result.MessageType) + { + case WebSocketMessageType.Text: + messageResult.Append(Encoding.UTF8.GetString(buffer[..result.Count])); + + if (result.EndOfMessage) + { + SocketMessage? message = JsonConvert.DeserializeObject(messageResult.ToString()); + messageResult.Clear(); + + Debug.Assert(message != null); + + if (message.Error != null) + { + Logger.Log($"{GetType().ReadableName()} error: {message.Error}", LoggingTarget.Network); + break; + } + + await invokeMessageReceived(message).ConfigureAwait(false); + } + + break; + + case WebSocketMessageType.Binary: + throw new NotImplementedException("Binary message type not supported."); + + case WebSocketMessageType.Close: + throw new WebException("Connection closed by remote host."); + } + } + catch (Exception ex) + { + await invokeClosed(ex).ConfigureAwait(false); + return; + } + } + }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default); + + private async Task invokeMessageReceived(SocketMessage message) + { + if (MessageReceived == null) + return; + + var invocationList = MessageReceived.GetInvocationList(); + + // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop + foreach (Func handler in invocationList) + await handler.Invoke(message).ConfigureAwait(false); + } + + private async Task invokeClosed(Exception ex) + { + if (Closed == null) + return; + + var invocationList = Closed.GetInvocationList(); + + // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop + foreach (Func handler in invocationList) + await handler.Invoke(ex).ConfigureAwait(false); + } + + public Task SendMessage(SocketMessage message, CancellationToken cancellationToken) + { + if (socket.State != WebSocketState.Open) + return Task.CompletedTask; + + return socket.SendAsync(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), WebSocketMessageType.Text, true, cancellationToken); + } + + public async Task DisconnectAsync() + { + linkedTokenSource?.Cancel(); + await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, @"Disconnecting", CancellationToken.None).ConfigureAwait(false); + linkedTokenSource?.Dispose(); + linkedTokenSource = null; + } + + public async ValueTask DisposeAsync() + { + try + { + await DisconnectAsync().ConfigureAwait(false); + } + catch + { + // Closure can fail if the connection is aborted. Don't really care since it's disposed anyway. + } + + socket.Dispose(); + } + } +} diff --git a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs index 73e5dcec6f..b85a6ca3fe 100644 --- a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs +++ b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs @@ -1,17 +1,11 @@ // 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.Concurrent; using System.Diagnostics; -using System.Net; -using System.Net.WebSockets; -using System.Text; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; -using osu.Framework.Extensions.TypeExtensions; -using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; @@ -23,96 +17,25 @@ namespace osu.Game.Online.Notifications.WebSocket /// public class WebSocketNotificationsClient : NotificationsClient { - private readonly ClientWebSocket socket; - private readonly string endpoint; + private readonly OsuClientWebSocket socket; private readonly ConcurrentDictionary channelsMap = new ConcurrentDictionary(); - public WebSocketNotificationsClient(ClientWebSocket socket, string endpoint, IAPIProvider api) + public WebSocketNotificationsClient(IAPIProvider api, string endpoint) : base(api) { - this.socket = socket; - this.endpoint = endpoint; + socket = new OsuClientWebSocket(api, endpoint); + socket.MessageReceived += onMessageReceivedAsync; + socket.Closed += InvokeClosed; } public override async Task ConnectAsync(CancellationToken cancellationToken) { - await socket.ConnectAsync(new Uri(endpoint), cancellationToken).ConfigureAwait(false); - await sendMessage(new StartChatRequest(), CancellationToken.None).ConfigureAwait(false); - - runReadLoop(cancellationToken); + await socket.ConnectAsync(cancellationToken).ConfigureAwait(false); + await socket.SendMessage(new StartChatRequest(), CancellationToken.None).ConfigureAwait(false); await base.ConnectAsync(cancellationToken).ConfigureAwait(false); } - private void runReadLoop(CancellationToken cancellationToken) => Task.Run(async () => - { - byte[] buffer = new byte[1024]; - StringBuilder messageResult = new StringBuilder(); - - while (!cancellationToken.IsCancellationRequested) - { - try - { - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false); - - switch (result.MessageType) - { - case WebSocketMessageType.Text: - messageResult.Append(Encoding.UTF8.GetString(buffer[..result.Count])); - - if (result.EndOfMessage) - { - SocketMessage? message = JsonConvert.DeserializeObject(messageResult.ToString()); - messageResult.Clear(); - - Debug.Assert(message != null); - - if (message.Error != null) - { - Logger.Log($"{GetType().ReadableName()} error: {message.Error}", LoggingTarget.Network); - break; - } - - await onMessageReceivedAsync(message).ConfigureAwait(false); - } - - break; - - case WebSocketMessageType.Binary: - throw new NotImplementedException("Binary message type not supported."); - - case WebSocketMessageType.Close: - throw new WebException("Connection closed by remote host."); - } - } - catch (Exception ex) - { - await InvokeClosed(ex).ConfigureAwait(false); - return; - } - } - }, cancellationToken); - - private async Task closeAsync() - { - try - { - await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, @"Disconnecting", CancellationToken.None).ConfigureAwait(false); - } - catch - { - // Closure can fail if the connection is aborted. Don't really care since it's disposed anyway. - } - } - - private async Task sendMessage(SocketMessage message, CancellationToken cancellationToken) - { - if (socket.State != WebSocketState.Open) - return; - - await socket.SendAsync(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), WebSocketMessageType.Text, true, cancellationToken).ConfigureAwait(false); - } - private async Task onMessageReceivedAsync(SocketMessage message) { switch (message.Event) @@ -173,8 +96,7 @@ namespace osu.Game.Online.Notifications.WebSocket public override async ValueTask DisposeAsync() { await base.DisposeAsync().ConfigureAwait(false); - await closeAsync().ConfigureAwait(false); - socket.Dispose(); + await socket.DisposeAsync().ConfigureAwait(false); } } } diff --git a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs index f50369a06c..6c61281e90 100644 --- a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs +++ b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs @@ -1,8 +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.Net; -using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; using osu.Game.Online.API; @@ -33,14 +31,7 @@ namespace osu.Game.Online.Notifications.WebSocket api.Queue(req); string endpoint = await tcs.Task.ConfigureAwait(false); - - ClientWebSocket socket = new ClientWebSocket(); - socket.Options.SetRequestHeader(@"Authorization", @$"Bearer {api.AccessToken}"); - socket.Options.Proxy = WebRequest.DefaultWebProxy; - if (socket.Options.Proxy != null) - socket.Options.Proxy.Credentials = CredentialCache.DefaultCredentials; - - return new WebSocketNotificationsClient(socket, endpoint, api); + return new WebSocketNotificationsClient(api, endpoint); } } } From e3eb7a8b4281c7d3b2170b10b2681cde8ee7f066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 Jan 2024 21:33:34 +0100 Subject: [PATCH 065/915] Support verification via clicking link from e-mail --- osu.Game/Online/API/APIAccess.cs | 50 ++++++++++++++++++- .../DevelopmentEndpointConfiguration.cs | 1 + osu.Game/Online/EndpointConfiguration.cs | 5 ++ .../ExperimentalEndpointConfiguration.cs | 1 + .../Online/ProductionEndpointConfiguration.cs | 1 + 5 files changed, 57 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 389816fcf8..dabb2cc94c 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -11,8 +11,10 @@ using System.Net.Http; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Newtonsoft.Json.Linq; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; @@ -76,6 +78,11 @@ namespace osu.Game.Online.API private readonly Logger log; + private string webSocketEndpointUrl; + + [CanBeNull] + private OsuClientWebSocket webSocket; + public APIAccess(OsuGameBase game, OsuConfigManager config, EndpointConfiguration endpointConfiguration, string versionHash) { this.game = game; @@ -84,6 +91,7 @@ namespace osu.Game.Online.API APIEndpointUrl = endpointConfiguration.APIEndpointUrl; WebsiteRootUrl = endpointConfiguration.WebsiteRootUrl; + webSocketEndpointUrl = endpointConfiguration.NotificationsWebSocketEndpointUrl; authentication = new OAuth(endpointConfiguration.APIClientID, endpointConfiguration.APIClientSecret, APIEndpointUrl); log = Logger.GetLogger(LoggingTarget.Network); @@ -267,7 +275,10 @@ namespace osu.Game.Online.API setLocalUser(me); - state.Value = me.SessionVerified ? APIState.Online : APIState.RequiresSecondFactorAuth; + if (me.SessionVerified) + state.Value = APIState.Online; + else + setUpSecondFactorAuthentication(); failureCount = 0; }; @@ -350,6 +361,42 @@ namespace osu.Game.Online.API this.password = password; } + private void setUpSecondFactorAuthentication() + { + if (state.Value == APIState.RequiresSecondFactorAuth) + return; + + state.Value = APIState.RequiresSecondFactorAuth; + + try + { + webSocket?.DisposeAsync().AsTask().WaitSafely(); + var newSocket = new OsuClientWebSocket(this, webSocketEndpointUrl); + newSocket.MessageReceived += async msg => + { + if (msg.Event == @"verified") + { + state.Value = APIState.Online; + await newSocket.DisposeAsync().ConfigureAwait(false); + if (webSocket == newSocket) + webSocket = null; + } + }; + newSocket.Closed += ex => + { + Logger.Error(ex, "Connection with account verification endpoint closed unexpectedly. Please supply account verification code manually.", LoggingTarget.Network); + return Task.CompletedTask; + }; + webSocket = newSocket; + + webSocket.ConnectAsync(cancellationToken.Token).WaitSafely(); + } + catch (Exception ex) + { + Logger.Error(ex, "Failed to set up connection with account verification endpoint. Please supply account verification code manually.", LoggingTarget.Network); + } + } + public void AuthenticateSecondFactor(string code) { Debug.Assert(State.Value == APIState.RequiresSecondFactorAuth); @@ -579,6 +626,7 @@ namespace osu.Game.Online.API flushQueue(); cancellationToken.Cancel(); + webSocket?.DisposeAsync().AsTask().WaitSafely(); } } diff --git a/osu.Game/Online/DevelopmentEndpointConfiguration.cs b/osu.Game/Online/DevelopmentEndpointConfiguration.cs index 5f3c353f4d..1c78c3c147 100644 --- a/osu.Game/Online/DevelopmentEndpointConfiguration.cs +++ b/osu.Game/Online/DevelopmentEndpointConfiguration.cs @@ -13,6 +13,7 @@ namespace osu.Game.Online SpectatorEndpointUrl = $@"{APIEndpointUrl}/signalr/spectator"; MultiplayerEndpointUrl = $@"{APIEndpointUrl}/signalr/multiplayer"; MetadataEndpointUrl = $@"{APIEndpointUrl}/signalr/metadata"; + NotificationsWebSocketEndpointUrl = "wss://dev.ppy.sh/home/notifications/feed"; } } } diff --git a/osu.Game/Online/EndpointConfiguration.cs b/osu.Game/Online/EndpointConfiguration.cs index f3bcced630..6187471b65 100644 --- a/osu.Game/Online/EndpointConfiguration.cs +++ b/osu.Game/Online/EndpointConfiguration.cs @@ -44,5 +44,10 @@ namespace osu.Game.Online /// The endpoint for the SignalR metadata server. /// public string MetadataEndpointUrl { get; set; } + + /// + /// The endpoint for the notifications websocket. + /// + public string NotificationsWebSocketEndpointUrl { get; set; } } } diff --git a/osu.Game/Online/ExperimentalEndpointConfiguration.cs b/osu.Game/Online/ExperimentalEndpointConfiguration.cs index c3d0014c8b..bc65fd63f3 100644 --- a/osu.Game/Online/ExperimentalEndpointConfiguration.cs +++ b/osu.Game/Online/ExperimentalEndpointConfiguration.cs @@ -14,6 +14,7 @@ namespace osu.Game.Online SpectatorEndpointUrl = "https://spectator.ppy.sh/spectator"; MultiplayerEndpointUrl = "https://spectator.ppy.sh/multiplayer"; MetadataEndpointUrl = "https://spectator.ppy.sh/metadata"; + NotificationsWebSocketEndpointUrl = "wss://notify.ppy.sh"; } } } diff --git a/osu.Game/Online/ProductionEndpointConfiguration.cs b/osu.Game/Online/ProductionEndpointConfiguration.cs index 0244761b65..a26a25bce5 100644 --- a/osu.Game/Online/ProductionEndpointConfiguration.cs +++ b/osu.Game/Online/ProductionEndpointConfiguration.cs @@ -13,6 +13,7 @@ namespace osu.Game.Online SpectatorEndpointUrl = "https://spectator.ppy.sh/spectator"; MultiplayerEndpointUrl = "https://spectator.ppy.sh/multiplayer"; MetadataEndpointUrl = "https://spectator.ppy.sh/metadata"; + NotificationsWebSocketEndpointUrl = "wss://notify.ppy.sh"; } } } From 67010fcd03b1546ef0bbf24fdf864db69ad5bb58 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 24 Jan 2024 23:45:07 +0300 Subject: [PATCH 066/915] Reduce allocation overhead in ScoreCounter --- osu.Game/Graphics/UserInterface/ScoreCounter.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index 255b2149f0..62cdefda43 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -4,7 +4,6 @@ #nullable disable using osu.Framework.Bindables; -using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; @@ -39,7 +38,7 @@ namespace osu.Game.Graphics.UserInterface protected override double GetProportionalDuration(long currentValue, long newValue) => currentValue > newValue ? currentValue - newValue : newValue - currentValue; - protected override LocalisableString FormatCount(long count) => count.ToLocalisableString(formatString); + protected override LocalisableString FormatCount(long count) => count.ToString(formatString); protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(s => s.Font = s.Font.With(fixedWidth: true)); From 2f8747776efa654e6d939eac867139249a75b6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 Jan 2024 22:01:59 +0100 Subject: [PATCH 067/915] Fix nullability inspection --- osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs index bb78cf9fd4..3607b37c7e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual.Online else { int userId = int.Parse(getUserRequest.Lookup); - string rulesetName = getUserRequest.Ruleset.ShortName; + string rulesetName = getUserRequest.Ruleset!.ShortName; var response = new APIUser { Id = userId, From 9e1c24271394770313e5b06e6b89ed1e73da5056 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Wed, 24 Jan 2024 08:01:41 -0500 Subject: [PATCH 068/915] Prevent custom divisor ranges from halting preset cycling A custom divisor like 24 or 32 will result in a range containing many divisors that are already in the `Common` and `Triplets` presets. When this happens, it can become impossible to cycle between presets, because the preset can only be changed if the new divisor isn't already contained within the current preset's range. --- .../Visual/Editing/TestSceneBeatDivisorControl.cs | 7 +++++++ osu.Game/Screens/Edit/BindableBeatDivisor.cs | 5 +++-- .../Screens/Edit/Compose/Components/BeatDivisorControl.cs | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index f2b3351533..6c36e6729e 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -210,6 +210,13 @@ namespace osu.Game.Tests.Visual.Editing switchPresets(-1); assertPreset(BeatDivisorType.Custom, 15); assertBeatSnap(15); + + setDivisorViaInput(24); + assertPreset(BeatDivisorType.Custom, 24); + switchPresets(1); + assertPreset(BeatDivisorType.Common); + switchPresets(-2); + assertPreset(BeatDivisorType.Triplets); } private void switchBeatSnap(int direction) => AddRepeatStep($"move snap {(direction > 0 ? "forward" : "backward")}", () => diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index ffa4f01e75..87cb191a82 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -29,10 +29,11 @@ namespace osu.Game.Screens.Edit /// Set a divisor, updating the valid divisor range appropriately. /// /// The intended divisor. - public void SetArbitraryDivisor(int divisor) + /// Ignores the current valid divisor range when true. + public void SetArbitraryDivisor(int divisor, bool force = false) { // If the current valid divisor range doesn't contain the proposed value, attempt to find one which does. - if (!ValidDivisors.Value.Presets.Contains(divisor)) + if (force || !ValidDivisors.Value.Presets.Contains(divisor)) { if (BeatDivisorPresetCollection.COMMON.Presets.Contains(divisor)) ValidDivisors.Value = BeatDivisorPresetCollection.COMMON; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index b33edb9edb..da1a37d57f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -208,11 +208,11 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (currentType) { case BeatDivisorType.Common: - beatDivisor.SetArbitraryDivisor(4); + beatDivisor.SetArbitraryDivisor(4, true); break; case BeatDivisorType.Triplets: - beatDivisor.SetArbitraryDivisor(6); + beatDivisor.SetArbitraryDivisor(6, true); break; case BeatDivisorType.Custom: From 781196858209dcc6804182b9d8dfac2896e6fd1d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 25 Jan 2024 03:28:02 +0300 Subject: [PATCH 069/915] Fix ArgonScoreCounter is still using localisation --- osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs b/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs index 348327d710..44b9fb3123 100644 --- a/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play.HUD public bool UsesFixedAnchor { get; set; } - protected override LocalisableString FormatCount(long count) => count.ToLocalisableString(); + protected override LocalisableString FormatCount(long count) => count.ToString(); protected override IHasText CreateText() => scoreText = new ArgonScoreTextComponent(Anchor.TopRight, BeatmapsetsStrings.ShowScoreboardHeadersScore.ToUpper()) { From 21b11092d61cb6b633b2b7ab248881504aeb98b7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 25 Jan 2024 04:06:15 +0300 Subject: [PATCH 070/915] Fix slider sliding samples allocation --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index baec200107..080d07be49 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -239,11 +239,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (Tracking.Value && Time.Current >= HitObject.StartTime) { // keep the sliding sample playing at the current tracking position - if (!slidingSample.IsPlaying) + if (!slidingSample.RequestedPlaying) slidingSample.Play(); slidingSample.Balance.Value = CalculateSamplePlaybackBalance(CalculateDrawableRelativePosition(Ball)); } - else if (slidingSample.IsPlaying) + else if (slidingSample.IsPlaying || slidingSample.RequestedPlaying) slidingSample.Stop(); } } From 30e335233da019c7e72203a2589fbe8fd9484476 Mon Sep 17 00:00:00 2001 From: Nitrous Date: Thu, 25 Jan 2024 09:27:10 +0800 Subject: [PATCH 071/915] Crop screenshot image to scaling container. --- osu.Game/Graphics/ScreenshotManager.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 26e499ae9a..47ce0d31eb 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -24,6 +24,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Processing; namespace osu.Game.Graphics { @@ -52,6 +53,9 @@ namespace osu.Game.Graphics private INotificationOverlay notificationOverlay { get; set; } private Sample shutter; + private Bindable sizeX; + private Bindable sizeY; + private Bindable scalingMode; [BackgroundDependencyLoader] private void load(OsuConfigManager config, Storage storage, AudioManager audio) @@ -62,6 +66,10 @@ namespace osu.Game.Graphics captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); shutter = audio.Samples.Get("UI/shutter"); + + sizeX = config.GetBindable(OsuSetting.ScalingSizeX); + sizeY = config.GetBindable(OsuSetting.ScalingSizeY); + scalingMode = config.GetBindable(OsuSetting.Scaling); } public bool OnPressed(KeyBindingPressEvent e) @@ -119,6 +127,19 @@ namespace osu.Game.Graphics using (var image = await host.TakeScreenshotAsync().ConfigureAwait(false)) { + if (scalingMode.Value == ScalingMode.Everything) + { + image.Mutate(m => + { + var size = m.GetCurrentSize(); + var rect = new Rectangle(Point.Empty, size); + int sx = (size.Width - (int)(size.Width * sizeX.Value)) / 2; + int sy = (size.Height - (int)(size.Height * sizeY.Value)) / 2; + rect.Inflate(-sx, -sy); + m.Crop(rect); + }); + } + clipboard.SetImage(image); (string filename, var stream) = getWritableStream(); From b20051fd55b9977152b22e1d3a86dba86d9b0839 Mon Sep 17 00:00:00 2001 From: Nitrous Date: Thu, 25 Jan 2024 10:35:41 +0800 Subject: [PATCH 072/915] offset crop rectangle to scaling container --- osu.Game/Graphics/ScreenshotManager.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 47ce0d31eb..a60d55cbef 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -53,6 +53,8 @@ namespace osu.Game.Graphics private INotificationOverlay notificationOverlay { get; set; } private Sample shutter; + private Bindable posX; + private Bindable posY; private Bindable sizeX; private Bindable sizeY; private Bindable scalingMode; @@ -67,6 +69,8 @@ namespace osu.Game.Graphics shutter = audio.Samples.Get("UI/shutter"); + posX = config.GetBindable(OsuSetting.ScalingPositionX); + posY = config.GetBindable(OsuSetting.ScalingPositionY); sizeX = config.GetBindable(OsuSetting.ScalingSizeX); sizeY = config.GetBindable(OsuSetting.ScalingSizeY); scalingMode = config.GetBindable(OsuSetting.Scaling); @@ -136,6 +140,8 @@ namespace osu.Game.Graphics int sx = (size.Width - (int)(size.Width * sizeX.Value)) / 2; int sy = (size.Height - (int)(size.Height * sizeY.Value)) / 2; rect.Inflate(-sx, -sy); + rect.X = (int)(rect.X * posX.Value) * 2; + rect.Y = (int)(rect.Y * posY.Value) * 2; m.Crop(rect); }); } From d2990170d021f2caee2c6e66368f07792c7ac53c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 13:53:31 +0900 Subject: [PATCH 073/915] Add retry loop to avoid log export failing occasionally on windows Closes https://github.com/ppy/osu/issues/26693. --- osu.Game/IO/MigratableStorage.cs | 40 ++--------- .../Sections/General/UpdateSettings.cs | 4 +- osu.Game/Utils/FileUtils.cs | 72 +++++++++++++++++++ 3 files changed, 80 insertions(+), 36 deletions(-) create mode 100644 osu.Game/Utils/FileUtils.cs diff --git a/osu.Game/IO/MigratableStorage.cs b/osu.Game/IO/MigratableStorage.cs index 14a3c5a43c..d03d259f71 100644 --- a/osu.Game/IO/MigratableStorage.cs +++ b/osu.Game/IO/MigratableStorage.cs @@ -6,8 +6,8 @@ using System; using System.IO; using System.Linq; -using System.Threading; using osu.Framework.Platform; +using osu.Game.Utils; namespace osu.Game.IO { @@ -81,7 +81,7 @@ namespace osu.Game.IO if (IgnoreSuffixes.Any(suffix => fi.Name.EndsWith(suffix, StringComparison.Ordinal))) continue; - allFilesDeleted &= AttemptOperation(() => fi.Delete(), throwOnFailure: false); + allFilesDeleted &= FileUtils.AttemptOperation(() => fi.Delete(), throwOnFailure: false); } foreach (DirectoryInfo dir in target.GetDirectories()) @@ -92,11 +92,11 @@ namespace osu.Game.IO if (IgnoreSuffixes.Any(suffix => dir.Name.EndsWith(suffix, StringComparison.Ordinal))) continue; - allFilesDeleted &= AttemptOperation(() => dir.Delete(true), throwOnFailure: false); + allFilesDeleted &= FileUtils.AttemptOperation(() => dir.Delete(true), throwOnFailure: false); } if (target.GetFiles().Length == 0 && target.GetDirectories().Length == 0) - allFilesDeleted &= AttemptOperation(target.Delete, throwOnFailure: false); + allFilesDeleted &= FileUtils.AttemptOperation(target.Delete, throwOnFailure: false); return allFilesDeleted; } @@ -115,7 +115,7 @@ namespace osu.Game.IO if (IgnoreSuffixes.Any(suffix => fileInfo.Name.EndsWith(suffix, StringComparison.Ordinal))) continue; - AttemptOperation(() => + FileUtils.AttemptOperation(() => { fileInfo.Refresh(); @@ -139,35 +139,5 @@ namespace osu.Game.IO CopyRecursive(dir, destination.CreateSubdirectory(dir.Name), false); } } - - /// - /// Attempt an IO operation multiple times and only throw if none of the attempts succeed. - /// - /// The action to perform. - /// The number of attempts (250ms wait between each). - /// Whether to throw an exception on failure. If false, will silently fail. - protected static bool AttemptOperation(Action action, int attempts = 10, bool throwOnFailure = true) - { - while (true) - { - try - { - action(); - return true; - } - catch (Exception) - { - if (attempts-- == 0) - { - if (throwOnFailure) - throw; - - return false; - } - } - - Thread.Sleep(250); - } - } } } diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 3ff5556f4d..fe88413e6a 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -15,6 +15,7 @@ using osu.Game.Localisation; using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Settings.Sections.Maintenance; using osu.Game.Updater; +using osu.Game.Utils; using SharpCompress.Archives.Zip; namespace osu.Game.Overlays.Settings.Sections.General @@ -111,7 +112,8 @@ namespace osu.Game.Overlays.Settings.Sections.General using (var outStream = storage.CreateFileSafely(archive_filename)) using (var zip = ZipArchive.Create()) { - foreach (string? f in logStorage.GetFiles(string.Empty, "*.log")) zip.AddEntry(f, logStorage.GetStream(f), true); + foreach (string? f in logStorage.GetFiles(string.Empty, "*.log")) + FileUtils.AttemptOperation(z => z.AddEntry(f, logStorage.GetStream(f), true), zip); zip.SaveTo(outStream); } diff --git a/osu.Game/Utils/FileUtils.cs b/osu.Game/Utils/FileUtils.cs new file mode 100644 index 0000000000..063ab178f7 --- /dev/null +++ b/osu.Game/Utils/FileUtils.cs @@ -0,0 +1,72 @@ +// 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.Threading; + +namespace osu.Game.Utils +{ + public static class FileUtils + { + /// + /// Attempt an IO operation multiple times and only throw if none of the attempts succeed. + /// + /// The action to perform. + /// The provided state. + /// The number of attempts (250ms wait between each). + /// Whether to throw an exception on failure. If false, will silently fail. + public static bool AttemptOperation(Action action, T state, int attempts = 10, bool throwOnFailure = true) + { + while (true) + { + try + { + action(state); + return true; + } + catch (Exception) + { + if (attempts-- == 0) + { + if (throwOnFailure) + throw; + + return false; + } + } + + Thread.Sleep(250); + } + } + + /// + /// Attempt an IO operation multiple times and only throw if none of the attempts succeed. + /// + /// The action to perform. + /// The number of attempts (250ms wait between each). + /// Whether to throw an exception on failure. If false, will silently fail. + public static bool AttemptOperation(Action action, int attempts = 10, bool throwOnFailure = true) + { + while (true) + { + try + { + action(); + return true; + } + catch (Exception) + { + if (attempts-- == 0) + { + if (throwOnFailure) + throw; + + return false; + } + } + + Thread.Sleep(250); + } + } + } +} From 0cbba7e011bd91d4d9883adc4d5c772c6789670a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 14:18:20 +0900 Subject: [PATCH 074/915] Apply NRT to `ScreenshotManager` --- osu.Game/Graphics/ScreenshotManager.cs | 39 ++++++++++++-------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index a60d55cbef..d952460c47 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.IO; using System.Threading; @@ -38,37 +36,36 @@ namespace osu.Game.Graphics /// public IBindable CursorVisibility => cursorVisibility; - private Bindable screenshotFormat; - private Bindable captureMenuCursor; + [Resolved] + private GameHost host { get; set; } = null!; [Resolved] - private GameHost host { get; set; } + private Clipboard clipboard { get; set; } = null!; [Resolved] - private Clipboard clipboard { get; set; } + private INotificationOverlay notificationOverlay { get; set; } = null!; - private Storage storage; + private Storage storage = null!; - [Resolved] - private INotificationOverlay notificationOverlay { get; set; } + private Sample? shutter; - private Sample shutter; - private Bindable posX; - private Bindable posY; - private Bindable sizeX; - private Bindable sizeY; - private Bindable scalingMode; + private Bindable screenshotFormat = null!; + private Bindable captureMenuCursor = null!; + private Bindable posX = null!; + private Bindable posY = null!; + private Bindable sizeX = null!; + private Bindable sizeY = null!; + private Bindable scalingMode = null!; [BackgroundDependencyLoader] private void load(OsuConfigManager config, Storage storage, AudioManager audio) { this.storage = storage.GetStorageForDirectory(@"screenshots"); - screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); - captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); - shutter = audio.Samples.Get("UI/shutter"); + screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); + captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); posX = config.GetBindable(OsuSetting.ScalingPositionX); posY = config.GetBindable(OsuSetting.ScalingPositionY); sizeX = config.GetBindable(OsuSetting.ScalingSizeX); @@ -84,7 +81,7 @@ namespace osu.Game.Graphics switch (e.Action) { case GlobalAction.TakeScreenshot: - shutter.Play(); + shutter?.Play(); TakeScreenshotAsync().FireAndForget(); return true; } @@ -148,7 +145,7 @@ namespace osu.Game.Graphics clipboard.SetImage(image); - (string filename, var stream) = getWritableStream(); + (string? filename, Stream? stream) = getWritableStream(); if (filename == null) return; @@ -191,7 +188,7 @@ namespace osu.Game.Graphics private static readonly object filename_reservation_lock = new object(); - private (string filename, Stream stream) getWritableStream() + private (string? filename, Stream? stream) getWritableStream() { lock (filename_reservation_lock) { From 85927e06827eaa3660f00191eac6b4251e8db7b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 14:22:27 +0900 Subject: [PATCH 075/915] Move configuration retrieval to non-bindable inline for readability --- osu.Game/Graphics/ScreenshotManager.cs | 65 ++++++++++++-------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index d952460c47..ca6a3fe84f 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -22,6 +22,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; namespace osu.Game.Graphics @@ -45,32 +46,18 @@ namespace osu.Game.Graphics [Resolved] private INotificationOverlay notificationOverlay { get; set; } = null!; + [Resolved] + private OsuConfigManager config { get; set; } = null!; + private Storage storage = null!; private Sample? shutter; - private Bindable screenshotFormat = null!; - private Bindable captureMenuCursor = null!; - private Bindable posX = null!; - private Bindable posY = null!; - private Bindable sizeX = null!; - private Bindable sizeY = null!; - private Bindable scalingMode = null!; - [BackgroundDependencyLoader] - private void load(OsuConfigManager config, Storage storage, AudioManager audio) + private void load(Storage storage, AudioManager audio) { this.storage = storage.GetStorageForDirectory(@"screenshots"); - shutter = audio.Samples.Get("UI/shutter"); - - screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); - captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); - posX = config.GetBindable(OsuSetting.ScalingPositionX); - posY = config.GetBindable(OsuSetting.ScalingPositionY); - sizeX = config.GetBindable(OsuSetting.ScalingSizeX); - sizeY = config.GetBindable(OsuSetting.ScalingSizeY); - scalingMode = config.GetBindable(OsuSetting.Scaling); } public bool OnPressed(KeyBindingPressEvent e) @@ -99,9 +86,19 @@ namespace osu.Game.Graphics { Interlocked.Increment(ref screenShotTasks); + ScreenshotFormat screenshotFormat = config.Get(OsuSetting.ScreenshotFormat); + bool captureMenuCursor = config.Get(OsuSetting.ScreenshotCaptureMenuCursor); + + float posX = config.Get(OsuSetting.ScalingPositionX); + float posY = config.Get(OsuSetting.ScalingPositionY); + float sizeX = config.Get(OsuSetting.ScalingSizeX); + float sizeY = config.Get(OsuSetting.ScalingSizeY); + + ScalingMode scalingMode = config.Get(OsuSetting.Scaling); + try { - if (!captureMenuCursor.Value) + if (!captureMenuCursor) { cursorVisibility.Value = false; @@ -110,7 +107,7 @@ namespace osu.Game.Graphics int framesWaited = 0; - using (var framesWaitedEvent = new ManualResetEventSlim(false)) + using (ManualResetEventSlim framesWaitedEvent = new ManualResetEventSlim(false)) { ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => { @@ -126,32 +123,32 @@ namespace osu.Game.Graphics } } - using (var image = await host.TakeScreenshotAsync().ConfigureAwait(false)) + using (Image? image = await host.TakeScreenshotAsync().ConfigureAwait(false)) { - if (scalingMode.Value == ScalingMode.Everything) + if (scalingMode == ScalingMode.Everything) { image.Mutate(m => { - var size = m.GetCurrentSize(); - var rect = new Rectangle(Point.Empty, size); - int sx = (size.Width - (int)(size.Width * sizeX.Value)) / 2; - int sy = (size.Height - (int)(size.Height * sizeY.Value)) / 2; + Size size = m.GetCurrentSize(); + Rectangle rect = new Rectangle(Point.Empty, size); + int sx = (size.Width - (int)(size.Width * sizeX)) / 2; + int sy = (size.Height - (int)(size.Height * sizeY)) / 2; rect.Inflate(-sx, -sy); - rect.X = (int)(rect.X * posX.Value) * 2; - rect.Y = (int)(rect.Y * posY.Value) * 2; + rect.X = (int)(rect.X * posX) * 2; + rect.Y = (int)(rect.Y * posY) * 2; m.Crop(rect); }); } clipboard.SetImage(image); - (string? filename, Stream? stream) = getWritableStream(); + (string? filename, Stream? stream) = getWritableStream(screenshotFormat); if (filename == null) return; using (stream) { - switch (screenshotFormat.Value) + switch (screenshotFormat) { case ScreenshotFormat.Png: await image.SaveAsPngAsync(stream).ConfigureAwait(false); @@ -164,7 +161,7 @@ namespace osu.Game.Graphics break; default: - throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat.Value}."); + throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat}."); } } @@ -188,12 +185,12 @@ namespace osu.Game.Graphics private static readonly object filename_reservation_lock = new object(); - private (string? filename, Stream? stream) getWritableStream() + private (string? filename, Stream? stream) getWritableStream(ScreenshotFormat format) { lock (filename_reservation_lock) { - var dt = DateTime.Now; - string fileExt = screenshotFormat.ToString().ToLowerInvariant(); + DateTime dt = DateTime.Now; + string fileExt = format.ToString().ToLowerInvariant(); string withoutIndex = $"osu_{dt:yyyy-MM-dd_HH-mm-ss}.{fileExt}"; if (!storage.Exists(withoutIndex)) From 69e822f3c53186c61299c6b80bcb17a834f547eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 14:30:26 +0900 Subject: [PATCH 076/915] Refactor crop logic slightly --- osu.Game/Graphics/ScreenshotManager.cs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index ca6a3fe84f..a085558b3a 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -89,13 +89,6 @@ namespace osu.Game.Graphics ScreenshotFormat screenshotFormat = config.Get(OsuSetting.ScreenshotFormat); bool captureMenuCursor = config.Get(OsuSetting.ScreenshotCaptureMenuCursor); - float posX = config.Get(OsuSetting.ScalingPositionX); - float posY = config.Get(OsuSetting.ScalingPositionY); - float sizeX = config.Get(OsuSetting.ScalingSizeX); - float sizeY = config.Get(OsuSetting.ScalingSizeY); - - ScalingMode scalingMode = config.Get(OsuSetting.Scaling); - try { if (!captureMenuCursor) @@ -125,17 +118,26 @@ namespace osu.Game.Graphics using (Image? image = await host.TakeScreenshotAsync().ConfigureAwait(false)) { - if (scalingMode == ScalingMode.Everything) + if (config.Get(OsuSetting.Scaling) == ScalingMode.Everything) { + float posX = config.Get(OsuSetting.ScalingPositionX); + float posY = config.Get(OsuSetting.ScalingPositionY); + float sizeX = config.Get(OsuSetting.ScalingSizeX); + float sizeY = config.Get(OsuSetting.ScalingSizeY); + image.Mutate(m => { - Size size = m.GetCurrentSize(); - Rectangle rect = new Rectangle(Point.Empty, size); - int sx = (size.Width - (int)(size.Width * sizeX)) / 2; - int sy = (size.Height - (int)(size.Height * sizeY)) / 2; + Rectangle rect = new Rectangle(Point.Empty, m.GetCurrentSize()); + + // Reduce size by user scale settings... + int sx = (rect.Width - (int)(rect.Width * sizeX)) / 2; + int sy = (rect.Height - (int)(rect.Height * sizeY)) / 2; rect.Inflate(-sx, -sy); + + // ...then adjust the region based on their positional offset. rect.X = (int)(rect.X * posX) * 2; rect.Y = (int)(rect.Y * posY) * 2; + m.Crop(rect); }); } From f22bfa350a2b95ff3fa16a5528d7ef95c0e0d3fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 15:02:43 +0900 Subject: [PATCH 077/915] Add test coverage of hidden scores on accuracy circle --- .../Visual/Ranking/TestSceneAccuracyCircle.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs index 7aa36429a7..41a5603060 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs @@ -46,6 +46,16 @@ namespace osu.Game.Tests.Visual.Ranking addCircleStep(createScore(1, new OsuRuleset())); } + [Test] + public void TestOsuRankHidden() + { + addCircleStep(createScore(0, new OsuRuleset(), 20, true)); + addCircleStep(createScore(0.8, new OsuRuleset(), 5, true)); + addCircleStep(createScore(0.95, new OsuRuleset(), 0, true)); + addCircleStep(createScore(0.97, new OsuRuleset(), 1, true)); + addCircleStep(createScore(1, new OsuRuleset(), 0, true)); + } + [Test] public void TestCatchRank() { @@ -66,7 +76,7 @@ namespace osu.Game.Tests.Visual.Ranking addCircleStep(createScore(1, new CatchRuleset())); } - private void addCircleStep(ScoreInfo score) => AddStep($"add panel ({score.DisplayAccuracy})", () => + private void addCircleStep(ScoreInfo score) => AddStep($"add panel ({score.DisplayAccuracy}, {score.Statistics.GetValueOrDefault(HitResult.Miss)} miss)", () => { Children = new Drawable[] { @@ -93,18 +103,22 @@ namespace osu.Game.Tests.Visual.Ranking }; }); - private ScoreInfo createScore(double accuracy, Ruleset ruleset) + private ScoreInfo createScore(double accuracy, Ruleset ruleset, int missCount = 0, bool hidden = false) { var scoreProcessor = ruleset.CreateScoreProcessor(); var statistics = new Dictionary { - { HitResult.Miss, 1 }, + { HitResult.Miss, missCount }, { HitResult.Meh, 50 }, { HitResult.Good, 100 }, { HitResult.Great, 300 }, }; + var mods = hidden + ? new[] { new OsuModHidden() } + : new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() }; + return new ScoreInfo { User = new APIUser @@ -114,7 +128,7 @@ namespace osu.Game.Tests.Visual.Ranking }, BeatmapInfo = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, Ruleset = ruleset.RulesetInfo, - Mods = new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() }, + Mods = mods, TotalScore = 2845370, Accuracy = accuracy, MaxCombo = 999, From 37e370e654d743ca11b78074cd9a60f66d5590c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 14:57:42 +0900 Subject: [PATCH 078/915] Fix crash at results screen when hidden is enabled and S rank becomes A due to miss Closes https://github.com/ppy/osu/issues/26692. --- osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index e7e54d0fae..0aff98df2b 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -417,7 +417,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy accuracyCircle .FillTo(accuracyS - NOTCH_WIDTH_PERCENTAGE / 2 - visual_alignment_offset, 70, Easing.OutQuint); - badges.Single(b => b.Rank == ScoreRank.S) + badges.Single(b => b.Rank == getRank(ScoreRank.S)) .FadeOut(70, Easing.OutQuint); } } From cc341b4119bd9a1aa8cb5aafe936088ff1e0f857 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 15:21:19 +0900 Subject: [PATCH 079/915] Adjust beatmap carousel padding to avoid scrollbar disappearing underneath logo --- osu.Game/Screens/Select/BeatmapCarousel.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 70ecde3858..32a1b5cb58 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -215,6 +215,12 @@ namespace osu.Game.Screens.Select InternalChild = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + // Avoid clash between scrollbar and osu! logo. + Top = 10, + Bottom = 100, + }, Children = new Drawable[] { setPool, From a264ac9f381dc71d8b8d79af70c61d168a9ed91f Mon Sep 17 00:00:00 2001 From: Mike Will Date: Thu, 25 Jan 2024 05:12:54 -0500 Subject: [PATCH 080/915] Change name and description of `force` parameter in `SetArbitraryDivisor` --- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index 87cb191a82..4b0726658f 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -29,11 +29,11 @@ namespace osu.Game.Screens.Edit /// Set a divisor, updating the valid divisor range appropriately. /// /// The intended divisor. - /// Ignores the current valid divisor range when true. - public void SetArbitraryDivisor(int divisor, bool force = false) + /// Forces changing the valid divisors to a known preset. + public void SetArbitraryDivisor(int divisor, bool preferKnownPresets = false) { // If the current valid divisor range doesn't contain the proposed value, attempt to find one which does. - if (force || !ValidDivisors.Value.Presets.Contains(divisor)) + if (preferKnownPresets || !ValidDivisors.Value.Presets.Contains(divisor)) { if (BeatDivisorPresetCollection.COMMON.Presets.Contains(divisor)) ValidDivisors.Value = BeatDivisorPresetCollection.COMMON; From 8aea6e07c31127f9b93540d9b99c295f9ca3463c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 16:31:33 +0900 Subject: [PATCH 081/915] Change slider end miss colour to gray --- osu.Game/Graphics/OsuColour.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 1b5877b966..985898958c 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -77,7 +77,7 @@ namespace osu.Game.Graphics { case HitResult.IgnoreMiss: case HitResult.SmallTickMiss: - return Orange1; + return Color4.Gray; case HitResult.Miss: case HitResult.LargeTickMiss: From dda96d71063796af8a3d4344ba080005447283e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 16:33:52 +0900 Subject: [PATCH 082/915] Rename `JudgementPiece` to `TextJudgementPiece` --- osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs | 2 +- osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs | 2 +- osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs | 2 +- .../Judgements/{JudgementPiece.cs => TextJudgementPiece.cs} | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) rename osu.Game/Rulesets/Judgements/{JudgementPiece.cs => TextJudgementPiece.cs} (88%) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs index a191dee1ca..0052fd8b78 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonJudgementPiece.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Skinning.Argon { - public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement + public partial class ArgonJudgementPiece : TextJudgementPiece, IAnimatableJudgement { private const float judgement_y_position = 160; diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs index 9a5abba4fb..83992fc785 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPiece.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Skinning.Argon { - public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement + public partial class ArgonJudgementPiece : TextJudgementPiece, IAnimatableJudgement { private RingExplosion? ringExplosion; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs index bbd62ff85b..724e387cc7 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonJudgementPiece.cs @@ -17,7 +17,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Taiko.Skinning.Argon { - public partial class ArgonJudgementPiece : JudgementPiece, IAnimatableJudgement + public partial class ArgonJudgementPiece : TextJudgementPiece, IAnimatableJudgement { private RingExplosion? ringExplosion; diff --git a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs index 7330f138ce..458d79cc00 100644 --- a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs +++ b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Rulesets.Judgements { - public partial class DefaultJudgementPiece : JudgementPiece, IAnimatableJudgement + public partial class DefaultJudgementPiece : TextJudgementPiece, IAnimatableJudgement { public DefaultJudgementPiece(HitResult result) : base(result) diff --git a/osu.Game/Rulesets/Judgements/JudgementPiece.cs b/osu.Game/Rulesets/Judgements/TextJudgementPiece.cs similarity index 88% rename from osu.Game/Rulesets/Judgements/JudgementPiece.cs rename to osu.Game/Rulesets/Judgements/TextJudgementPiece.cs index 03f211c318..42527705eb 100644 --- a/osu.Game/Rulesets/Judgements/JudgementPiece.cs +++ b/osu.Game/Rulesets/Judgements/TextJudgementPiece.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Judgements { - public abstract partial class JudgementPiece : CompositeDrawable + public abstract partial class TextJudgementPiece : CompositeDrawable { protected readonly HitResult Result; @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Judgements [Resolved] private OsuColour colours { get; set; } = null!; - protected JudgementPiece(HitResult result) + protected TextJudgementPiece(HitResult result) { Result = result; } From 6070eac6eec64852a8aa27a2c283cf9388c6ad5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 18:48:14 +0900 Subject: [PATCH 083/915] Remove dead code --- osu.Game/Skinning/LegacyJudgementPieceNew.cs | 2 +- osu.Game/Skinning/LegacyJudgementPieceOld.cs | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game/Skinning/LegacyJudgementPieceNew.cs b/osu.Game/Skinning/LegacyJudgementPieceNew.cs index 5ff28726c0..bd1508b4a6 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceNew.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceNew.cs @@ -53,7 +53,7 @@ namespace osu.Game.Skinning if (!result.IsMiss()) { //new judgement shows old as a temporary effect - AddInternal(temporaryOldStyle = new LegacyJudgementPieceOld(result, createMainDrawable, 1.05f, true) + AddInternal(temporaryOldStyle = new LegacyJudgementPieceOld(result, createMainDrawable, 1.05f) { Blending = BlendingParameters.Additive, Anchor = Anchor.Centre, diff --git a/osu.Game/Skinning/LegacyJudgementPieceOld.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs index a9f68bd378..55c81e4e41 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceOld.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -18,16 +18,14 @@ namespace osu.Game.Skinning private readonly HitResult result; private readonly float finalScale; - private readonly bool forceTransforms; [Resolved] private ISkinSource skin { get; set; } = null!; - public LegacyJudgementPieceOld(HitResult result, Func createMainDrawable, float finalScale = 1f, bool forceTransforms = false) + public LegacyJudgementPieceOld(HitResult result, Func createMainDrawable, float finalScale = 1f) { this.result = result; this.finalScale = finalScale; - this.forceTransforms = forceTransforms; AutoSizeAxes = Axes.Both; Origin = Anchor.Centre; @@ -48,14 +46,6 @@ namespace osu.Game.Skinning this.FadeInFromZero(fade_in_length); this.Delay(fade_out_delay).FadeOut(fade_out_length); - // legacy judgements don't play any transforms if they are an animation.... UNLESS they are the temporary displayed judgement from new piece. - if (animation?.FrameCount > 1 && !forceTransforms) - { - if (isMissedTick()) - applyMissedTickScaling(); - return; - } - if (result.IsMiss()) { decimal? legacyVersion = skin.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value; From d0421fe20667530bf1bca1a5c8e3f387dde0cf6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 18:50:45 +0900 Subject: [PATCH 084/915] Move fade more local to avoid fading twice --- osu.Game/Skinning/LegacyJudgementPieceOld.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacyJudgementPieceOld.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs index 55c81e4e41..c15ff041d1 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceOld.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -44,7 +44,6 @@ namespace osu.Game.Skinning const double fade_out_length = 600; this.FadeInFromZero(fade_in_length); - this.Delay(fade_out_delay).FadeOut(fade_out_length); if (result.IsMiss()) { @@ -74,6 +73,8 @@ namespace osu.Game.Skinning this.RotateTo(0); this.RotateTo(rotation, fade_in_length) .Then().RotateTo(rotation * 2, fade_out_delay + fade_out_length - fade_in_length, Easing.In); + + this.Delay(fade_out_delay).FadeOut(fade_out_length); } } else @@ -87,6 +88,8 @@ namespace osu.Game.Skinning // so we need to force the current value to be correct at 1.2 (0.95) then complete the // second half of the transform. .ScaleTo(0.95f).ScaleTo(finalScale, fade_in_length * 0.2f); // t = 1.4 + + this.Delay(fade_out_delay).FadeOut(fade_out_length); } } From 0175f6e0b8f5357a161211474e07af840dcf1852 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 18:23:25 +0900 Subject: [PATCH 085/915] Add new judgement drawable for argon slider misses --- .../ArgonJudgementPieceSliderTickMiss.cs | 51 +++++++++++++++++++ .../Skinning/Argon/ArgonSliderScorePoint.cs | 4 +- .../Skinning/Argon/OsuArgonSkinTransformer.cs | 14 ++++- 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs new file mode 100644 index 0000000000..878e8dbfc2 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs @@ -0,0 +1,51 @@ +// 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.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Skinning.Argon +{ + public partial class ArgonJudgementPieceSliderTickMiss : CompositeDrawable, IAnimatableJudgement + { + private readonly HitResult result; + private Circle piece = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + public ArgonJudgementPieceSliderTickMiss(HitResult result) + { + this.result = result; + } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(piece = new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + Colour = colours.ForHitResult(result), + Size = new Vector2(ArgonSliderScorePoint.SIZE) + }); + } + + public void PlayAnimation() + { + this.ScaleTo(1.4f); + this.ScaleTo(1f, 150, Easing.Out); + + this.FadeOutFromOne(400); + } + + public Drawable? GetAboveHitObjectsProxiedContent() => piece.CreateProxy(); + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderScorePoint.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderScorePoint.cs index 7479c2aced..e9ee432bac 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderScorePoint.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderScorePoint.cs @@ -16,14 +16,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon { private Bindable accentColour = null!; - private const float size = 12; + public const float SIZE = 12; [BackgroundDependencyLoader] private void load(DrawableHitObject hitObject) { Masking = true; Origin = Anchor.Centre; - Size = new Vector2(size); + Size = new Vector2(SIZE); BorderThickness = 3; BorderColour = Color4.White; Child = new Box diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/OsuArgonSkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/OsuArgonSkinTransformer.cs index 0f9c97059c..ec63e1194d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/OsuArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/OsuArgonSkinTransformer.cs @@ -19,11 +19,21 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon switch (lookup) { case GameplaySkinComponentLookup resultComponent: + HitResult result = resultComponent.Component; + // This should eventually be moved to a skin setting, when supported. - if (Skin is ArgonProSkin && (resultComponent.Component == HitResult.Great || resultComponent.Component == HitResult.Perfect)) + if (Skin is ArgonProSkin && (result == HitResult.Great || result == HitResult.Perfect)) return Drawable.Empty(); - return new ArgonJudgementPiece(resultComponent.Component); + switch (result) + { + case HitResult.IgnoreMiss: + case HitResult.LargeTickMiss: + return new ArgonJudgementPieceSliderTickMiss(result); + + default: + return new ArgonJudgementPiece(result); + } case OsuSkinComponentLookup osuComponent: // TODO: Once everything is finalised, consider throwing UnsupportedSkinComponentException on missing entries. From 107b37494ede1ca66a1b2cf4d669102d4c9804d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 19:14:04 +0900 Subject: [PATCH 086/915] Update triangles skin judgment display --- .../Objects/Drawables/DrawableSliderTick.cs | 6 +-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++ .../DefaultJudgementPieceSliderTickMiss.cs | 52 +++++++++++++++++++ .../Default/OsuTrianglesSkinTransformer.cs | 38 ++++++++++++++ .../Judgements/DefaultJudgementPiece.cs | 14 ----- osu.Game/Rulesets/Scoring/HitResult.cs | 2 - 6 files changed, 97 insertions(+), 19 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs create mode 100644 osu.Game.Rulesets.Osu/Skinning/Default/OsuTrianglesSkinTransformer.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index d64fb0bcc6..e457a50128 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public const double ANIM_DURATION = 150; - private const float default_tick_size = 16; + public const float DEFAULT_TICK_SIZE = 16; protected DrawableSlider DrawableSlider => (DrawableSlider)ParentHitObject; @@ -44,8 +44,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { Masking = true, Origin = Anchor.Centre, - Size = new Vector2(default_tick_size), - BorderThickness = default_tick_size / 4, + Size = new Vector2(DEFAULT_TICK_SIZE), + BorderThickness = DEFAULT_TICK_SIZE / 4, BorderColour = Color4.White, Child = new Box { diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 0496d1f680..6752712be1 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -28,6 +28,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.Skinning.Argon; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Rulesets.Osu.Statistics; using osu.Game.Rulesets.Osu.UI; @@ -254,6 +255,9 @@ namespace osu.Game.Rulesets.Osu case ArgonSkin: return new OsuArgonSkinTransformer(skin); + + case TrianglesSkin: + return new OsuTrianglesSkinTransformer(skin); } return null; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs new file mode 100644 index 0000000000..9fc71852ba --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs @@ -0,0 +1,52 @@ +// 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.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Skinning.Default +{ + public partial class DefaultJudgementPieceSliderTickMiss : CompositeDrawable, IAnimatableJudgement + { + private readonly HitResult result; + private Circle piece = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + public DefaultJudgementPieceSliderTickMiss(HitResult result) + { + this.result = result; + } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(piece = new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + Colour = colours.ForHitResult(result), + Size = new Vector2(DrawableSliderTick.DEFAULT_TICK_SIZE) + }); + } + + public void PlayAnimation() + { + this.ScaleTo(1.4f); + this.ScaleTo(1f, 150, Easing.Out); + + this.FadeOutFromOne(400); + } + + public Drawable? GetAboveHitObjectsProxiedContent() => piece.CreateProxy(); + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/OsuTrianglesSkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/OsuTrianglesSkinTransformer.cs new file mode 100644 index 0000000000..7a4c768aa2 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Default/OsuTrianglesSkinTransformer.cs @@ -0,0 +1,38 @@ +// 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.Graphics; +using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Osu.Skinning.Default +{ + public class OsuTrianglesSkinTransformer : SkinTransformer + { + public OsuTrianglesSkinTransformer(ISkin skin) + : base(skin) + { + } + + public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup) + { + switch (lookup) + { + case GameplaySkinComponentLookup resultComponent: + HitResult result = resultComponent.Component; + + switch (result) + { + case HitResult.IgnoreMiss: + case HitResult.LargeTickMiss: + // use argon judgement piece for new tick misses because i don't want to design another one for triangles. + return new DefaultJudgementPieceSliderTickMiss(result); + } + + break; + } + + return base.GetDrawableComponent(lookup); + } + } +} diff --git a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs index 458d79cc00..61b72a6066 100644 --- a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs +++ b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs @@ -38,20 +38,6 @@ namespace osu.Game.Rulesets.Judgements /// public virtual void PlayAnimation() { - // TODO: make these better. currently they are using a text `-` and it's not centered properly. - // Should be an explicit drawable. - // - // When this is done, remove the [Description] attributes from HitResults which were added for this purpose. - if (Result == HitResult.IgnoreMiss || Result == HitResult.LargeTickMiss) - { - this.RotateTo(-45); - this.ScaleTo(1.6f); - this.ScaleTo(1.2f, 100, Easing.In); - - this.FadeOutFromOne(400); - return; - } - if (Result.IsMiss()) { this.ScaleTo(1.6f); diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 7e58df3cfa..20ec3c4946 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -86,7 +86,6 @@ namespace osu.Game.Rulesets.Scoring /// Indicates a large tick miss. /// [EnumMember(Value = "large_tick_miss")] - [Description("-")] [Order(11)] LargeTickMiss, @@ -118,7 +117,6 @@ namespace osu.Game.Rulesets.Scoring /// Indicates a miss that should be ignored for scoring purposes. /// [EnumMember(Value = "ignore_miss")] - [Description("-")] [Order(14)] IgnoreMiss, From fd9527d5233fd6254d4b8a627fd4b07588dbc496 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 19:25:42 +0900 Subject: [PATCH 087/915] Remove weird red fade that didn't work --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index e457a50128..73c061afbd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -88,8 +88,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; case ArmedState.Miss: - this.FadeOut(ANIM_DURATION); - this.TransformBindableTo(AccentColour, Color4.Red, 0); + this.FadeOut(ANIM_DURATION, Easing.OutQuint); break; case ArmedState.Hit: From 56a9b059e9ff32b1be5288cd7f4a92921cc49542 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 19:42:38 +0900 Subject: [PATCH 088/915] Add back `ScaleAdjust` to triangles --- osu.Game/Graphics/Backgrounds/TrianglesV2.cs | 24 ++++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs index 706b05f5ad..bcb73f71cc 100644 --- a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs +++ b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs @@ -1,17 +1,18 @@ // 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.Utils; -using osuTK; using System; -using osu.Framework.Graphics.Shaders; -using osu.Framework.Graphics.Textures; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Allocation; using System.Collections.Generic; -using osu.Framework.Graphics.Rendering; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Shaders; +using osu.Framework.Graphics.Textures; +using osu.Framework.Utils; +using osuTK; namespace osu.Game.Graphics.Backgrounds { @@ -27,6 +28,8 @@ namespace osu.Game.Graphics.Backgrounds public float Thickness { get; set; } = 0.02f; // No need for invalidation since it's happening in Update() + public float ScaleAdjust { get; set; } = 1; + /// /// Whether we should create new triangles as others expire. /// @@ -106,7 +109,7 @@ namespace osu.Game.Graphics.Backgrounds parts[i] = newParticle; - float bottomPos = parts[i].Position.Y + triangle_size * equilateral_triangle_ratio / DrawHeight; + float bottomPos = parts[i].Position.Y + triangle_size * ScaleAdjust * equilateral_triangle_ratio / DrawHeight; if (bottomPos < 0) parts.RemoveAt(i); } @@ -149,7 +152,7 @@ namespace osu.Game.Graphics.Backgrounds if (randomY) { // since triangles are drawn from the top - allow them to be positioned a bit above the screen - float maxOffset = triangle_size * equilateral_triangle_ratio / DrawHeight; + float maxOffset = triangle_size * ScaleAdjust * equilateral_triangle_ratio / DrawHeight; y = Interpolation.ValueAt(nextRandom(), -maxOffset, 1f, 0f, 1f); } @@ -188,7 +191,7 @@ namespace osu.Game.Graphics.Backgrounds private readonly List parts = new List(); - private readonly Vector2 triangleSize = new Vector2(1f, equilateral_triangle_ratio) * triangle_size; + private Vector2 triangleSize; private Vector2 size; private float thickness; @@ -209,6 +212,7 @@ namespace osu.Game.Graphics.Backgrounds size = Source.DrawSize; thickness = Source.Thickness; clampAxes = Source.ClampAxes; + triangleSize = new Vector2(1f, equilateral_triangle_ratio) * triangle_size * Source.ScaleAdjust; Quad triangleQuad = new Quad( Vector2Extensions.Transform(Vector2.Zero, DrawInfo.Matrix), From 4a629fbc799093c96ec824f979c7258cdf5370ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 19:43:08 +0900 Subject: [PATCH 089/915] Update logo to new version --- osu.Game/Screens/Menu/OsuLogo.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 75ef8be02e..624c78bdb8 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -10,6 +10,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; 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; @@ -31,15 +32,13 @@ namespace osu.Game.Screens.Menu /// public partial class OsuLogo : BeatSyncedContainer { - public readonly Color4 OsuPink = Color4Extensions.FromHex(@"e967a1"); - private const double transition_length = 300; /// /// The osu! logo sprite has a shadow included in its texture. /// This adjustment vector is used to match the precise edge of the border of the logo. /// - public static readonly Vector2 SCALE_ADJUST = new Vector2(0.96f); + public static readonly Vector2 SCALE_ADJUST = new Vector2(0.94f); private readonly Sprite logo; private readonly CircularContainer logoContainer; @@ -58,7 +57,7 @@ namespace osu.Game.Screens.Menu private Sample sampleDownbeat; private readonly Container colourAndTriangles; - private readonly Triangles triangles; + private readonly TrianglesV2 triangles; /// /// Return value decides whether the logo should play its own sample for the click action. @@ -184,13 +183,17 @@ namespace osu.Game.Screens.Menu new Box { RelativeSizeAxes = Axes.Both, - Colour = OsuPink, + Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex(@"ff66ab"), Color4Extensions.FromHex(@"cc5289")), }, - triangles = new Triangles + triangles = new TrianglesV2 { - TriangleScale = 4, - ColourLight = Color4Extensions.FromHex(@"ff7db7"), - ColourDark = Color4Extensions.FromHex(@"de5b95"), + ClampAxes = Axes.X, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Thickness = 0.009f, + ScaleAdjust = 3, + SpawnRatio = 1.2f, + Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex(@"ff66ab"), Color4Extensions.FromHex(@"b6346f")), RelativeSizeAxes = Axes.Both, }, } From 7476d307d3b71f46aec187b2c16b60a51458d959 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 19:49:52 +0900 Subject: [PATCH 090/915] Update repository resources --- assets/lazer-nuget.png | Bin 12471 -> 12770 bytes assets/lazer.png | Bin 191397 -> 326320 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/lazer-nuget.png b/assets/lazer-nuget.png index c2a587fdc26734c1f263023d7eefa8fd644e978b..98a152a5a05b40b857780b2682be6a126151ba72 100644 GIT binary patch literal 12770 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 literal 12471 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 BjmH20 diff --git a/assets/lazer.png b/assets/lazer.png index 1e40e844ccb4f6065bbdb28a591af35ed78ada35..484bc0a449bb2ee813fad5180a1f74d368d75e2e 100644 GIT binary patch literal 326320 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⩔30V^aN^)*_D&yQ2xLHAa-!JJ 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 z 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 literal 191397 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

grX5kAnI7=yXit`@W>Pbv5O3$W*%9No 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%0D!HvI2srO7R>s0u0X(o9pX;k-Xz_y?7-o4VgT%# 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.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 VCItYF2In1!ZDDF{Qek{8`d_IH0SW*B From 7e8b3d03fa583a86ffafbdff573e9ed51a9178df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 19:56:40 +0900 Subject: [PATCH 091/915] Update copyright years --- Directory.Build.props | 2 +- LICENCE | 2 +- Templates/osu.Game.Templates.csproj | 4 ++-- osu.Desktop/osu.nuspec | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 734374c840..b08283f071 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -35,7 +35,7 @@ https://github.com/ppy/osu Automated release. ppy Pty Ltd - Copyright (c) 2022 ppy Pty Ltd + Copyright (c) 2024 ppy Pty Ltd osu game diff --git a/LICENCE b/LICENCE index d3e7537cef..3bb8b62d5d 100644 --- a/LICENCE +++ b/LICENCE @@ -1,4 +1,4 @@ -Copyright (c) 2022 ppy Pty Ltd . +Copyright (c) 2024 ppy Pty Ltd . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Templates/osu.Game.Templates.csproj b/Templates/osu.Game.Templates.csproj index b8c3ad373a..186a6093f5 100644 --- a/Templates/osu.Game.Templates.csproj +++ b/Templates/osu.Game.Templates.csproj @@ -1,4 +1,4 @@ - + Template ppy.osu.Game.Templates @@ -8,7 +8,7 @@ https://github.com/ppy/osu/blob/master/Templates https://github.com/ppy/osu Automated release. - Copyright (c) 2022 ppy Pty Ltd + Copyright (c) 2024 ppy Pty Ltd Templates to use when creating a ruleset for consumption in osu!. dotnet-new;templates;osu netstandard2.1 diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec index db58c325bd..3dadc4e002 100644 --- a/osu.Desktop/osu.nuspec +++ b/osu.Desktop/osu.nuspec @@ -11,7 +11,7 @@ false A free-to-win rhythm game. Rhythm is just a *click* away! testing - Copyright (c) 2022 ppy Pty Ltd + Copyright (c) 2024 ppy Pty Ltd en-AU From 2941787f5eec8543f68bbc9be89ca69b118ad9c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 20:35:33 +0900 Subject: [PATCH 092/915] Update windows logo --- osu.Desktop/lazer.ico | Bin 86650 -> 67263 bytes 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 osu.Desktop/lazer.ico diff --git a/osu.Desktop/lazer.ico b/osu.Desktop/lazer.ico old mode 100755 new mode 100644 index a6aa8abb9f3f10a2aac07c1168d9a2adb25ce1ea..5051c00ffc79eceac173442cd0466750d8e3aaa6 GIT binary patch literal 67263 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 literal 86650 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

@r7l@_>dLwGP1inIvgp>RYo9-;{?Vr` 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 Date: Thu, 25 Jan 2024 21:02:22 +0900 Subject: [PATCH 093/915] Simplify `TaikoLegacyHitTarget` container hierarchy --- .../Skinning/Legacy/TaikoLegacyHitTarget.cs | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs index cf9d8dd52e..0b43f1c845 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs @@ -17,30 +17,24 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy { RelativeSizeAxes = Axes.Both; - InternalChild = new Container + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new Drawable[] + new Sprite { - new Sprite - { - Texture = skin.GetTexture("approachcircle"), - Scale = new Vector2(0.83f), - Alpha = 0.47f, // eyeballed to match stable - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - new Sprite - { - Texture = skin.GetTexture("taikobigcircle"), - Scale = new Vector2(0.8f), - Alpha = 0.22f, // eyeballed to match stable - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - } + Texture = skin.GetTexture("approachcircle"), + Scale = new Vector2(0.83f), + Alpha = 0.47f, // eyeballed to match stable + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new Sprite + { + Texture = skin.GetTexture("taikobigcircle"), + Scale = new Vector2(0.8f), + Alpha = 0.22f, // eyeballed to match stable + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, }; } } From 64ba95bbd664964409224a8f589b473af7d6ca1e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 21:11:33 +0900 Subject: [PATCH 094/915] Remove pointless comments --- osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 7fe0080e89..6caaab1508 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -48,7 +48,6 @@ namespace osu.Game.Beatmaps.Drawables Colour = colours.Gray3, RelativeSizeAxes = Axes.Both }, - // Headers new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -70,7 +69,6 @@ namespace osu.Game.Beatmaps.Drawables Anchor = Anchor.Centre, Origin = Anchor.Centre }, - // Difficulty stats difficultyFillFlowContainer = new FillFlowContainer { Anchor = Anchor.Centre, @@ -107,7 +105,6 @@ namespace osu.Game.Beatmaps.Drawables } } }, - // Misc stats miscFillFlowContainer = new FillFlowContainer { Anchor = Anchor.Centre, @@ -146,11 +143,9 @@ namespace osu.Game.Beatmaps.Drawables displayedContent = content; - // Header row starRating.Current.BindTarget = displayedContent.Difficulty; difficultyName.Text = displayedContent.BeatmapInfo.DifficultyName; - // Don't show difficulty stats if showExtendedTooltip is false if (!displayedContent.ShowExtendedTooltip) { difficultyFillFlowContainer.Hide(); @@ -158,7 +153,6 @@ namespace osu.Game.Beatmaps.Drawables return; } - // Show the difficulty stats if showExtendedTooltip is true difficultyFillFlowContainer.Show(); miscFillFlowContainer.Show(); @@ -185,13 +179,11 @@ namespace osu.Game.Beatmaps.Drawables Ruleset ruleset = displayedContent.Ruleset.CreateInstance(); BeatmapDifficulty adjustedDifficulty = ruleset.GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); - // Difficulty row circleSize.Text = "CS: " + adjustedDifficulty.CircleSize.ToString("0.##"); drainRate.Text = " HP: " + adjustedDifficulty.DrainRate.ToString("0.##"); approachRate.Text = " AR: " + adjustedDifficulty.ApproachRate.ToString("0.##"); overallDifficulty.Text = " OD: " + adjustedDifficulty.OverallDifficulty.ToString("0.##"); - // Misc row length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length / rate).ToString("mm\\:ss"); bpm.Text = " BPM: " + Math.Round(bpmAdjusted, 0); } From 3c18efed0530c362ae363c84f5a5321c7e60eb3e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 21:13:25 +0900 Subject: [PATCH 095/915] Remove transparency --- osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 6caaab1508..fa07b150d5 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -44,7 +44,6 @@ namespace osu.Game.Beatmaps.Drawables { new Box { - Alpha = 0.9f, Colour = colours.Gray3, RelativeSizeAxes = Axes.Both }, From aeac0a2a9d83c741b65c81e04ab445061d94324d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 21:16:12 +0900 Subject: [PATCH 096/915] Nullability --- .../Drawables/DifficultyIconTooltip.cs | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index fa07b150d5..803618f15e 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -21,17 +19,17 @@ namespace osu.Game.Beatmaps.Drawables { internal partial class DifficultyIconTooltip : VisibilityContainer, ITooltip { - private OsuSpriteText difficultyName; - private StarRatingDisplay starRating; - private OsuSpriteText overallDifficulty; - private OsuSpriteText drainRate; - private OsuSpriteText circleSize; - private OsuSpriteText approachRate; - private OsuSpriteText bpm; - private OsuSpriteText length; + private OsuSpriteText difficultyName = null!; + private StarRatingDisplay starRating = null!; + private OsuSpriteText overallDifficulty = null!; + private OsuSpriteText drainRate = null!; + private OsuSpriteText circleSize = null!; + private OsuSpriteText approachRate = null!; + private OsuSpriteText bpm = null!; + private OsuSpriteText length = null!; - private FillFlowContainer difficultyFillFlowContainer; - private FillFlowContainer miscFillFlowContainer; + private FillFlowContainer difficultyFillFlowContainer = null!; + private FillFlowContainer miscFillFlowContainer = null!; [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -133,7 +131,7 @@ namespace osu.Game.Beatmaps.Drawables }; } - private DifficultyIconTooltipContent displayedContent; + private DifficultyIconTooltipContent? displayedContent; public void SetContent(DifficultyIconTooltipContent content) { @@ -178,12 +176,12 @@ namespace osu.Game.Beatmaps.Drawables Ruleset ruleset = displayedContent.Ruleset.CreateInstance(); BeatmapDifficulty adjustedDifficulty = ruleset.GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); - circleSize.Text = "CS: " + adjustedDifficulty.CircleSize.ToString("0.##"); - drainRate.Text = " HP: " + adjustedDifficulty.DrainRate.ToString("0.##"); - approachRate.Text = " AR: " + adjustedDifficulty.ApproachRate.ToString("0.##"); - overallDifficulty.Text = " OD: " + adjustedDifficulty.OverallDifficulty.ToString("0.##"); + circleSize.Text = @"CS: " + adjustedDifficulty.CircleSize.ToString(@"0.##"); + drainRate.Text = @" HP: " + adjustedDifficulty.DrainRate.ToString(@"0.##"); + approachRate.Text = @" AR: " + adjustedDifficulty.ApproachRate.ToString(@"0.##"); + overallDifficulty.Text = @" OD: " + adjustedDifficulty.OverallDifficulty.ToString(@"0.##"); - length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length / rate).ToString("mm\\:ss"); + length.Text = "Length: " + TimeSpan.FromMilliseconds(displayedContent.BeatmapInfo.Length / rate).ToString(@"mm\:ss"); bpm.Text = " BPM: " + Math.Round(bpmAdjusted, 0); } @@ -199,10 +197,10 @@ namespace osu.Game.Beatmaps.Drawables public readonly IBeatmapInfo BeatmapInfo; public readonly IBindable Difficulty; public readonly IRulesetInfo Ruleset; - public readonly Mod[] Mods; + public readonly Mod[]? Mods; public readonly bool ShowExtendedTooltip; - public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[] mods, bool showExtendedTooltip = false) + public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[]? mods, bool showExtendedTooltip = false) { BeatmapInfo = beatmapInfo; Difficulty = difficulty; From 50300adef86222ed1554f512dafe857cf25d2cf3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 21:17:29 +0900 Subject: [PATCH 097/915] Tidy things up --- .../Drawables/DifficultyIconTooltip.cs | 44 +++---------------- 1 file changed, 6 insertions(+), 38 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 803618f15e..71366de654 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -76,30 +76,10 @@ namespace osu.Game.Beatmaps.Drawables Spacing = new Vector2(5), Children = new Drawable[] { - circleSize = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14) - }, - drainRate = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14) - }, - approachRate = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14) - }, - overallDifficulty = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14) - } + circleSize = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, + drainRate = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, + approachRate = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, + overallDifficulty = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) } } }, miscFillFlowContainer = new FillFlowContainer @@ -112,18 +92,8 @@ namespace osu.Game.Beatmaps.Drawables Spacing = new Vector2(5), Children = new Drawable[] { - length = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14) - }, - bpm = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 14) - }, + length = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, + bpm = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, } } } @@ -168,9 +138,7 @@ namespace osu.Game.Beatmaps.Drawables if (displayedContent.Mods != null) { foreach (var mod in displayedContent.Mods.OfType()) - { mod.ApplyToDifficulty(originalDifficulty); - } } Ruleset ruleset = displayedContent.Ruleset.CreateInstance(); From 3f9c2b41f7080639d3f4d94097cfeb3238ee503a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 21:28:08 +0900 Subject: [PATCH 098/915] Adjust `BeatSyncContainer`'s early animate offset based on source's rate --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index f911311a09..a14dfd4d64 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -91,7 +91,17 @@ namespace osu.Game.Graphics.Containers if (IsBeatSyncedWithTrack) { - currentTrackTime = BeatSyncSource.Clock.CurrentTime + EarlyActivationMilliseconds; + double early = EarlyActivationMilliseconds; + + // In the case of gameplay, we are usually within a hierarchy with the correct rate applied to our `Drawable.Clock`. + // This means that the amount of early adjustment is adjusted in line with audio track rate changes. + // But other cases like the osu! logo at the main menu won't correctly have this rate information. + // + // So for cases where the rate of the source isn't in sync with our hierarchy, let's assume we need to account for it locally. + if (Clock.Rate == 1 && BeatSyncSource.Clock.Rate != Clock.Rate) + early *= BeatSyncSource.Clock.Rate; + + currentTrackTime = BeatSyncSource.Clock.CurrentTime + early; timingPoint = BeatSyncSource.ControlPoints?.TimingPointAt(currentTrackTime) ?? TimingControlPoint.DEFAULT; effectPoint = BeatSyncSource.ControlPoints?.EffectPointAt(currentTrackTime) ?? EffectControlPoint.DEFAULT; From 6a338ce5551c9ce8de5af42a06886c7c951e2cbf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 Jan 2024 21:59:38 +0900 Subject: [PATCH 099/915] Adjust spawn ratio up slightly --- osu.Game/Screens/Menu/OsuLogo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 624c78bdb8..a39d552a90 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -192,7 +192,7 @@ namespace osu.Game.Screens.Menu Origin = Anchor.Centre, Thickness = 0.009f, ScaleAdjust = 3, - SpawnRatio = 1.2f, + SpawnRatio = 1.4f, Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex(@"ff66ab"), Color4Extensions.FromHex(@"b6346f")), RelativeSizeAxes = Axes.Both, }, From c35df0313f758c4747cbfe5f43e983511d005205 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 25 Jan 2024 16:31:12 +0300 Subject: [PATCH 100/915] Fix taiko playfield test scene --- .../Skinning/TestSceneTaikoPlayfield.cs | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs index c89e2b727b..d1a8a048ed 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs @@ -1,17 +1,19 @@ // 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 NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; +using osuTK; namespace osu.Game.Rulesets.Taiko.Tests.Skinning { @@ -37,11 +39,14 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning Beatmap.Value.Track.Start(); }); - AddStep("Load playfield", () => SetContents(_ => new TaikoPlayfield + AddStep("Load playfield", () => SetContents(_ => new Container { - Height = 0.2f, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(2f, 1f), + Scale = new Vector2(0.5f), + Child = new TaikoPlayfieldAdjustmentContainer { Child = new TaikoPlayfield() }, })); } @@ -54,7 +59,20 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning [Test] public void TestHeightChanges() { - AddRepeatStep("change height", () => this.ChildrenOfType().ForEach(p => p.Height = Math.Max(0.2f, (p.Height + 0.2f) % 1f)), 50); + int value = 0; + + AddRepeatStep("change height", () => + { + value = (value + 1) % 5; + + this.ChildrenOfType().ForEach(p => + { + var parent = (Container)p.Parent.AsNonNull(); + parent.Scale = new Vector2(0.5f + 0.1f * value); + parent.Width = 1f / parent.Scale.X; + parent.Height = 0.5f / parent.Scale.Y; + }); + }, 50); } [Test] From de52f0a80c088d6f6fb4bc8008a1f525d6783a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 25 Jan 2024 12:25:27 +0100 Subject: [PATCH 101/915] Decouple notifications websocket handling from chat operations This is a prerequisite for https://github.com/ppy/osu/pull/25480. The `WebSocketNotificationsClient` was tightly coupled to chat specifics making it difficult to use in the second factor verification flow. This commit's goal is to separate the websocket connection and message handling concerns from specific chat logic concerns. --- .../Chat/TestSceneChannelManager.cs | 2 - osu.Game/Online/API/APIAccess.cs | 8 +- osu.Game/Online/API/DummyAPIAccess.cs | 8 +- osu.Game/Online/API/IAPIProvider.cs | 10 +- osu.Game/Online/Chat/ChannelManager.cs | 26 +-- osu.Game/Online/Chat/IChatClient.cs | 18 +++ osu.Game/Online/Chat/WebSocketChatClient.cs | 148 ++++++++++++++++++ .../NotificationsClientConnector.cs | 42 ----- .../WebSocket/DummyNotificationsClient.cs | 29 ++++ .../WebSocket/INotificationsClient.cs | 17 ++ .../WebSocket/WebSocketNotificationsClient.cs | 79 +--------- .../WebSocketNotificationsClientConnector.cs | 20 ++- .../PollingChatClient.cs} | 41 ++--- osu.Game/Tests/PollingChatClientConnector.cs | 48 ++++++ osu.Game/Tests/PollingNotificationsClient.cs | 35 ----- .../PollingNotificationsClientConnector.cs | 24 --- 16 files changed, 330 insertions(+), 225 deletions(-) create mode 100644 osu.Game/Online/Chat/IChatClient.cs create mode 100644 osu.Game/Online/Chat/WebSocketChatClient.cs delete mode 100644 osu.Game/Online/Notifications/NotificationsClientConnector.cs create mode 100644 osu.Game/Online/Notifications/WebSocket/DummyNotificationsClient.cs create mode 100644 osu.Game/Online/Notifications/WebSocket/INotificationsClient.cs rename osu.Game/{Online/Notifications/NotificationsClient.cs => Tests/PollingChatClient.cs} (59%) create mode 100644 osu.Game/Tests/PollingChatClientConnector.cs delete mode 100644 osu.Game/Tests/PollingNotificationsClient.cs delete mode 100644 osu.Game/Tests/PollingNotificationsClientConnector.cs diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index eae12edebd..95fd2669e5 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -75,8 +75,6 @@ namespace osu.Game.Tests.Chat return false; }; }); - - AddUntilStep("wait for notifications client", () => channelManager.NotificationsConnected); } [Test] diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 17bf8bcc37..359c52553d 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -21,7 +21,7 @@ using osu.Game.Configuration; using osu.Game.Localisation; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Notifications; +using osu.Game.Online.Chat; using osu.Game.Online.Notifications.WebSocket; using osu.Game.Users; @@ -55,6 +55,8 @@ namespace osu.Game.Online.API public IBindable Activity => activity; public IBindable Statistics => statistics; + public INotificationsClient NotificationsClient { get; } + public Language Language => game.CurrentLanguage.Value; private Bindable localUser { get; } = new Bindable(createGuestUser()); @@ -82,6 +84,7 @@ namespace osu.Game.Online.API APIEndpointUrl = endpointConfiguration.APIEndpointUrl; WebsiteRootUrl = endpointConfiguration.WebsiteRootUrl; + NotificationsClient = new WebSocketNotificationsClientConnector(this); authentication = new OAuth(endpointConfiguration.APIClientID, endpointConfiguration.APIClientSecret, APIEndpointUrl); log = Logger.GetLogger(LoggingTarget.Network); @@ -324,8 +327,7 @@ namespace osu.Game.Online.API public IHubClientConnector GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => new HubClientConnector(clientName, endpoint, this, versionHash, preferMessagePack); - public NotificationsClientConnector GetNotificationsConnector() => - new WebSocketNotificationsClientConnector(this); + public IChatClient GetChatClient() => new WebSocketChatClient(this); public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password) { diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 4b4f8061e0..2d5852b209 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -8,7 +8,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Notifications; +using osu.Game.Online.Chat; +using osu.Game.Online.Notifications.WebSocket; using osu.Game.Tests; using osu.Game.Users; @@ -30,6 +31,9 @@ namespace osu.Game.Online.API public Bindable Statistics { get; } = new Bindable(); + public DummyNotificationsClient NotificationsClient { get; } = new DummyNotificationsClient(); + INotificationsClient IAPIProvider.NotificationsClient => NotificationsClient; + public Language Language => Language.en; public string AccessToken => "token"; @@ -144,7 +148,7 @@ namespace osu.Game.Online.API public IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => null; - public NotificationsClientConnector GetNotificationsConnector() => new PollingNotificationsClientConnector(this); + public IChatClient GetChatClient() => new PollingChatClientConnector(this); public RegistrationRequest.RegistrationRequestErrors? CreateAccount(string email, string username, string password) { diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index b58d4a363a..ea4eb97ccb 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -6,7 +6,8 @@ using System.Threading.Tasks; using osu.Framework.Bindables; using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Notifications; +using osu.Game.Online.Chat; +using osu.Game.Online.Notifications.WebSocket; using osu.Game.Users; namespace osu.Game.Online.API @@ -129,10 +130,9 @@ namespace osu.Game.Online.API /// Whether to use MessagePack for serialisation if available on this platform. IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack = true); - ///

- /// Constructs a new . - /// - NotificationsClientConnector GetNotificationsConnector(); + INotificationsClient NotificationsClient { get; } + + IChatClient GetChatClient(); /// /// Create a new user account. This is a blocking operation. diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 23989caae2..d0c686a666 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -16,7 +16,6 @@ using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Notifications; using osu.Game.Overlays.Chat.Listing; namespace osu.Game.Online.Chat @@ -64,13 +63,8 @@ namespace osu.Game.Online.Chat /// public IBindableList AvailableChannels => availableChannels; - /// - /// Whether the client responsible for channel notifications is connected. - /// - public bool NotificationsConnected => connector.IsConnected.Value; - private readonly IAPIProvider api; - private readonly NotificationsClientConnector connector; + private readonly IChatClient chatClient; [Resolved] private UserLookupCache users { get; set; } @@ -85,7 +79,7 @@ namespace osu.Game.Online.Chat { this.api = api; - connector = api.GetNotificationsConnector(); + chatClient = api.GetChatClient(); CurrentChannel.ValueChanged += currentChannelChanged; } @@ -93,15 +87,11 @@ namespace osu.Game.Online.Chat [BackgroundDependencyLoader] private void load() { - connector.ChannelJoined += ch => Schedule(() => joinChannel(ch)); - - connector.ChannelParted += ch => Schedule(() => leaveChannel(getChannel(ch), false)); - - connector.NewMessages += msgs => Schedule(() => addMessages(msgs)); - - connector.PresenceReceived += () => Schedule(initializeChannels); - - connector.Start(); + chatClient.ChannelJoined += ch => Schedule(() => joinChannel(ch)); + chatClient.ChannelParted += ch => Schedule(() => leaveChannel(getChannel(ch), false)); + chatClient.NewMessages += msgs => Schedule(() => addMessages(msgs)); + chatClient.PresenceReceived += () => Schedule(initializeChannels); + chatClient.FetchInitialMessages(); apiState.BindTo(api.State); apiState.BindValueChanged(_ => SendAck(), true); @@ -655,7 +645,7 @@ namespace osu.Game.Online.Chat protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - connector?.Dispose(); + chatClient?.Dispose(); } } diff --git a/osu.Game/Online/Chat/IChatClient.cs b/osu.Game/Online/Chat/IChatClient.cs new file mode 100644 index 0000000000..94977b8acd --- /dev/null +++ b/osu.Game/Online/Chat/IChatClient.cs @@ -0,0 +1,18 @@ +// 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; + +namespace osu.Game.Online.Chat +{ + public interface IChatClient : IDisposable + { + event Action? ChannelJoined; + event Action? ChannelParted; + event Action>? NewMessages; + event Action? PresenceReceived; + + void FetchInitialMessages(); + } +} diff --git a/osu.Game/Online/Chat/WebSocketChatClient.cs b/osu.Game/Online/Chat/WebSocketChatClient.cs new file mode 100644 index 0000000000..fb67c205dc --- /dev/null +++ b/osu.Game/Online/Chat/WebSocketChatClient.cs @@ -0,0 +1,148 @@ +// 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.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using Newtonsoft.Json; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Logging; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.Notifications.WebSocket; + +namespace osu.Game.Online.Chat +{ + public class WebSocketChatClient : IChatClient + { + public event Action? ChannelJoined; + public event Action? ChannelParted; + public event Action>? NewMessages; + public event Action? PresenceReceived; + + private readonly IAPIProvider api; + private readonly INotificationsClient client; + private readonly ConcurrentDictionary channelsMap = new ConcurrentDictionary(); + + public WebSocketChatClient(IAPIProvider api) + { + this.api = api; + client = api.NotificationsClient; + client.IsConnected.BindValueChanged(start, true); + } + + private void start(ValueChangedEvent connected) + { + if (!connected.NewValue) + return; + + client.MessageReceived += onMessageReceived; + client.SendAsync(new StartChatRequest()).WaitSafely(); + } + + public void FetchInitialMessages() + { + api.Queue(createInitialFetchRequest()); + } + + private APIRequest createInitialFetchRequest() + { + var fetchReq = new GetUpdatesRequest(0); + + fetchReq.Success += updates => + { + if (updates?.Presence != null) + { + foreach (var channel in updates.Presence) + joinChannel(channel); + + handleMessages(updates.Messages); + } + + PresenceReceived?.Invoke(); + }; + + return fetchReq; + } + + private void onMessageReceived(SocketMessage message) + { + switch (message.Event) + { + case @"chat.channel.join": + Debug.Assert(message.Data != null); + + Channel? joinedChannel = JsonConvert.DeserializeObject(message.Data.ToString()); + Debug.Assert(joinedChannel != null); + + joinChannel(joinedChannel); + break; + + case @"chat.channel.part": + Debug.Assert(message.Data != null); + + Channel? partedChannel = JsonConvert.DeserializeObject(message.Data.ToString()); + Debug.Assert(partedChannel != null); + + partChannel(partedChannel); + break; + + case @"chat.message.new": + Debug.Assert(message.Data != null); + + NewChatMessageData? messageData = JsonConvert.DeserializeObject(message.Data.ToString()); + Debug.Assert(messageData != null); + + foreach (var msg in messageData.Messages) + postToChannel(msg); + + break; + } + } + + private void postToChannel(Message message) + { + if (channelsMap.TryGetValue(message.ChannelId, out Channel? channel)) + { + joinChannel(channel); + NewMessages?.Invoke(new List { message }); + return; + } + + var req = new GetChannelRequest(message.ChannelId); + + req.Success += response => + { + joinChannel(channelsMap[message.ChannelId] = response.Channel); + NewMessages?.Invoke(new List { message }); + }; + req.Failure += ex => Logger.Error(ex, "Failed to join channel"); + + api.Queue(req); + } + + private void joinChannel(Channel ch) + { + ch.Joined.Value = true; + ChannelJoined?.Invoke(ch); + } + + private void partChannel(Channel channel) => ChannelParted?.Invoke(channel); + + private void handleMessages(List? messages) + { + if (messages == null) + return; + + NewMessages?.Invoke(messages); + } + + public void Dispose() + { + client.IsConnected.ValueChanged -= start; + client.MessageReceived -= onMessageReceived; + } + } +} diff --git a/osu.Game/Online/Notifications/NotificationsClientConnector.cs b/osu.Game/Online/Notifications/NotificationsClientConnector.cs deleted file mode 100644 index 34ce186cb8..0000000000 --- a/osu.Game/Online/Notifications/NotificationsClientConnector.cs +++ /dev/null @@ -1,42 +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 System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using osu.Game.Online.API; -using osu.Game.Online.Chat; - -namespace osu.Game.Online.Notifications -{ - /// - /// An abstract connector or s. - /// - public abstract class NotificationsClientConnector : PersistentEndpointClientConnector - { - public event Action? ChannelJoined; - public event Action? ChannelParted; - public event Action>? NewMessages; - public event Action? PresenceReceived; - - protected NotificationsClientConnector(IAPIProvider api) - : base(api) - { - } - - protected sealed override async Task BuildConnectionAsync(CancellationToken cancellationToken) - { - var client = await BuildNotificationClientAsync(cancellationToken).ConfigureAwait(false); - - client.ChannelJoined = c => ChannelJoined?.Invoke(c); - client.ChannelParted = c => ChannelParted?.Invoke(c); - client.NewMessages = m => NewMessages?.Invoke(m); - client.PresenceReceived = () => PresenceReceived?.Invoke(); - - return client; - } - - protected abstract Task BuildNotificationClientAsync(CancellationToken cancellationToken); - } -} diff --git a/osu.Game/Online/Notifications/WebSocket/DummyNotificationsClient.cs b/osu.Game/Online/Notifications/WebSocket/DummyNotificationsClient.cs new file mode 100644 index 0000000000..c1f3d25be7 --- /dev/null +++ b/osu.Game/Online/Notifications/WebSocket/DummyNotificationsClient.cs @@ -0,0 +1,29 @@ +// 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.Threading; +using System.Threading.Tasks; +using osu.Framework.Bindables; + +namespace osu.Game.Online.Notifications.WebSocket +{ + public class DummyNotificationsClient : INotificationsClient + { + public IBindable IsConnected => new BindableBool(true); + + public event Action? MessageReceived; + + public Func? HandleMessage; + + public Task SendAsync(SocketMessage message, CancellationToken? cancellationToken = default) + { + if (HandleMessage?.Invoke(message) != true) + throw new InvalidOperationException($@"{nameof(DummyNotificationsClient)} cannot process this message."); + + return Task.CompletedTask; + } + + public void Receive(SocketMessage message) => MessageReceived?.Invoke(message); + } +} diff --git a/osu.Game/Online/Notifications/WebSocket/INotificationsClient.cs b/osu.Game/Online/Notifications/WebSocket/INotificationsClient.cs new file mode 100644 index 0000000000..f687752047 --- /dev/null +++ b/osu.Game/Online/Notifications/WebSocket/INotificationsClient.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. + +using System; +using System.Threading; +using System.Threading.Tasks; +using osu.Framework.Bindables; + +namespace osu.Game.Online.Notifications.WebSocket +{ + public interface INotificationsClient + { + IBindable IsConnected { get; } + event Action? MessageReceived; + Task SendAsync(SocketMessage message, CancellationToken? cancellationToken = default); + } +} diff --git a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs index 73e5dcec6f..854f46880f 100644 --- a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs +++ b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Concurrent; using System.Diagnostics; using System.Net; using System.Net.WebSockets; @@ -12,23 +11,20 @@ using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Logging; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Online.Chat; namespace osu.Game.Online.Notifications.WebSocket { /// /// A notifications client which receives events via a websocket. /// - public class WebSocketNotificationsClient : NotificationsClient + public class WebSocketNotificationsClient : PersistentEndpointClient { + public event Action? MessageReceived; + private readonly ClientWebSocket socket; private readonly string endpoint; - private readonly ConcurrentDictionary channelsMap = new ConcurrentDictionary(); - public WebSocketNotificationsClient(ClientWebSocket socket, string endpoint, IAPIProvider api) - : base(api) + public WebSocketNotificationsClient(ClientWebSocket socket, string endpoint) { this.socket = socket; this.endpoint = endpoint; @@ -37,11 +33,7 @@ namespace osu.Game.Online.Notifications.WebSocket public override async Task ConnectAsync(CancellationToken cancellationToken) { await socket.ConnectAsync(new Uri(endpoint), cancellationToken).ConfigureAwait(false); - await sendMessage(new StartChatRequest(), CancellationToken.None).ConfigureAwait(false); - runReadLoop(cancellationToken); - - await base.ConnectAsync(cancellationToken).ConfigureAwait(false); } private void runReadLoop(CancellationToken cancellationToken) => Task.Run(async () => @@ -73,7 +65,7 @@ namespace osu.Game.Online.Notifications.WebSocket break; } - await onMessageReceivedAsync(message).ConfigureAwait(false); + MessageReceived?.Invoke(message); } break; @@ -105,69 +97,12 @@ namespace osu.Game.Online.Notifications.WebSocket } } - private async Task sendMessage(SocketMessage message, CancellationToken cancellationToken) + public async Task SendAsync(SocketMessage message, CancellationToken? cancellationToken = default) { if (socket.State != WebSocketState.Open) return; - await socket.SendAsync(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), WebSocketMessageType.Text, true, cancellationToken).ConfigureAwait(false); - } - - private async Task onMessageReceivedAsync(SocketMessage message) - { - switch (message.Event) - { - case @"chat.channel.join": - Debug.Assert(message.Data != null); - - Channel? joinedChannel = JsonConvert.DeserializeObject(message.Data.ToString()); - Debug.Assert(joinedChannel != null); - - HandleChannelJoined(joinedChannel); - break; - - case @"chat.channel.part": - Debug.Assert(message.Data != null); - - Channel? partedChannel = JsonConvert.DeserializeObject(message.Data.ToString()); - Debug.Assert(partedChannel != null); - - HandleChannelParted(partedChannel); - break; - - case @"chat.message.new": - Debug.Assert(message.Data != null); - - NewChatMessageData? messageData = JsonConvert.DeserializeObject(message.Data.ToString()); - Debug.Assert(messageData != null); - - foreach (var msg in messageData.Messages) - HandleChannelJoined(await getChannel(msg.ChannelId).ConfigureAwait(false)); - - HandleMessages(messageData.Messages); - break; - } - } - - private async Task getChannel(long channelId) - { - if (channelsMap.TryGetValue(channelId, out Channel? channel)) - return channel; - - var tsc = new TaskCompletionSource(); - var req = new GetChannelRequest(channelId); - - req.Success += response => - { - channelsMap[channelId] = response.Channel; - tsc.SetResult(response.Channel); - }; - - req.Failure += ex => tsc.SetException(ex); - - API.Queue(req); - - return await tsc.Task.ConfigureAwait(false); + await socket.SendAsync(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), WebSocketMessageType.Text, true, cancellationToken ?? CancellationToken.None).ConfigureAwait(false); } public override async ValueTask DisposeAsync() diff --git a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs index f50369a06c..73fe29d441 100644 --- a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs +++ b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.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.Net; using System.Net.WebSockets; using System.Threading; @@ -13,17 +14,20 @@ namespace osu.Game.Online.Notifications.WebSocket /// /// A connector for s that receive events via a websocket. /// - public class WebSocketNotificationsClientConnector : NotificationsClientConnector + public class WebSocketNotificationsClientConnector : PersistentEndpointClientConnector, INotificationsClient { + public event Action? MessageReceived; + private readonly IAPIProvider api; public WebSocketNotificationsClientConnector(IAPIProvider api) : base(api) { this.api = api; + Start(); } - protected override async Task BuildNotificationClientAsync(CancellationToken cancellationToken) + protected override async Task BuildConnectionAsync(CancellationToken cancellationToken) { var tcs = new TaskCompletionSource(); @@ -40,7 +44,17 @@ namespace osu.Game.Online.Notifications.WebSocket if (socket.Options.Proxy != null) socket.Options.Proxy.Credentials = CredentialCache.DefaultCredentials; - return new WebSocketNotificationsClient(socket, endpoint, api); + var client = new WebSocketNotificationsClient(socket, endpoint); + client.MessageReceived += msg => MessageReceived?.Invoke(msg); + return client; + } + + public Task SendAsync(SocketMessage message, CancellationToken? cancellationToken = default) + { + if (CurrentConnection is not WebSocketNotificationsClient webSocketClient) + return Task.CompletedTask; + + return webSocketClient.SendAsync(message, cancellationToken); } } } diff --git a/osu.Game/Online/Notifications/NotificationsClient.cs b/osu.Game/Tests/PollingChatClient.cs similarity index 59% rename from osu.Game/Online/Notifications/NotificationsClient.cs rename to osu.Game/Tests/PollingChatClient.cs index 5762e0e588..eb29b35c1d 100644 --- a/osu.Game/Online/Notifications/NotificationsClient.cs +++ b/osu.Game/Tests/PollingChatClient.cs @@ -6,34 +6,39 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; -namespace osu.Game.Online.Notifications +namespace osu.Game.Tests { - /// - /// An abstract client which receives notification-related events (chat/notifications). - /// - public abstract class NotificationsClient : PersistentEndpointClient + public class PollingChatClient : PersistentEndpointClient { - public Action? ChannelJoined; - public Action? ChannelParted; - public Action>? NewMessages; - public Action? PresenceReceived; + public event Action? ChannelJoined; + public event Action>? NewMessages; + public event Action? PresenceReceived; - protected readonly IAPIProvider API; + private readonly IAPIProvider api; private long lastMessageId; - protected NotificationsClient(IAPIProvider api) + public PollingChatClient(IAPIProvider api) { - API = api; + this.api = api; } public override Task ConnectAsync(CancellationToken cancellationToken) { - API.Queue(CreateInitialFetchRequest(0)); + Task.Run(async () => + { + while (!cancellationToken.IsCancellationRequested) + { + await api.PerformAsync(CreateInitialFetchRequest()).ConfigureAwait(true); + await Task.Delay(1000, cancellationToken).ConfigureAwait(true); + } + }, cancellationToken); + return Task.CompletedTask; } @@ -46,11 +51,11 @@ namespace osu.Game.Online.Notifications if (updates?.Presence != null) { foreach (var channel in updates.Presence) - HandleChannelJoined(channel); + handleChannelJoined(channel); //todo: handle left channels - HandleMessages(updates.Messages); + handleMessages(updates.Messages); } PresenceReceived?.Invoke(); @@ -59,15 +64,13 @@ namespace osu.Game.Online.Notifications return fetchReq; } - protected void HandleChannelJoined(Channel channel) + private void handleChannelJoined(Channel channel) { channel.Joined.Value = true; ChannelJoined?.Invoke(channel); } - protected void HandleChannelParted(Channel channel) => ChannelParted?.Invoke(channel); - - protected void HandleMessages(List? messages) + private void handleMessages(List? messages) { if (messages == null) return; diff --git a/osu.Game/Tests/PollingChatClientConnector.cs b/osu.Game/Tests/PollingChatClientConnector.cs new file mode 100644 index 0000000000..3e96a8cde7 --- /dev/null +++ b/osu.Game/Tests/PollingChatClientConnector.cs @@ -0,0 +1,48 @@ +// 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.Threading; +using System.Threading.Tasks; +using osu.Game.Online; +using osu.Game.Online.API; +using osu.Game.Online.Chat; + +namespace osu.Game.Tests +{ + public class PollingChatClientConnector : PersistentEndpointClientConnector, IChatClient + { + public event Action? ChannelJoined; + + public event Action? ChannelParted + { + add { } + remove { } + } + + public event Action>? NewMessages; + public event Action? PresenceReceived; + + public void FetchInitialMessages() + { + // don't really need to do anything special if we poll every second anyway. + } + + public PollingChatClientConnector(IAPIProvider api) + : base(api) + { + } + + protected sealed override Task BuildConnectionAsync(CancellationToken cancellationToken) + { + var client = new PollingChatClient(API); + + client.ChannelJoined += c => ChannelJoined?.Invoke(c); + client.NewMessages += m => NewMessages?.Invoke(m); + client.PresenceReceived += () => PresenceReceived?.Invoke(); + + return Task.FromResult(client); + } + } +} diff --git a/osu.Game/Tests/PollingNotificationsClient.cs b/osu.Game/Tests/PollingNotificationsClient.cs deleted file mode 100644 index 450c763170..0000000000 --- a/osu.Game/Tests/PollingNotificationsClient.cs +++ /dev/null @@ -1,35 +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.Threading; -using System.Threading.Tasks; -using osu.Game.Online.API; -using osu.Game.Online.Notifications; - -namespace osu.Game.Tests -{ - /// - /// A notifications client which polls for new messages every second. - /// - public class PollingNotificationsClient : NotificationsClient - { - public PollingNotificationsClient(IAPIProvider api) - : base(api) - { - } - - public override Task ConnectAsync(CancellationToken cancellationToken) - { - Task.Run(async () => - { - while (!cancellationToken.IsCancellationRequested) - { - await API.PerformAsync(CreateInitialFetchRequest()).ConfigureAwait(true); - await Task.Delay(1000, cancellationToken).ConfigureAwait(true); - } - }, cancellationToken); - - return Task.CompletedTask; - } - } -} diff --git a/osu.Game/Tests/PollingNotificationsClientConnector.cs b/osu.Game/Tests/PollingNotificationsClientConnector.cs deleted file mode 100644 index 823fc9d157..0000000000 --- a/osu.Game/Tests/PollingNotificationsClientConnector.cs +++ /dev/null @@ -1,24 +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.Threading; -using System.Threading.Tasks; -using osu.Game.Online.API; -using osu.Game.Online.Notifications; - -namespace osu.Game.Tests -{ - /// - /// A connector for s that poll for new messages. - /// - public class PollingNotificationsClientConnector : NotificationsClientConnector - { - public PollingNotificationsClientConnector(IAPIProvider api) - : base(api) - { - } - - protected override Task BuildNotificationClientAsync(CancellationToken cancellationToken) - => Task.FromResult((NotificationsClient)new PollingNotificationsClient(API)); - } -} From c463aa5ba1e67d0fc0fca5b5db5230a3875cf52a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 25 Jan 2024 14:46:39 +0100 Subject: [PATCH 102/915] xmldoc everything --- osu.Game/Online/API/IAPIProvider.cs | 6 ++++ osu.Game/Online/Chat/ChannelManager.cs | 2 +- osu.Game/Online/Chat/IChatClient.cs | 29 ++++++++++++++++--- osu.Game/Online/Chat/WebSocketChatClient.cs | 10 ++----- .../WebSocket/INotificationsClient.cs | 14 +++++++++ osu.Game/Tests/PollingChatClientConnector.cs | 2 +- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index ea4eb97ccb..a050b2dfae 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -130,8 +130,14 @@ namespace osu.Game.Online.API /// Whether to use MessagePack for serialisation if available on this platform. IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack = true); + /// + /// Accesses the used to receive asynchronous notifications from web. + /// INotificationsClient NotificationsClient { get; } + /// + /// Creates a instance to use in order to chat. + /// IChatClient GetChatClient(); /// diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index d0c686a666..74e85c595c 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -91,7 +91,7 @@ namespace osu.Game.Online.Chat chatClient.ChannelParted += ch => Schedule(() => leaveChannel(getChannel(ch), false)); chatClient.NewMessages += msgs => Schedule(() => addMessages(msgs)); chatClient.PresenceReceived += () => Schedule(initializeChannels); - chatClient.FetchInitialMessages(); + chatClient.RequestPresence(); apiState.BindTo(api.State); apiState.BindValueChanged(_ => SendAck(), true); diff --git a/osu.Game/Online/Chat/IChatClient.cs b/osu.Game/Online/Chat/IChatClient.cs index 94977b8acd..290ee22710 100644 --- a/osu.Game/Online/Chat/IChatClient.cs +++ b/osu.Game/Online/Chat/IChatClient.cs @@ -6,13 +6,34 @@ using System.Collections.Generic; namespace osu.Game.Online.Chat { + /// + /// Interface for consuming online chat. + /// public interface IChatClient : IDisposable { + /// + /// Fired when a has been joined. + /// event Action? ChannelJoined; - event Action? ChannelParted; - event Action>? NewMessages; - event Action? PresenceReceived; - void FetchInitialMessages(); + /// + /// Fired when a has been parted. + /// + event Action? ChannelParted; + + /// + /// Fired when new s have arrived from the server. + /// + event Action>? NewMessages; + + /// + /// Requests presence information from the server. + /// + void RequestPresence(); + + /// + /// Fired when the initial user presence information has been received. + /// + event Action? PresenceReceived; } } diff --git a/osu.Game/Online/Chat/WebSocketChatClient.cs b/osu.Game/Online/Chat/WebSocketChatClient.cs index fb67c205dc..05d3b7b3ce 100644 --- a/osu.Game/Online/Chat/WebSocketChatClient.cs +++ b/osu.Game/Online/Chat/WebSocketChatClient.cs @@ -40,14 +40,10 @@ namespace osu.Game.Online.Chat client.MessageReceived += onMessageReceived; client.SendAsync(new StartChatRequest()).WaitSafely(); + RequestPresence(); } - public void FetchInitialMessages() - { - api.Queue(createInitialFetchRequest()); - } - - private APIRequest createInitialFetchRequest() + public void RequestPresence() { var fetchReq = new GetUpdatesRequest(0); @@ -64,7 +60,7 @@ namespace osu.Game.Online.Chat PresenceReceived?.Invoke(); }; - return fetchReq; + api.Queue(fetchReq); } private void onMessageReceived(SocketMessage message) diff --git a/osu.Game/Online/Notifications/WebSocket/INotificationsClient.cs b/osu.Game/Online/Notifications/WebSocket/INotificationsClient.cs index f687752047..9a222d0fdd 100644 --- a/osu.Game/Online/Notifications/WebSocket/INotificationsClient.cs +++ b/osu.Game/Online/Notifications/WebSocket/INotificationsClient.cs @@ -8,10 +8,24 @@ using osu.Framework.Bindables; namespace osu.Game.Online.Notifications.WebSocket { + /// + /// A client for asynchronous notifications sent by osu-web. + /// public interface INotificationsClient { + /// + /// Whether this is currently connected to a server. + /// IBindable IsConnected { get; } + + /// + /// Invoked when a new arrives for this client. + /// event Action? MessageReceived; + + /// + /// Sends a to the notification server. + /// Task SendAsync(SocketMessage message, CancellationToken? cancellationToken = default); } } diff --git a/osu.Game/Tests/PollingChatClientConnector.cs b/osu.Game/Tests/PollingChatClientConnector.cs index 3e96a8cde7..1cab24dae6 100644 --- a/osu.Game/Tests/PollingChatClientConnector.cs +++ b/osu.Game/Tests/PollingChatClientConnector.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests public event Action>? NewMessages; public event Action? PresenceReceived; - public void FetchInitialMessages() + public void RequestPresence() { // don't really need to do anything special if we poll every second anyway. } From 14067c2e573e00719b849bd37c01e37f96dbc712 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jan 2024 00:39:29 +0900 Subject: [PATCH 103/915] Remove unused using statements --- osu.Game/Graphics/Backgrounds/TrianglesV2.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs index bcb73f71cc..4143a6d76d 100644 --- a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs +++ b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Shaders; From 93bd3ce5ae73eb6f00649e09ace1acd2224ecc95 Mon Sep 17 00:00:00 2001 From: Chandler Stowell Date: Thu, 25 Jan 2024 11:25:41 -0500 Subject: [PATCH 104/915] update `DrawableHitCircle.ApplyResult` to pass `this` to its callback --- .../DrawableEmptyFreeformHitObject.cs | 2 +- .../Drawables/DrawablePippidonHitObject.cs | 6 ++--- .../DrawableEmptyScrollingHitObject.cs | 2 +- .../Drawables/DrawablePippidonHitObject.cs | 5 ++-- .../Drawables/DrawableCatchHitObject.cs | 7 +++--- .../Objects/Drawables/DrawableHoldNote.cs | 2 +- .../Objects/Drawables/DrawableHoldNoteBody.cs | 9 ++++++- .../Drawables/DrawableManiaHitObject.cs | 2 +- .../Objects/Drawables/DrawableNote.cs | 16 +++++++++---- .../TestSceneHitCircle.cs | 2 +- .../TestSceneHitCircleLateFade.cs | 2 +- .../Objects/Drawables/DrawableHitCircle.cs | 19 ++++++++------- .../Objects/Drawables/DrawableOsuHitObject.cs | 4 ++-- .../Objects/Drawables/DrawableSlider.cs | 14 +++++------ .../Objects/Drawables/DrawableSpinner.cs | 5 ++-- .../Objects/Drawables/DrawableSpinnerTick.cs | 12 +++++++++- .../Objects/Drawables/DrawableDrumRoll.cs | 8 +++---- .../Objects/Drawables/DrawableDrumRollTick.cs | 13 +++++----- .../Objects/Drawables/DrawableFlyingHit.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 24 ++++++++++++------- .../Drawables/DrawableStrongNestedHit.cs | 2 +- .../Objects/Drawables/DrawableSwell.cs | 16 +++++++------ .../Objects/Drawables/DrawableSwellTick.cs | 10 +++++--- .../Gameplay/TestSceneDrawableHitObject.cs | 2 +- .../Gameplay/TestScenePoolingRuleset.cs | 8 +++---- .../Objects/Drawables/DrawableHitObject.cs | 13 ++-------- 26 files changed, 120 insertions(+), 87 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs index e8f511bc4b..3ad8f06fb4 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Objects.Drawables { if (timeOffset >= 0) // todo: implement judgement logic - ApplyResult(static r => r.Type = HitResult.Perfect); + ApplyResult(static (r, hitObject) => r.Type = HitResult.Perfect); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index a8bb57ba18..925f2d04bf 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -50,10 +50,10 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables { if (timeOffset >= 0) { - ApplyResult(static (r, isHovered) => + ApplyResult(static (r, hitObject) => { - r.Type = isHovered ? HitResult.Perfect : HitResult.Miss; - }, IsHovered); + r.Type = hitObject.IsHovered ? HitResult.Perfect : HitResult.Miss; + }); } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs index 070a802aea..408bbea717 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.EmptyScrolling.Objects.Drawables { if (timeOffset >= 0) // todo: implement judgement logic - ApplyResult(static r => r.Type = HitResult.Perfect); + ApplyResult(static (r, hitObject) => r.Type = HitResult.Perfect); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index 9983ec20b0..2c9eac7f65 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -50,10 +50,11 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables { if (timeOffset >= 0) { - ApplyResult(static (r, pippidonHitObject) => + ApplyResult(static (r, hitObject) => { + var pippidonHitObject = (DrawablePippidonHitObject)hitObject; r.Type = pippidonHitObject.currentLane.Value == pippidonHitObject.HitObject.Lane ? HitResult.Perfect : HitResult.Miss; - }, this); + }); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 5a921f36f5..721c6aaa59 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -64,10 +64,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables if (timeOffset >= 0 && Result != null) { - ApplyResult(static (r, state) => + ApplyResult(static (r, hitObject) => { - r.Type = state.CheckPosition.Invoke(state.HitObject) ? r.Judgement.MaxResult : r.Judgement.MinResult; - }, this); + var catchHitObject = (DrawableCatchHitObject)hitObject; + r.Type = catchHitObject.CheckPosition!.Invoke(catchHitObject.HitObject) ? r.Judgement.MaxResult : r.Judgement.MinResult; + }); } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index e5056d5167..6c70ab3526 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -265,7 +265,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (Tail.AllJudged) { if (Tail.IsHit) - ApplyResult(static r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); else MissForcefully(); } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs index 317da0580c..731b1b6298 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs @@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public override bool DisplayResult => false; + private bool hit; + public DrawableHoldNoteBody() : this(null) { @@ -25,7 +27,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { if (AllJudged) return; - ApplyResult(static (r, hit) => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult, hit); + this.hit = hit; + ApplyResult(static (r, hitObject) => + { + var holdNoteBody = (DrawableHoldNoteBody)hitObject; + r.Type = holdNoteBody.hit ? r.Judgement.MaxResult : r.Judgement.MinResult; + }); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index dea0817869..2d10fa27cd 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Causes this to get missed, disregarding all conditions in implementations of . /// - public virtual void MissForcefully() => ApplyResult(static r => r.Type = r.Judgement.MinResult); + public virtual void MissForcefully() => ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); } public abstract partial class DrawableManiaHitObject : DrawableManiaHitObject diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 985007f905..a70253798a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -38,6 +38,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private Drawable headPiece; + private HitResult hitResult; + public DrawableNote() : this(null) { @@ -89,18 +91,22 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); return; } - var result = HitObject.HitWindows.ResultFor(timeOffset); - if (result == HitResult.None) + hitResult = HitObject.HitWindows.ResultFor(timeOffset); + if (hitResult == HitResult.None) return; - result = GetCappedResult(result); + hitResult = GetCappedResult(hitResult); - ApplyResult(static (r, result) => r.Type = result, result); + ApplyResult(static (r, hitObject) => + { + var note = (DrawableNote)hitObject; + r.Type = note.hitResult; + }); } /// diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index 30b0451a3b..8d4145f2c1 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && timeOffset > hitOffset && CheckHittable?.Invoke(this, Time.Current, HitResult.Great) == ClickAction.Hit) { // force success - ApplyResult(r => r.Type = HitResult.Great); + ApplyResult(static (r, _) => r.Type = HitResult.Great); } else base.CheckForResult(userTriggered, timeOffset); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs index 7824f26251..2d1e9c1270 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs @@ -208,7 +208,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (shouldHit && !userTriggered && timeOffset >= 0) { // force success - ApplyResult(r => r.Type = HitResult.Great); + ApplyResult(static (r, _) => r.Type = HitResult.Great); } else base.CheckForResult(userTriggered, timeOffset); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 8284229d82..ce5422b180 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -44,6 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Container scaleContainer; private InputManager inputManager; + private HitResult hitResult; public DrawableHitCircle() : this(null) @@ -155,34 +156,34 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); return; } - var result = ResultFor(timeOffset); - var clickAction = CheckHittable?.Invoke(this, Time.Current, result); + hitResult = ResultFor(timeOffset); + var clickAction = CheckHittable?.Invoke(this, Time.Current, hitResult); if (clickAction == ClickAction.Shake) Shake(); - if (result == HitResult.None || clickAction != ClickAction.Hit) + if (hitResult == HitResult.None || clickAction != ClickAction.Hit) return; - ApplyResult(static (r, state) => + ApplyResult(static (r, hitObject) => { - var (hitCircle, hitResult) = state; + var hitCircle = (DrawableHitCircle)hitObject; var circleResult = (OsuHitCircleJudgementResult)r; // Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss. - if (hitResult.IsHit()) + if (hitCircle.hitResult.IsHit()) { var localMousePosition = hitCircle.ToLocalSpace(hitCircle.inputManager.CurrentState.Mouse.Position); circleResult.CursorPositionAtHit = hitCircle.HitObject.StackedPosition + (localMousePosition - hitCircle.DrawSize / 2); } - circleResult.Type = hitResult; - }, (this, result)); + circleResult.Type = hitCircle.hitResult; + }); } /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index cc06d009c9..6de60a9d51 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -100,12 +100,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// /// Causes this to get hit, disregarding all conditions in implementations of . /// - public void HitForcefully() => ApplyResult(static r => r.Type = r.Judgement.MaxResult); + public void HitForcefully() => ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); /// /// Causes this to get missed, disregarding all conditions in implementations of . /// - public void MissForcefully() => ApplyResult(static r => r.Type = r.Judgement.MinResult); + public void MissForcefully() => ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); private RectangleF parentScreenSpaceRectangle => ((DrawableOsuHitObject)ParentHitObject)?.parentScreenSpaceRectangle ?? Parent!.ScreenSpaceDrawQuad.AABBFloat; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 3c298cc6af..c0ff258352 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -292,10 +292,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (HitObject.ClassicSliderBehaviour) { // Classic behaviour means a slider is judged proportionally to the number of nested hitobjects hit. This is the classic osu!stable scoring. - ApplyResult(static (r, nestedHitObjects) => + ApplyResult(static (r, hitObject) => { - int totalTicks = nestedHitObjects.Count; - int hitTicks = nestedHitObjects.Count(h => h.IsHit); + int totalTicks = hitObject.NestedHitObjects.Count; + int hitTicks = hitObject.NestedHitObjects.Count(h => h.IsHit); if (hitTicks == totalTicks) r.Type = HitResult.Great; @@ -306,16 +306,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables double hitFraction = (double)hitTicks / totalTicks; r.Type = hitFraction >= 0.5 ? HitResult.Ok : HitResult.Meh; } - }, NestedHitObjects); + }); } else { // If only the nested hitobjects are judged, then the slider's own judgement is ignored for scoring purposes. // But the slider needs to still be judged with a reasonable hit/miss result for visual purposes (hit/miss transforms, etc). - ApplyResult(static (r, nestedHitObjects) => + ApplyResult(static (r, hitObject) => { - r.Type = nestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult; - }, NestedHitObjects); + r.Type = hitObject.NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult; + }); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d21d02c8ce..3679bc9775 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -258,8 +258,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables foreach (var tick in ticks.Where(t => !t.Result.HasResult)) tick.TriggerResult(false); - ApplyResult(static (r, spinner) => + ApplyResult(static (r, hitObject) => { + var spinner = (DrawableSpinner)hitObject; if (spinner.Progress >= 1) r.Type = HitResult.Great; else if (spinner.Progress > .9) @@ -268,7 +269,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables r.Type = HitResult.Meh; else if (spinner.Time.Current >= spinner.HitObject.EndTime) r.Type = r.Judgement.MinResult; - }, this); + }); } protected override void Update() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs index 1c3ff29118..628f07a281 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs @@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public override bool DisplayResult => false; + private bool hit; + public DrawableSpinnerTick() : this(null) { @@ -35,6 +37,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// Apply a judgement result. /// /// Whether this tick was reached. - internal void TriggerResult(bool hit) => ApplyResult(static (r, hit) => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult, hit); + internal void TriggerResult(bool hit) + { + this.hit = hit; + ApplyResult(static (r, hitObject) => + { + var spinnerTick = (DrawableSpinnerTick)hitObject; + r.Type = spinnerTick.hit ? r.Judgement.MaxResult : r.Judgement.MinResult; + }); + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index d3fe363857..2e40875af1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (timeOffset < 0) return; - ApplyResult(static r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); } protected override void UpdateHitStateTransforms(ArmedState state) @@ -192,10 +192,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!ParentHitObject.Judged) return; - ApplyResult(static (r, parentHitObject) => + ApplyResult(static (r, hitObject) => { - r.Type = parentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; - }, ParentHitObject); + r.Type = hitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; + }); } public override bool OnPressed(KeyBindingPressEvent e) => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index de9a3a31c5..aa678d7043 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (timeOffset > HitObject.HitWindow) - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); return; } if (Math.Abs(timeOffset) > HitObject.HitWindow) return; - ApplyResult(static r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); } public override void OnKilled() @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables base.OnKilled(); if (Time.Current > HitObject.GetEndTime() && !Judged) - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); } protected override void UpdateHitStateTransforms(ArmedState state) @@ -105,10 +105,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!ParentHitObject.Judged) return; - ApplyResult(static (r, parentHitObject) => + ApplyResult(static (r, hitObject) => { - r.Type = parentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; - }, ParentHitObject); + var nestedHit = (StrongNestedHit)hitObject; + r.Type = nestedHit.ParentHitObject!.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; + }); } public override bool OnPressed(KeyBindingPressEvent e) => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs index 1332b9e950..4349dff9f9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void LoadComplete() { base.LoadComplete(); - ApplyResult(static r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); } protected override void LoadSamples() diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index c3bd76bf81..cf8e4050ee 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -37,6 +37,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private double? lastPressHandleTime; + private HitResult hitResult; + private readonly Bindable type = new Bindable(); public DrawableHit() @@ -99,18 +101,24 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); return; } - var result = HitObject.HitWindows.ResultFor(timeOffset); - if (result == HitResult.None) + hitResult = HitObject.HitWindows.ResultFor(timeOffset); + if (hitResult == HitResult.None) return; if (!validActionPressed) - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); else - ApplyResult(static (r, result) => r.Type = result, result); + { + ApplyResult(static (r, hitObject) => + { + var drawableHit = (DrawableHit)hitObject; + r.Type = drawableHit.hitResult; + }); + } } public override bool OnPressed(KeyBindingPressEvent e) @@ -209,19 +217,19 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!ParentHitObject.Result.IsHit) { - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); return; } if (!userTriggered) { if (timeOffset - ParentHitObject.Result.TimeOffset > SECOND_HIT_WINDOW) - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); return; } if (Math.Abs(timeOffset - ParentHitObject.Result.TimeOffset) <= SECOND_HIT_WINDOW) - ApplyResult(static r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); } public override bool OnPressed(KeyBindingPressEvent e) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index 4080c14066..8f99538448 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // it can happen that the hit window of the nested strong hit extends past the lifetime of the parent object. // this is a safety to prevent such cases from causing the nested hit to never be judged and as such prevent gameplay from completing. if (!Judged && Time.Current > ParentHitObject?.HitObject.GetEndTime()) - ApplyResult(static r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index d48b78283b..0781ea5e2a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -41,6 +41,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private double? lastPressHandleTime; + private int numHits; + public override bool DisplayResult => false; public DrawableSwell() @@ -192,7 +194,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables nextTick?.TriggerResult(true); - int numHits = ticks.Count(r => r.IsHit); + numHits = ticks.Count(r => r.IsHit); float completion = (float)numHits / HitObject.RequiredHits; @@ -206,14 +208,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint); if (numHits == HitObject.RequiredHits) - ApplyResult(static r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); } else { if (timeOffset < 0) return; - int numHits = 0; + numHits = 0; foreach (var tick in ticks) { @@ -227,11 +229,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables tick.TriggerResult(false); } - ApplyResult(static (r, state) => + ApplyResult(static (r, hitObject) => { - var (numHits, hitObject) = state; - r.Type = numHits == hitObject.RequiredHits ? r.Judgement.MaxResult : r.Judgement.MinResult; - }, (numHits, HitObject)); + var swell = (DrawableSwell)hitObject; + r.Type = swell.numHits == swell.HitObject.RequiredHits ? r.Judgement.MaxResult : r.Judgement.MinResult; + }); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index ad1d09bc7b..557438e5e5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -15,6 +15,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public override bool DisplayResult => false; + private bool hit; + public DrawableSwellTick() : this(null) { @@ -29,11 +31,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public void TriggerResult(bool hit) { + this.hit = hit; HitObject.StartTime = Time.Current; - ApplyResult(static (r, hit) => + ApplyResult(static (r, hitObject) => { - r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult; - }, hit); + var swellTick = (DrawableSwellTick)hitObject; + r.Type = swellTick.hit ? r.Judgement.MaxResult : r.Judgement.MinResult; + }); } protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs index 10dbede2e0..bf1e52aab5 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs @@ -216,7 +216,7 @@ namespace osu.Game.Tests.Gameplay LifetimeStart = LIFETIME_ON_APPLY; } - public void MissForcefully() => ApplyResult(r => r.Type = HitResult.Miss); + public void MissForcefully() => ApplyResult(static (r, _) => r.Type = HitResult.Miss); protected override void UpdateHitStateTransforms(ArmedState state) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs index fea7456472..00bd58e303 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs @@ -431,7 +431,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void CheckForResult(bool userTriggered, double timeOffset) { if (timeOffset > HitObject.Duration) - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); } protected override void UpdateHitStateTransforms(ArmedState state) @@ -468,7 +468,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override void OnKilled() { base.OnKilled(); - ApplyResult(r => r.Type = r.Judgement.MinResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); } } @@ -547,7 +547,7 @@ namespace osu.Game.Tests.Visual.Gameplay { base.CheckForResult(userTriggered, timeOffset); if (timeOffset >= 0) - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); } } @@ -596,7 +596,7 @@ namespace osu.Game.Tests.Visual.Gameplay { base.CheckForResult(userTriggered, timeOffset); if (timeOffset >= 0) - ApplyResult(r => r.Type = r.Judgement.MaxResult); + ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 9acd7b3c0f..bffe174be1 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -687,14 +687,12 @@ namespace osu.Game.Rulesets.Objects.Drawables /// the of the . /// /// The callback that applies changes to the . - /// The state passed to the callback. - /// The type of the state information that is passed to the callback method. - protected void ApplyResult(Action application, TState state) + protected void ApplyResult(Action application) { if (Result.HasResult) throw new InvalidOperationException("Cannot apply result on a hitobject that already has a result."); - application?.Invoke(Result, state); + application?.Invoke(Result, this); if (!Result.HasResult) throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}."); @@ -716,13 +714,6 @@ namespace osu.Game.Rulesets.Objects.Drawables OnNewResult?.Invoke(this, Result); } - /// - /// Applies the of this , notifying responders such as - /// the of the . - /// - /// The callback that applies changes to the . - protected void ApplyResult(Action application) => ApplyResult((r, _) => application?.Invoke(r), null); - /// /// Processes this , checking if a scoring result has occurred. /// From 682dab5d8327e24b38914f0599d8822eddf05e93 Mon Sep 17 00:00:00 2001 From: Chandler Stowell Date: Thu, 25 Jan 2024 11:30:52 -0500 Subject: [PATCH 105/915] check if parent was hit in taiko's `DrawableDrumRoll.CheckForResult` --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 2e40875af1..f68198b967 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -194,7 +194,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(static (r, hitObject) => { - r.Type = hitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; + var drumRoll = (DrawableDrumRoll)hitObject; + r.Type = drumRoll.ParentHitObject!.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; }); } From 542f571deecbcc1a1a86cfd960687e5bf1dd546e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 26 Jan 2024 01:03:22 +0300 Subject: [PATCH 106/915] Remove LINQ cast in HUDOverlay --- osu.Game/Screens/Play/HUDOverlay.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index b5482f2a5b..4fc37b8bb5 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; -using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -259,14 +258,14 @@ namespace osu.Game.Screens.Play Vector2? highestBottomScreenSpace = null; - // LINQ cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes. - foreach (var element in mainComponents.Components.Cast()) - processDrawable(element); + // cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes. + foreach (var element in mainComponents.Components) + processDrawable(element as Drawable); if (rulesetComponents != null) { - foreach (var element in rulesetComponents.Components.Cast()) - processDrawable(element); + foreach (var element in rulesetComponents.Components) + processDrawable(element as Drawable); } if (lowestTopScreenSpaceRight.HasValue) From d2af05b30e93f729ba40326bdaf51867817f65f2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 26 Jan 2024 04:09:00 +0300 Subject: [PATCH 107/915] Remove useless bindable from ArgonSongProgressBar --- .../Screens/Play/HUD/ArgonSongProgressBar.cs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index beaee0e9ee..40311da646 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -52,23 +51,14 @@ namespace osu.Game.Screens.Play.HUD set => CurrentNumber.Value = value; } - public double TrackTime - { - private get => currentTrackTime.Value; - set => currentTrackTime.Value = value; - } + public double TrackTime { private get; set; } private double length => EndTime - StartTime; - private readonly BindableNumber currentTrackTime; - public bool Interactive { get; set; } public ArgonSongProgressBar(float barHeight) { - currentTrackTime = new BindableDouble(); - setupAlternateValue(); - StartTime = 0; EndTime = 1; @@ -107,13 +97,6 @@ namespace osu.Game.Screens.Play.HUD }; } - private void setupAlternateValue() - { - CurrentNumber.MaxValueChanged += v => currentTrackTime.MaxValue = v; - CurrentNumber.MinValueChanged += v => currentTrackTime.MinValue = v; - CurrentNumber.PrecisionChanged += v => currentTrackTime.Precision = v; - } - private float normalizedReference { get From 9b5b313193d61c603c6e42773a8fc6ea7e05fb94 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 26 Jan 2024 04:49:23 +0300 Subject: [PATCH 108/915] Move common logic into own SongProgressBar class --- .../Screens/Play/HUD/ArgonSongProgressBar.cs | 46 +----------- .../Play/HUD/DefaultSongProgressBar.cs | 64 ++--------------- osu.Game/Screens/Play/HUD/SongProgressBar.cs | 70 +++++++++++++++++++ 3 files changed, 76 insertions(+), 104 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/SongProgressBar.cs diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 40311da646..5fe3b97f15 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -7,19 +7,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; -using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Graphics; using osuTK; namespace osu.Game.Screens.Play.HUD { - public partial class ArgonSongProgressBar : SliderBar + public partial class ArgonSongProgressBar : SongProgressBar { - public Action? OnSeek { get; set; } - // Parent will handle restricting the area of valid input. public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; @@ -33,35 +29,12 @@ namespace osu.Game.Screens.Play.HUD private readonly ColourInfo mainColour; private ColourInfo catchUpColour; - public double StartTime - { - private get => CurrentNumber.MinValue; - set => CurrentNumber.MinValue = value; - } - - public double EndTime - { - private get => CurrentNumber.MaxValue; - set => CurrentNumber.MaxValue = value; - } - - public double CurrentTime - { - private get => CurrentNumber.Value; - set => CurrentNumber.Value = value; - } - public double TrackTime { private get; set; } private double length => EndTime - StartTime; - public bool Interactive { get; set; } - public ArgonSongProgressBar(float barHeight) { - StartTime = 0; - EndTime = 1; - RelativeSizeAxes = Axes.X; Height = this.barHeight = barHeight; @@ -136,11 +109,6 @@ namespace osu.Game.Screens.Play.HUD base.OnHoverLost(e); } - protected override void UpdateValue(float value) - { - // Handled in Update - } - protected override void Update() { base.Update(); @@ -167,18 +135,6 @@ namespace osu.Game.Screens.Play.HUD catchupBar.Alpha = Math.Max(1, catchupBar.Length); } - private ScheduledDelegate? scheduledSeek; - - protected override void OnUserChange(double value) - { - scheduledSeek?.Cancel(); - scheduledSeek = Schedule(() => - { - if (Interactive) - OnSeek?.Invoke(value); - }); - } - private partial class RoundedBar : Container { private readonly Box fill; diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs index 0e16067dcc..4079351baf 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs @@ -7,67 +7,23 @@ using osuTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Utils; -using osu.Framework.Threading; namespace osu.Game.Screens.Play.HUD { - public partial class DefaultSongProgressBar : SliderBar + public partial class DefaultSongProgressBar : SongProgressBar { - /// - /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. - /// - public Action? OnSeek { get; set; } - - /// - /// Whether the progress bar should allow interaction, ie. to perform seek operations. - /// - public bool Interactive - { - get => showHandle; - set - { - if (value == showHandle) - return; - - showHandle = value; - - handleBase.FadeTo(showHandle ? 1 : 0, 200); - } - } - public Color4 FillColour { set => fill.Colour = value; } - public double StartTime - { - set => CurrentNumber.MinValue = value; - } - - public double EndTime - { - set => CurrentNumber.MaxValue = value; - } - - public double CurrentTime - { - set => CurrentNumber.Value = value; - } - private readonly Box fill; private readonly Container handleBase; private readonly Container handleContainer; - private bool showHandle; - public DefaultSongProgressBar(float barHeight, float handleBarHeight, Vector2 handleSize) { - CurrentNumber.MinValue = 0; - CurrentNumber.MaxValue = 1; - RelativeSizeAxes = Axes.X; Height = barHeight + handleBarHeight + handleSize.Y; @@ -130,9 +86,11 @@ namespace osu.Game.Screens.Play.HUD }; } - protected override void UpdateValue(float value) + protected override void LoadComplete() { - // handled in update + base.LoadComplete(); + + InteractiveBindable.BindValueChanged(i => handleBase.FadeTo(i.NewValue ? 1 : 0, 200), true); } protected override void Update() @@ -145,17 +103,5 @@ namespace osu.Game.Screens.Play.HUD fill.Width = newX; handleBase.X = newX; } - - private ScheduledDelegate? scheduledSeek; - - protected override void OnUserChange(double value) - { - scheduledSeek?.Cancel(); - scheduledSeek = Schedule(() => - { - if (showHandle) - OnSeek?.Invoke(value); - }); - } } } diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/SongProgressBar.cs new file mode 100644 index 0000000000..db9c8901b4 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/SongProgressBar.cs @@ -0,0 +1,70 @@ +// 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 osu.Framework.Bindables; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Threading; + +namespace osu.Game.Screens.Play.HUD +{ + public abstract partial class SongProgressBar : SliderBar + { + /// + /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. + /// + public Action? OnSeek { get; set; } + + /// + /// Whether the progress bar should allow interaction, ie. to perform seek operations. + /// + public bool Interactive + { + get => InteractiveBindable.Value; + set => InteractiveBindable.Value = value; + } + + protected readonly BindableBool InteractiveBindable = new BindableBool(); + + public double StartTime + { + get => CurrentNumber.MinValue; + set => CurrentNumber.MinValue = value; + } + + public double EndTime + { + get => CurrentNumber.MaxValue; + set => CurrentNumber.MaxValue = value; + } + + public double CurrentTime + { + get => CurrentNumber.Value; + set => CurrentNumber.Value = value; + } + + protected SongProgressBar() + { + StartTime = 0; + EndTime = 1; + } + + protected override void UpdateValue(float value) + { + // handled in update + } + + private ScheduledDelegate? scheduledSeek; + + protected override void OnUserChange(double value) + { + scheduledSeek?.Cancel(); + scheduledSeek = Schedule(() => + { + if (Interactive) + OnSeek?.Invoke(value); + }); + } + } +} From 84a0291c85550ab70db9a9aea0a69b9e8edfd428 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jan 2024 12:32:18 +0900 Subject: [PATCH 109/915] Update icon in nuspec file --- osu.Desktop/osu.nuspec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec index 3dadc4e002..3b7d6cbe79 100644 --- a/osu.Desktop/osu.nuspec +++ b/osu.Desktop/osu.nuspec @@ -7,7 +7,8 @@ ppy Pty Ltd Dean Herbert https://osu.ppy.sh/ - https://puu.sh/tYyXZ/9a01a5d1b0.ico + https://github.com/ppy/osu/blob/master/assets/lazer-nuget.png?raw=true + icon.png false A free-to-win rhythm game. Rhythm is just a *click* away! testing From 6e3eb674f61d6865d5c39cc25a4241921796f989 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jan 2024 12:55:36 +0900 Subject: [PATCH 110/915] Move cast to local function and make direct cast --- osu.Game/Screens/Play/HUDOverlay.cs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 4fc37b8bb5..32ebb82f15 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -258,14 +258,13 @@ namespace osu.Game.Screens.Play Vector2? highestBottomScreenSpace = null; - // cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes. foreach (var element in mainComponents.Components) - processDrawable(element as Drawable); + processDrawable(element); if (rulesetComponents != null) { foreach (var element in rulesetComponents.Components) - processDrawable(element as Drawable); + processDrawable(element); } if (lowestTopScreenSpaceRight.HasValue) @@ -283,33 +282,36 @@ namespace osu.Game.Screens.Play else bottomRightElements.Y = 0; - void processDrawable(Drawable element) + void processDrawable(ISerialisableDrawable element) { + // Cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes. + Drawable drawable = (Drawable)element; + // for now align some top components with the bottom-edge of the lowest top-anchored hud element. - if (element.Anchor.HasFlagFast(Anchor.y0)) + if (drawable.Anchor.HasFlagFast(Anchor.y0)) { // health bars are excluded for the sake of hacky legacy skins which extend the health bar to take up the full screen area. if (element is LegacyHealthDisplay) return; - float bottom = element.ScreenSpaceDrawQuad.BottomRight.Y; + float bottom = drawable.ScreenSpaceDrawQuad.BottomRight.Y; - bool isRelativeX = element.RelativeSizeAxes == Axes.X; + bool isRelativeX = drawable.RelativeSizeAxes == Axes.X; - if (element.Anchor.HasFlagFast(Anchor.TopRight) || isRelativeX) + if (drawable.Anchor.HasFlagFast(Anchor.TopRight) || isRelativeX) { if (lowestTopScreenSpaceRight == null || bottom > lowestTopScreenSpaceRight.Value) lowestTopScreenSpaceRight = bottom; } - if (element.Anchor.HasFlagFast(Anchor.TopLeft) || isRelativeX) + if (drawable.Anchor.HasFlagFast(Anchor.TopLeft) || isRelativeX) { if (lowestTopScreenSpaceLeft == null || bottom > lowestTopScreenSpaceLeft.Value) lowestTopScreenSpaceLeft = bottom; } } // and align bottom-right components with the top-edge of the highest bottom-anchored hud element. - else if (element.Anchor.HasFlagFast(Anchor.BottomRight) || (element.Anchor.HasFlagFast(Anchor.y2) && element.RelativeSizeAxes == Axes.X)) + else if (drawable.Anchor.HasFlagFast(Anchor.BottomRight) || (drawable.Anchor.HasFlagFast(Anchor.y2) && drawable.RelativeSizeAxes == Axes.X)) { var topLeft = element.ScreenSpaceDrawQuad.TopLeft; if (highestBottomScreenSpace == null || topLeft.Y < highestBottomScreenSpace.Value.Y) From 347e88f59772f0dc0045f46dc1c8e060ed8b51b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jan 2024 16:21:48 +0900 Subject: [PATCH 111/915] Add note about using `static` callback --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index bffe174be1..e30ce13f08 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -686,7 +686,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Applies the of this , notifying responders such as /// the of the . /// - /// The callback that applies changes to the . + /// The callback that applies changes to the . Using a `static` delegate is recommended to avoid allocation overhead. protected void ApplyResult(Action application) { if (Result.HasResult) From 6cfd2813ede27126f002ace78e3def0e5f7b03f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jan 2024 16:52:03 +0900 Subject: [PATCH 112/915] Fix incorrect cast --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index f68198b967..e15298f3ca 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -194,7 +194,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(static (r, hitObject) => { - var drumRoll = (DrawableDrumRoll)hitObject; + var drumRoll = (StrongNestedHit)hitObject; r.Type = drumRoll.ParentHitObject!.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult; }); } From b6fa50c312c6b47b37cc6037688c303e5c039b24 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jan 2024 17:48:36 +0900 Subject: [PATCH 113/915] Reduce allocation overheads in `SliderInputManager` --- .../Objects/Drawables/SliderInputManager.cs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs index 95896c7c91..148cf79337 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs @@ -215,8 +215,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (headCircleHitAction == null) timeToAcceptAnyKeyAfter = null; - var actions = slider.OsuActionInputManager?.PressedActions; - // if the head circle was hit with a specific key, tracking should only occur while that key is pressed. if (headCircleHitAction != null && timeToAcceptAnyKeyAfter == null) { @@ -227,6 +225,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables timeToAcceptAnyKeyAfter = Time.Current; } + if (slider.OsuActionInputManager == null) + return; + + lastPressedActions.Clear(); + bool validTrackingAction = false; + + foreach (OsuAction action in slider.OsuActionInputManager.PressedActions) + { + if (isValidTrackingAction(action)) + validTrackingAction = true; + + lastPressedActions.Add(action); + } + Tracking = // even in an edge case where current time has exceeded the slider's time, we may not have finished judging. // we don't want to potentially update from Tracking=true to Tracking=false at this point. @@ -234,11 +246,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // in valid position range && isValidTrackingPosition // valid action - && (actions?.Any(isValidTrackingAction) ?? false); - - lastPressedActions.Clear(); - if (actions != null) - lastPressedActions.AddRange(actions); + && validTrackingAction; } private OsuAction? getInitialHitAction() => slider.HeadCircle?.HitAction; From 68d5e8affc69c6d219c85e220913a27749551035 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 Jan 2024 18:50:40 +0900 Subject: [PATCH 114/915] Use a better constant for playfield positioning --- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 9a5fc90a05..c10e505f50 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -28,6 +28,8 @@ namespace osu.Game.Rulesets.Taiko.UI base.Update(); const float base_relative_height = TaikoPlayfield.BASE_HEIGHT / 768; + // Matches stable, see https://github.com/peppy/osu-stable-reference/blob/7519cafd1823f1879c0d9c991ba0e5c7fd3bfa02/osu!/GameModes/Play/Rulesets/Taiko/RulesetTaiko.cs#L514 + const float base_position = 135f / 480f; float relativeHeight = base_relative_height; @@ -49,14 +51,7 @@ namespace osu.Game.Rulesets.Taiko.UI // Limit the maximum relative height of the playfield to one-third of available area to avoid it masking out on extreme resolutions. relativeHeight = Math.Min(relativeHeight, 1f / 3f); - // Position the taiko playfield exactly one playfield from the top of the screen, if there is enough space for it. - // Note that the relative height cannot exceed one-third - if that limit is hit, the playfield will be exactly centered. - float playfieldPosition = relativeHeight; - - // arbitrary offset to make playfield position match stable. - playfieldPosition += 0.022f; - - Y = playfieldPosition; + Y = base_position; Scale = new Vector2(Math.Max((Parent!.ChildSize.Y / 768f) * (relativeHeight / base_relative_height), 1f)); Width = 1 / Scale.X; From 04cae874b0e0a6f98ba40aa048c6b6f08120c667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 26 Jan 2024 10:51:52 +0100 Subject: [PATCH 115/915] Handle forced logouts due to password change too --- osu.Game/Online/API/APIAccess.cs | 45 ++++++++++++++----------- osu.Game/Online/OnlineStatusNotifier.cs | 22 ++++++++++++ 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index ebebdbbfc2..8b369d0f3f 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -86,7 +86,7 @@ namespace osu.Game.Online.API APIEndpointUrl = endpointConfiguration.APIEndpointUrl; WebsiteRootUrl = endpointConfiguration.WebsiteRootUrl; - NotificationsClient = new WebSocketNotificationsClientConnector(this); + NotificationsClient = setUpNotificationsClient(); authentication = new OAuth(endpointConfiguration.APIClientID, endpointConfiguration.APIClientSecret, APIEndpointUrl); log = Logger.GetLogger(LoggingTarget.Network); @@ -119,6 +119,30 @@ namespace osu.Game.Online.API thread.Start(); } + private WebSocketNotificationsClientConnector setUpNotificationsClient() + { + var connector = new WebSocketNotificationsClientConnector(this); + + connector.MessageReceived += msg => + { + switch (msg.Event) + { + case @"verified": + if (state.Value == APIState.RequiresSecondFactorAuth) + state.Value = APIState.Online; + break; + + case @"logout": + if (state.Value == APIState.Online) + Logout(); + + break; + } + }; + + return connector; + } + private void onTokenChanged(ValueChangedEvent e) => config.SetValue(OsuSetting.Token, config.Get(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty); internal new void Schedule(Action action) => base.Schedule(action); @@ -270,10 +294,7 @@ namespace osu.Game.Online.API setLocalUser(me); - if (me.SessionVerified) - state.Value = APIState.Online; - else - setUpSecondFactorAuthentication(); + state.Value = me.SessionVerified ? APIState.Online : APIState.RequiresSecondFactorAuth; failureCount = 0; }; @@ -356,20 +377,6 @@ namespace osu.Game.Online.API this.password = password; } - private void setUpSecondFactorAuthentication() - { - if (state.Value == APIState.RequiresSecondFactorAuth) - return; - - state.Value = APIState.RequiresSecondFactorAuth; - - NotificationsClient.MessageReceived += msg => - { - if (msg.Event == @"verified") - state.Value = APIState.Online; - }; - } - public void AuthenticateSecondFactor(string code) { Debug.Assert(State.Value == APIState.RequiresSecondFactorAuth); diff --git a/osu.Game/Online/OnlineStatusNotifier.cs b/osu.Game/Online/OnlineStatusNotifier.cs index c36e4ab894..dda430ce6f 100644 --- a/osu.Game/Online/OnlineStatusNotifier.cs +++ b/osu.Game/Online/OnlineStatusNotifier.cs @@ -11,6 +11,7 @@ using osu.Framework.Screens; using osu.Game.Online.API; using osu.Game.Online.Metadata; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Notifications.WebSocket; using osu.Game.Online.Spectator; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -25,6 +26,8 @@ namespace osu.Game.Online { private readonly Func getCurrentScreen; + private INotificationsClient notificationsClient = null!; + [Resolved] private MultiplayerClient multiplayerClient { get; set; } = null!; @@ -55,9 +58,11 @@ namespace osu.Game.Online private void load(IAPIProvider api) { apiState = api.State.GetBoundCopy(); + notificationsClient = api.NotificationsClient; multiplayerState = multiplayerClient.IsConnected.GetBoundCopy(); spectatorState = spectatorClient.IsConnected.GetBoundCopy(); + notificationsClient.MessageReceived += notifyAboutForcedDisconnection; multiplayerClient.Disconnecting += notifyAboutForcedDisconnection; spectatorClient.Disconnecting += notifyAboutForcedDisconnection; metadataClient.Disconnecting += notifyAboutForcedDisconnection; @@ -127,10 +132,27 @@ namespace osu.Game.Online }); } + private void notifyAboutForcedDisconnection(SocketMessage obj) + { + if (obj.Event != @"logout") return; + + if (userNotified) return; + + userNotified = true; + notificationOverlay?.Post(new SimpleErrorNotification + { + Icon = FontAwesome.Solid.ExclamationCircle, + Text = "You have been logged out due to a change to your account. Please log in again." + }); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); + if (notificationsClient.IsNotNull()) + notificationsClient.MessageReceived += notifyAboutForcedDisconnection; + if (spectatorClient.IsNotNull()) spectatorClient.Disconnecting -= notifyAboutForcedDisconnection; From a2e69d37e8444a75763e9e974bf32e4eb2ce1dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 26 Jan 2024 11:17:32 +0100 Subject: [PATCH 116/915] Add basic testing of failure flow --- .../Visual/Menus/TestSceneLoginOverlay.cs | 54 +++++++++++++++++++ osu.Game/Online/API/DummyAPIAccess.cs | 22 +++++++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index 0c0edca995..5fc075ed99 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using System.Net; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -9,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Overlays; using osu.Game.Overlays.Login; using osu.Game.Users.Drawables; @@ -19,6 +21,8 @@ namespace osu.Game.Tests.Visual.Menus [TestFixture] public partial class TestSceneLoginOverlay : OsuManualInputManagerTestScene { + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + private LoginOverlay loginOverlay = null!; [BackgroundDependencyLoader] @@ -49,13 +53,63 @@ namespace osu.Game.Tests.Visual.Menus assertAPIState(APIState.RequiresSecondFactorAuth); AddUntilStep("wait for second factor auth form", () => loginOverlay.ChildrenOfType().SingleOrDefault(), () => Is.Not.Null); + AddStep("set up verification handling", () => dummyAPI.HandleRequest = req => + { + switch (req) + { + case VerifySessionRequest verifySessionRequest: + if (verifySessionRequest.VerificationKey == "88800088") + verifySessionRequest.TriggerSuccess(); + else + verifySessionRequest.TriggerFailure(new WebException()); + return true; + } + + return false; + }); AddStep("enter code", () => loginOverlay.ChildrenOfType().First().Text = "88800088"); assertAPIState(APIState.Online); + AddStep("clear handler", () => dummyAPI.HandleRequest = null); } private void assertAPIState(APIState expected) => AddUntilStep($"login state is {expected}", () => API.State.Value, () => Is.EqualTo(expected)); + [Test] + public void TestVerificationFailure() + { + bool verificationHandled = false; + AddStep("reset flag", () => verificationHandled = false); + AddStep("logout", () => API.Logout()); + assertAPIState(APIState.Offline); + + AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); + AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + + assertAPIState(APIState.RequiresSecondFactorAuth); + AddUntilStep("wait for second factor auth form", () => loginOverlay.ChildrenOfType().SingleOrDefault(), () => Is.Not.Null); + + AddStep("set up verification handling", () => dummyAPI.HandleRequest = req => + { + switch (req) + { + case VerifySessionRequest verifySessionRequest: + if (verifySessionRequest.VerificationKey == "88800088") + verifySessionRequest.TriggerSuccess(); + else + verifySessionRequest.TriggerFailure(new WebException()); + verificationHandled = true; + return true; + } + + return false; + }); + AddStep("enter code", () => loginOverlay.ChildrenOfType().First().Text = "abcdefgh"); + AddUntilStep("wait for verification handled", () => verificationHandled); + assertAPIState(APIState.RequiresSecondFactorAuth); + AddStep("clear handler", () => dummyAPI.HandleRequest = null); + } + [Test] public void TestLoginFailure() { diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 08b1733aed..435c100c9a 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Localisation; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osu.Game.Online.Notifications.WebSocket; @@ -133,7 +134,26 @@ namespace osu.Game.Online.API } } - public void AuthenticateSecondFactor(string code) => onSuccessfulLogin(); + public void AuthenticateSecondFactor(string code) + { + var request = new VerifySessionRequest(code); + request.Failure += e => + { + state.Value = APIState.RequiresSecondFactorAuth; + LastLoginError = e; + }; + + state.Value = APIState.Connecting; + LastLoginError = null; + + // if no handler installed / handler can't handle verification, just assume that the server would verify for simplicity. + if (HandleRequest?.Invoke(request) != true) + onSuccessfulLogin(); + + // if a handler did handle this, make sure the verification actually passed. + if (request.CompletionState == APIRequestCompletionState.Completed) + onSuccessfulLogin(); + } private void onSuccessfulLogin() { From 243c2bc9b420b264e5a48b34fb4d7f3bd78d155d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 26 Jan 2024 11:21:23 +0100 Subject: [PATCH 117/915] Make sure the polling connector actually auto-starts itself --- osu.Game/Tests/PollingChatClientConnector.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Tests/PollingChatClientConnector.cs b/osu.Game/Tests/PollingChatClientConnector.cs index 1cab24dae6..f1b0d9dd7d 100644 --- a/osu.Game/Tests/PollingChatClientConnector.cs +++ b/osu.Game/Tests/PollingChatClientConnector.cs @@ -32,6 +32,7 @@ namespace osu.Game.Tests public PollingChatClientConnector(IAPIProvider api) : base(api) { + Start(); } protected sealed override Task BuildConnectionAsync(CancellationToken cancellationToken) From 9dc2a1d6f8892d7a548df60b1a21f2c6eb66dd7a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 27 Jan 2024 01:02:16 +0900 Subject: [PATCH 118/915] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1b1abe3971..f2623ac2a0 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From f54e1418ae8308202f963faabd5acf545ef7ba1c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 27 Jan 2024 01:25:48 +0900 Subject: [PATCH 119/915] Update to v4 --- assets/lazer-nuget.png | Bin 12770 -> 11930 bytes assets/lazer.png | Bin 326320 -> 328536 bytes osu.Desktop/lazer.ico | Bin 67263 -> 67391 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/lazer-nuget.png b/assets/lazer-nuget.png index 98a152a5a05b40b857780b2682be6a126151ba72..fed2f45149d74aee14421e74fa75dc117469d01a 100644 GIT binary patch literal 11930 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 b!4O3$rBAdmT`k@`=Kuv673nHTP~iUodp;H% literal 12770 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 diff --git a/assets/lazer.png b/assets/lazer.png index 484bc0a449bb2ee813fad5180a1f74d368d75e2e..2ee44225bf02b4bcd19b0f6590f0695027f3f1ee 100644 GIT binary patch literal 328536 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 z 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 literal 326320 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⩔30V^aN^)*_D&yQ2xLHAa-!JJ zxXYfCFS&k$%5Tl(DfSlX{oOxEK7an|9RL?%+lw%6y3_s}Uc7Ktxi9g9tRPa0q)a6b zD?N3N~S(&&a7 zb)IJChmh-Iu5<(ESxD$<#VG2$4T2tme2W!npZ3}3DUqGxEXKQ?1NM-4j=G|F!fX3k zD8~P2dIt*^DZu$!(`UjI1i#m%~OEk%*@P+{U=)3Y~}*t6}~<#kdmYs zfYUkfB43Yd>x6+$tNgvuJUS9``^hZMJgFb$=cxOaUSEYGZzARWuhsciv5p{Hcv)$CWNiiun?Y&A}+UW(FY*z^~|X2nEvbPes;`hx#v{2%H$hJf}+zAS(tfv z5e?asCY8{`>4P4r#f8(|K(Fc;3=DK^%XmtYd{L_Y?V>Qf>{QucY0E0hFvGJ<=KH3o zJlx)su~M0bvz+|iue^t&w~2CS&0aAYK$`ss%!{u3{7^E<*xMrdk<{WqYG>B4_hx0j zo#iXvS$kJMYE;rwo{HiMw$$~G=sd#9c^jw54LKCu-rFj*c$Z`)v$~mtA$m@W4RGN# zk!Aq5W4|8OJ!DnLL_Gqx)NRro81juUvC9^ zMe$;PF!N^g9|GE0fBlAqU&TvP+kF&&CfupNji?3N{BlLT$&}lRIgaw03tbj!m3yG9{p`X8U11N1KLJNX5g6-fBtWjkkZs){D(2;~&MJkIcy$S3 z5s|(!vNR`Wvh_O|~DDNqP z!4=>4FFG@7-~ZQ)r-Lq0;djL#bS+%{Xa1{beIay}6spQanOu3Sbdr%GZ=|i^VMcNS zCRU+lqFb#0z!ioTOK=gd9W=UC;0Kz@dzDFfG)8?QmRsTFa~ZB~Rs3)0c-WZtcLKBT zS=dne`Cxc{hvzDc8HF2t5mUO42U2+meQ3aoBYSY+oNi8!VB_CHzJX%8)fz?p@14I;S{M^o!{I3^-<1D=eD6X|jZUgZE}GY? z6S!2=&AJ`ba&e0c$_wEo#jl6v@UX**VgTzI06&*Ohhlbeq!>%N1&Q~p3~_DO`8V*C zYsp{6v;#Xg))cwM?)9sZ77|GE`>^G}*ks zqpJCn;hkpvp!R09Y6;}%c+I;NChfjP84tEma+?FtlyQ@bHv5&OXc^X>E1P`9y3C1$}QiG->;Y z%Kh+nW^Y@{L)m&OJ+8j<{l~I9i`RZ#1RPEI9ZehSV25j!@Yze4h>QKU6wzA&39_?> z(+Snx$d(O0))sC(Fr3vf_>ac!l4ZsX@lo+VFT=Fbc#C*L*S}~ zUkZs|#c!$=3Mf@SMV_ggK)jGSb1`U+Y3Eq%iBAqAwmX)i^)26P^Y%;c+v70vze&g) z|D9-c4Y8y0L=H(HlCUzDo;OYMtY{jQ-&RVSj2qCA^|b*6$JY&WFqL<=mYW-5T&>If z=P0M9C;hPl8bj#Pj8t`gH;lSRgKyyiiF297YJjsn|M)XaA<)x;4WO2SR-tq1{i6zI zSY8)(T%p1A2vuu7BcbKWM$6=srIdE8mrUx*lo=NJc; za)V$i(Q*v5(>sg(`#*)(T92#N?H>a*Cs@uiOg_|=p-L+hXpnTS`*))!XErpLAvb_^ zef(;g2tp=M=}8!pLw6oYPDziuft0rgqU+;DRB0?`?GdazCRzevBi%7fn+a|KXJjJ} zzA2=eR=SjE%=9{p!0)QbDV3ig%p&tOG~BqO*x*=Up)g+9X?j_DaLPL8eY7makNNT1 zR@(~cZec`6f+=gL+Z>~ygpR<6-a0>a+2(5)(*HVzHvj}x@Q??YAM9}=70KtwG2{v+_$McjP0I?tvK~a5-E- zk1f&IB?nbFv!RcU_3kb3mks|sqJxOcc4`r>LWIwSEf=?3$WOKH1dd3bC~BbAxiq8U z@W!$foh-H)*>RH~iB9s=?^4-}9z=3|p0R581KvsNrboaZQ}Vt`-T)Re!qempHA7Rv zq4)rnPXm5Ze~rIfC1hi%d%M!XwdFsFKb>6innpcc?E9ihkD8o=3 zKg)-1ugRwNAb~*+TH@aCUvh}nF@6D920dQUbBLDpyopIMt#Zcr90&22`X~RrnNBq`Eo7=6tEjG%&(8R&p+O9U4VpL*1Lm$2cpu9rwQ?JnlmwgVaEMI3L+xO zQc0JBhxpWJ=0>E+vJpH+)%oo9VLhY|QH6>+0Ovt8$}_>}Ar}LnWM%#Be75(~B)77# z()4w|A`&zm$w!Os01|ZA3o8MEEVPzQxBXZ#Ib)v_isxKm4ep!uW>Ok>NiCDMFnHgV z03Gd0S$fGw%)_s}P+zmp&2J@c{=I;WJG8eYr~h6kiOX7wQTUN&>)^s z7skuZlR;9)UOKJpwDZ{hLfuyt?c7!W!W;?o7EJl5`F?+U$=9qHC;YDPUUU_&piCIf zM(47kY}s>N^`*SJx%`qL^Sin3X5n{?ys-tsS~mQds+BZ?$uUQ%reTK1rjgE`)|&w; z@<*k)rDJuu4_?b<@Tbv+wVR|q;n4(9>j11KB7e*5-Y=JY>jzP)oxcOGS#LG$QN8T) z8HcxgL4|$_C$=%;(Oj>sB$f)B-cG-Qg!9$~TJqEN3Q2cKCw3A3gLz>9+9yO?*t%#- z(YOrU<&J`vI;vVa7&CPBeQ9`8N{J>Eh3z ze&n;C0a_KGIX!zytuk&RhNR9Lk8g(jw{3SBl)tI_dC5og_#kB z^%WR0GtIo;47-UKBVJbEoVIxr>vI?p4mbAvI{jf^Ab~Q3hc=pHSsZ&V3~IA}(g97* zqoNIfITi4SuI1O)3GW)bP`@5jPt9K3SQ_lTxX#Ah*`4PRB7tczk|cfK5;>ef?WTMo zS-r-0xVeOaOz_iUFo4LAYG4(C;!!EXgs}s$zIzWSYkXKl&2#D2CnZB#7idV<1Qp`L z$Uq9Tu!78hJB3tSI|Eu+`@D-d6&cS;ZdKZcZOIQWL5t5|G{YAsztnclBLEuGPi0Wq z1ur~Lbe)=K0AL-}dN6N#iWA~Ss zQo_Jj8t!`Gn`N%=KuYo{xAgi3Ubw5~wD)+9TcG+$H|_X+4i=_a;E%tWu-@Lu18;wg zBvvbb**cfF9J0^CV40n32(^_-#9p#^+8rUswvc9ob?!3xtB|@x|S6Hp4R}!PM z>|i#R)xUw0M3Ben@C5*6IP|~kN?vw63m;Lk#A(=Tk=QVn0Sie-U_S)hT`Pa9sn*~v z2<2QdTI(}P(={UP}8g?w1%T_^lbk}s|g`+Z>5i=~+=)e>ssUQS(0zvCY| zfR&+ZV{dh_ZbNubm5bIN`5jihX#2(_&gRF;p&>`9@b-U3r#~Yd?06EtkQ|?kl`!2= z5Tj^c42X{bt7zi%ZYEkkjCJZhw<%CXxT>C4lh_qaqkYN^Rgv#4=w+s}Ni>ybcdU{g zLO|aaP4=&I10rGF4$sO9%7=p`Jo-#s> z`-cOD6R{gf((<`w&L3|7_Lt^WHZcpFle z^65FBM`g|+mWyJbgPf(lZUWdZ3@q;4be$~-c&K8jTKkI~_@4icQFr9O=FzVAz44!X zH7N&|ll4hBNfa*amWm#6PR~rdtNu3zwmS4tGuv;LS3k;Bea{-9!Rf&j(wK+xlo}<_ zSvMAaVST_Ra+g_VoFYy{wqkZ^Io>$MA5nj%?Re4S{2qsg@q4p-1!H6Jho?V> zIWGJg1-4S|!}7pu6?o^TZQRNVT};qgqxK(Ju4oC&63RvG3=`#PX1-wKwB(q|R) zDT!#1uD1Q7INPS-d;R3gv%Rqn;`8UC<%!ztX;W{2%mH@bB|>!&<)YESVfGOGZcT9o z$<4o)NsB!BZmSqW^JpIm@_QQVAw_4(eV`q&97X+`)fqzlPo+p#1Fk4;uof}1to}D2 zJ!SyF$p9OvA82qCTo^8P+%h#&@#|0KW2W=o5u!8Dl2UrnK?Opbxa0QiPlg-&$lIp* zb7kGAb8SK%8GGWw8zj!m@k&Niq#6co7=~YBIuAGR3C~ z!>Ni`C}Ti_ITBmUzRa4|F`a$&4|9o}w!hn`tGBJ%fI;)bO8jP^kET$ZV6q_=D`>>u zmNdGJ4`;XOylLA~VaEODk}m6ew@Ns)=l$mcKZVKi=0LX1-_aMdsqBry;g!G%fu@?e zNhI6F{lKps856{I=vWac40+!)Gk!d9mBY0K;&WfSK`p|CHLgQ6yWm!PWt=aPOu@%B zXz;J`u&0*d@C(!6RJ$Y=BHbXYDXiQaqh>R{AeZ9PKQ0HaLrZ^*?Sqo&$k%^Jn!Q7^ zcPlkzb0Yl*%+S48i4Tq!+6Fz!W1^ z$M8Q>&lQ)%@xQU|D;|sfOG^$lm7Un1zb-8;rIS;n5Y-erlV5uzE_%`&!`G%C&)?Dy z3>#EAnDNdOWep_ zA;`Y~tUcjsSN08lx}t}#eoAIct1I!hEzb7+yTT(-tSDsU^Ek?cjaV)t#IfB9IUCb2 zmsi09n|H;OHD-kgz(py&9{=vM3EeLjUp`2Sg8DxW%}sulzrql9j4ttt`nZoB*U>qa zi-NN3KSG0%T*BNCwKf`@4_sSfy$S>2LSc8d8>s*6CElwKuM8$YMbE8U8AreDoUp)e~eC;Wh{(BmWP6NzLsKzS6 z27Zbc{N&6c4Ei0c6dsaqXw+k;y-l>c399it&Auap5c!PAHqvOuhzI% z5e6$Pd;=>PWw%bd3kN$9htQR?{LzyjWi54cx~f~^x=1`8R`jsb>aIPRo*i3rOtnj< z|LkkvRDewqq*6&8-S1$=s~j@XpwG2`daM(N&BNZTgd-PIYOuf$4_i!rrH2Ngo(z+P##t001)ayYb2A+ZY45}T`Z&5v13sva zyEDfuj|airO$Ik(?4)*|b|(TvTauzj!=$QBldiCl#PobKh8b8#v8X#{(WnXcnP-!~-~`PMU9UGceVE-Z>TsdR5tP(a z_;e;>*iI_V2j=}@EwCMhdC>5VzLh#3jkrCwFo<23sZ69A&D#;OELTW#{dz0@Sg-72(pl5StSnKKc`Wk_2m*j*{*G+X{56??sgy%$=9QrxDl7G-#(#e-d= z9yJR_paZ?W^c3)^ZB;MB&Im(P=9Ls_hvi(PB$CTv7f9j+C8>l_0Sh<;`0>`j0hsQ8 z%gNqSv*(!C)x0gO9a|$UboRSw&Jfmb@p!rf7nrI8)srJ_!{;Ke%HR#@xm(#HU-}+W z$C2I^U-SKIcY3C;+Dfm@Squx;ezJY*eV23G9Qabv<8=Zp0HGXiGiL? z2<7fLC~u7_*)2jaZA#q`$uSwCUZo4tE9jxQ}Uz*ZB|K$EV;}2nU2-+vTHuCk+ zxSMO84>xSj!UOIk00~mXla1NtN9t5L)dI@TU9Y3WHzB13Z`zdYw?^h>UW_qo<9kCpf;+|5^)&iah=<2CUfJB$n2%*J9mjV z{+w1<`pUwk-!5(g9Zb94UzNczSG>6PpM-IZONpeD=lWgu@8ub6Y4}qY=-Cp}PRsde z&uXbN>1tC~6)2=!vMFhCGnab6gpf0=g)*c4IrYQu`$`V#$CcQeNk<$_ zlDkMb&(i$U7|eXTd%aJ5rz;!us(<5-_xXH#Cl)Hd=l{JD_eIE3ebSuYYAsNA;pbBP zHCfc~wc>nk3%_RO=DS0^RbMoD#pREY#3|I%UOmAuLLG0Q^7(*#XBO!xVd*OnT&|}} z4XWl3nBD&}zx`$YFlQA*ZO_q>>DR=E#BNVb1=-|1krC#uE&k68BM#o9Xaq8Kv)MHN zNs@RATYcO@8$kasGB>w>eQvcPgi%`FvpZa=`D_2Smg+&WZZ3*6=PEEMb`$;l_U4~?wU05Q zz~4xZPp`!Ea{?%@rA39lG)*-&pPGK&F_34be4M;_o-{qKVIx^`3XS0pWaZvKiFY7m z=t*LS@#r>-QIZWS?kth#-2GMIlB&YThxZGz*{Y4JTBaP|ox7Cm)drkGDSq?+EXAuO ztL*MSh!R=vsu_DMIyzq#(+l31qz}e?7nH9X|8HGW1zVRdyMnRK;H?Z!Os~(&OgyXs z%a4fx$EF{9+gvlTEdm9rBSkZfuOUG#1zkyYm2LslskJQckjLu1sJ##Y5$x6OgOR@& zPVv#J_8XA;&PsScwDU{!W66HlP5m}+t0(nZoCMe9#4}dw(8H3owP--l@I1dfWsq~! zL}uqDT?{>zQ&HmEvQKyq8haUdOl;|YoR4UdDtkrP)2}6boCvy>_pjE5&)kru!4%X6 z=#B5gCY-)Wxij2G{>k;(NNUkDc#CbVSHF*uy?@!MHcq%+NK!zO^)Qk)LY_A~eTG@K zT|;EbZU{P<*Gv;14E-Ztyk-tgk9k5)R12PP>;+0USW0Fnxu0+`@eWXbv^uYc?`ZU* zmdL+5Dp#@nB1t#&iTUJ12kA@qL=HdMp*d`Jx_3NJz0iCLc{f!@^_{cqqKKVt9!IM+ z>gzOo5EF{D5_pvOm#B(ci~GFCl3i2c=Z-@&&8#{ga_D)s@BACm6Ude6B6CjSykhZ$(t2mlo(iOU znk0_bHa+%2TX(!FX;bfIZ7_`|^U<0&Wt?UDEB;>>(1I{F@#|S~ozk%>jDn*fU&F3M zDnrK5dt8j2?fbXG*;}4`!QZt4q$6n{u(TH+WW#$Ypm37lpbMjsB5M=ww!6yn320*5 z>gSekE)P}$Nf#0l{h_+?X#t&1fd$L!bJ7`BaoJiQqB7nr1iQGW>7uT*uf5$mNDgBN z$<#VM9ZA8P&5HUXS(e4Tw+B=RJsCNr)brgoid*u3(-YQP?9U^xuM61>(lBkZIk_I9p7$t`C0X9?e6D`rJ49aiHM>W9-W; zb~XOvgls9R_@1Xn#=j#N;@XUTY+ zhr~SmPT)@>AaEq_lE}fC*mkw8t@0<7(WV}b$VP2qNm2)NWLy<7E#qZ+^`k2rx!f+R zYPh$b@q-XcXBK;D?^zZ$b=-Is{qQP&zNvv`=RGJ4Jj6=~F8Jjd--6D(k{h?7v`*P{ zjjB&@eVw}BA2jk&WU4_-L~RUzrB+giyOnF8^!^9&>P?!OGur93GAHxH{5PLkd=uaf zj^SU&yBBBW?NHTq%1&ALHr3J!VG6BjpW1G}Zb3-2)9<3ngATDMxewdNDS^G4_8Qt* zl!h(v{*NSZG0xz2_`lRxZ8_wYIdbcM;r*H7XiEWK69c7*VMi6^QHW2s6&8#w#AuqzMc@08-LmSLPC@uoa>;~)pb1bh;; z7WR(Zz&SHcX`h&v?w7dz7svibM&YXR*D>c=nmW5+5yN}TqzNZi@pbpjes?VR^3$EX zh(C+%%O?8fH?8O!4-!=;W&x6GGEZ!CM&eT{YEa#bg&{md6m6Q^SXhQLHokuW?K-yO zvK<&~uqo3|R_j)fl2*@U4?TVN?*n-1>jSAtoM}Pg;)YuC;Vtof*bJoOqEsGLF3u!4 zw}oC5w~6kxx#(+r2q@JpU3Z<>f~BcZ-zS|#0r5xLI)*3|OBzz@5Xd5y9(t;6=bv#) z?2M^5EMR4cKO{0%;KS_$4*CKP_Mi0A-Rs&WoK@R^W? z3`Xbo2rtr4uFD^Oc$V>gl&Hk?G@D9Wm)V-tQyb6h7WZ zw0tDFUIJwmc@1%B|3Dbx&>uzEW@PauTxh4N;&zm~7nu2`RGRK-mVb>Y2&L2h^E>z2 z_8o2uAyv0+!wxadpx)$F6m**DEvt|>#&q5vrc2|+&`HU`8tahnJF=ZLANb&%(PU%l8S}}G?qQ0 zO`gtmcGSSFQkeF{r;rYw^lZRbdJ7%=l_$)*9cQgcMi`r_uhO#8Iem9{;=UicXjN4m zb^nCp^SX4H&~LNX@%L=(vR^jXpF7F#ZCH&JTw9?5d_dR-?D~>Lr_G?fXY#kV-e~?9 zqrc06+chc=$rWd6kXsJ@Rq~pX@tJYHrB`o+iwR{}GP|cD=W9c=Aodcg0|xtO28^v-+37hg2{`B74ob){efgJP{XjCb%Y3F91cXHhNvG2GWcKP!Q4A7xyP zMA$A3kc*0%j?t>A_ugx7(vGNt4rtRGJ7$gQR!U4N*t1i+FuYB9Rko5(MNY4kYy|_( zt)%Y%&DVY2r~TTL`7n_A@a-oOMR5@je+uQ2zJrp#irGQg(m9vzqK<%mYs3`v!^Rjj zV1y}+1>6JhuHf&c3QzMiSafUdPrfkME2v|KE4S7SAryEDh;5=b1R8N*{=ghIoYW(m zE~uBuZfJH`h|?r}VAaQbFQE`PzoDS814n-aAa{-)61>X1JM= zt&3+qjyeK=L*^l?&jbX&;@qK~kgJH2W?7j&GnOafCm=KAolEMl{+hw0LWb$PPML7= z4`4nB@pWoXwMqtN)~(E&1kHWZ%Vh>=l`@yipIoSUxJ7N_^%aM5W?Vqr8hst0Tsbj*Z?G>wQR~bns>=NC{aD#M{#U_{T zJ3Fzyl9LWcn7*L5Is7tgJZT&oh5;evpHk1CRP_03@0haq&Q#fWf?K6%brCD z3*Y`pj;jfdFf#`tHdGtR6{Mo*zf4bA@Nz^aYo_ z^Lp8{p}L18<9M;kQ^o0qanvQ+1eE%t+7D}-4C^;x)>XvU~q8F=E0+hz{BWR%(R{^ZcauFAMUdP?W5s%)yRtNf$w}nTc*F z^S8UG2rSh*lyn`-!UI++=e&RaSwQ*>stfbt4k`+eJ=%idByOn8Q9ucw>i`V!}V7W}949?Rs}YLSQhYKH(m|1l{CLyrZo zoU)4^N!-!PacvN*y@Nu}p*+AE73^91E&JQ#sF$(ef{^R)qFNZgCBLi2++0RT4Rj}3 zz=RpiakJlr?A6aun4%c9-m%lk?Um!^RXp~nKOEPi90P|G%~86i-Q~X2Gyd&jRhl%| znT(&m(fDuZ09Ey0@Cf_@I!A<`-mv%u3qChDm%{thr87dAe}!`?HKZWRFHw?6C(%2p zOJp$~zybE^z&1OX7sVsM0}?<_DoP_h{Oa)Eu?jssjRV_!ruW0Z=m72g<+OaLH86~p z_45^I7rTWyeIn<&t^$HF#h$h9#-DX-M&1Tv*vs^E^6c?K)E-Ezht@jipr}|)NvA_* zJMUT-cfNjOr>cBq&_vS_noBwK`}Zd^zokU==C5rEUDO$V!kOGmbNg|%f|)9h-Ptny zE^Gpe)~U{xYl4q>|4oh^N(|Z`47D4Qe6tb9JcrWfWL6*uTs|I0A!Pmh=g%bkmZJP) z%~DwBWWbuqIF~fJGUR*S?B%on13quv|1FNa{}-Z7V-5vbT#QDD`)68# zJ|rBPxVEic#$vP68`NQugJ-i*b`kywgeFGTt|=y^`(aOr6oRsmqketwPVF)w;+Q5l z|9Z>Rm1?+PHa~Fq>kPed|% zk}*VR_VaL@aEkjz?O0e`yE4bda3$9KxHJ$53JP~+jyUx(X4F_qIh zQno1DM{O#v{_T(Elyd}3(1%&EG4WF!`zRFRDcURiiKv@raBQH=2JTRn;O(c~_00%1 zwgdI?XZ?R>?@R=X0e6Exkproq_16$8y8l&{PlohfONr3iM5qe|xl7FmP5Ds!S$X>J zd9c~jlhnd%v~e5&-Wn;NcC|n8vXlNld4tr4$~W8!el9!50&|G>@Tupk6R%}rv&&UF z_B8%XTbO@+){|jFLtGcTIJL+H-&0*8Tpf?|EX!r`KH(S{mAHSBTA8|}*c`~tyrG}A zF_k~)g3U;NV|Sh&67w<0lkE+`vUnWPap7X}wj_E)jPOfj0?=fjc1To|}- zrKz>V%j3L-T%GY&dCb8z6RCeI7OtH)!s5yrGJB4M?K@M(Ls4VeLAidOoE3qYwjiq1 z#sMac_dmOs5MO(Ji7z0Ow>~I$d8-+fLVDP;Tgc^P?6rVRJHde-%`c9Lfh}STx1qvD zh@rKZ3{7yRoadhr*9VLLcJ-;66>Xe!lGQocYUss}-;FNtq#K&$%N~H%YXaag1Evlp z1+I&#+Kxn|u!iK5zA}2wD=oznznlk*26L~z^MxdX>oL(%{fV7n(CA(PQUf7KrhntT zzp;@=hbB5hb|PB)87uPX>Z#z6Q1pmnIz$9PHQ4A!)LoJVd5dn%(Nw~@Pz&v~GkEJa z?d6XP<&WC@sHr=s8tS`R|0&cB$eo2;WRe3@crcO#(2cOPxV$^C`nm)RzXx(RX1nAP zdO=9NRAtnY1@EYH@<;?NA2qOyGj6+jmpzbu^ULjhFeRZDhpWHVHn!-BXA-RLb3w2| zCbp4KLJDQBK%{5owc-gXv43vXN|#Kh*Dq1(ZSh2;=l68CgXJlnz)`DSeN=~@Fx2O}@CscjyJ zcllHYZM#80nqivabB`Q)ug4>IbleW)e%QCuO2?N^Nr_NL-WM}lO}}37yZVGG&Qz`p z?^nM2H*Y}9OO8pQ@|EC^!)9&QepRc-ifRpd2ZyR$vZR(YiXe!p%&1(=B0-L;DV3QwE`+=USRgZIs>?P1^g zVdd`~>WMACp+#X)^0eyjqwF3uF7HrwSU@!}4O+DZma*V{pemeIC*-zM+eYKX>^3iK zL+Y+1X=%ts{A*4ArMoCG>5FR1X9p4X*QPga9~1hDEqS4LVVwz3~&H0u^52{Jj z3dvO53qoE8IDI7(@mgW7y$Ir>NnML8P;f$4PJ0~^BnZd8x?4)0AO~Mu?CarDjqY00 z3;9W!+C#q9So5=!JXf|83|@((k*b^SFY3h*D_a`k^G$(*X{?s{xUt zQF+4)i18X)ADZJKRU0GaIk^b&Mj5DuhEp@90Fi5jeu^ZnX0V4hYASm=Bu9Tf;CW*# zOTi}yX&kh7&lat(WV9XWh?pe^%@Z$(`}Ucm%qrQk_v3fU+cFK=WXF@?SBjs$s=07J z^$~F-cAxPfH{QCbS+iGZaPO>=dv&({{4eG`XY|exxS>9lQOO^K!KZ05XRu51eCZgh1bZQSbapog+@~J4~8ZB~7O!W>* zgDQBE7eRkP0A(C8U?hliYC@Oh12kVqW5LwHN{Dk|X&Vp>Jr9TO8YG?atip9`u-s=o zoN0Of%h+r=%9j%?{Bsb9=E?_Wy$6r8KgCIyR@@=Wc#2-Dlm4i6T`t#^a{707nVPzD zD`uZPvNrAO;q2*Hj@duw5oIBi58rNko|}3oh6qv5A_n z8z9O>ydrH;=C2b)#!NiHwgn&D1BN@X-OiNhcXn2+Thc}(XzKFR^+hrE0|j9CK8lc^ zlM%?AtGakPoUlaDXH043(*{Q>I&B#POt>U)Le`3UJVu@CC4#7$=g7^{@y3lr(>Chb*XBL4GrD4F1Ug&=bFep;PI3cHkCSHPqPHZF|v?I))*&k1OSgun)82KOM%f0<` zBHW+7*2We4$E4tEPlvUdly|As%O%hpJE;#s_GqV_+w-D;n9d2Jh_Y^G>=Bg`Yf+$s zz^O1K-l$k(F67b=hnK|3LXSvGOf=P9_7VL&6wj>Ng*`MFtadedCYf^-e|9N~P<2u} z45c<*U=iR!r20ScV9lOKW6v!MQ_EZw)0>pvNq!vrkRgPtRf-E|xpD^8&vnoQTm-?s7j6K%fCahq z0!sD*q|}cG#D?a)!J`sB;d6M4s@9NPO1`;WIgA|s7h(fTTZy0*qXtqi=zjd_tfC2g z9yQuZpZ$9ewZv;VDSpt;`2>sdeHOvYpFgI@Ezqdx)c+D9<16dj z?)b^~i|3zBg?+t0_daTz{0iw5ZT4G2BV%v_9s2ll#O`X7!A3BpvWr3_rAde==mH{) z7v(E-@R(LGo>AY5#qUb!CwAH{S03QJJu+Ygg4jaE#YWfODx4mi z&9!qj0Mj@ksEiM~iYI(QgV(y8|EiaSk$|X-9z!h5LsL z%ff-yx9?*9&ab68x*fS!n-xOV)~DBGkM~1=l_}ooh>o+{2gb%55W^JNw}M)Pd99>p zh)G)O#!}-usN_!DP2IcEHzzn6>IZYyYy4=OJNouB5_$OrPd{Bl^HKOY_o%T4y}H*6 z51vmBg_-X(>a&ojP_0L)uks40k5WItS-A8-K@^k?eA6AIapnSBz@lrVxdeF~j-ejL zpyzyJ;t*&m6ga-E1{cL6q%#oSey1L}H=oIYX4NNVh4Ek4E45a^;+0kZJq71Siluf( zw0hU*dmg`!OKH2~r$_%P1a`+pdwr;lR%BNu;Xw~PX1>l3_64)Mk6 zz{toEo^Jn=Cr6$ou=bqlRjLIsBxu3e3xVw)=y{TTint2%u3R&8Rm z{+mhfTD&+L%GsyUNA1-sIGelz(eQd6QXT);&z^>p|aGz4Q5d7SfBi zWd(@`!{UF=`_fRjey4gyFl#{0iApRU;}v30;!lM>miAD zeu-A&{+OK7aN}t+_$BHuh5=r zieI+~APy0!V~Q(!MNP)00tFce|KcWBuluy~t%g+EdZ&yQ?&^o?521Oq`wjl_8tdN< zM@Cn`Xq_bOFN%W}Hx`%Ja4KcUK&d{r9!U zJ(4lY?OYGNp2Oa0O*8pVFXC2}*!W%ni+G%yZ9=$>{t@dGZ77n;%-|znVvG?}ci-PXc-+VJ z$NRir=e(ZloWqgQ9*gp+2(FHA&q}~on~aVnV6GXS%sHm7B~bor&Dh578P-uDA(_e@ z6^>56#WU_75n8Ojc{0akqQX2CIrz3B;Wz^mL(Kg$GGike+;+!*tz@XirUi4jD`1lt#|);KN_`Nx^Jy0dv|w_sR}$!8%a=(hg8!=NOl?1Kyr}S~+^hPcvXA zYG^kb?-ur3h;;oL+c{??ZmD%R--+QjT)msk4+$a?=_Qsygz37hanz5EEIv3P)eh2q6P@SG^GCMYWF4G+y ztn41QR$=pnrjZ>t8^8sM=Fh@s-$W7u%*sxAxCFgp^(%Y{`*TLI5y6b?o30<$#sM*b zg(g)i1qBaLM+yb$r0WL{#ICpa1Ud*+mz&}*jQ=QU>O85y$Db~)tZnnGni@!NTMdo< zHHjE%IUOkx`s?=P-ibId8IJWp!C81p!hYOS6v0uxX0G^lhgd0+L=DPGW4XA9Hv#g5 z+nIFO0I&=$eD3rOGiR1*c@zyUgJK#k)z6nfj-`lA$yG4;yduax(4`CtJLt89t1&1q z4+^v3QYQh9aKJC7odt;H#bMIefh*E{Y-6d-L|8|<*0#0b%cBEy1#KM$@r*9Ft*&}t z_liG)y7n1vYc9l=B?wGgFLpGQI3BX|r-u&@dc9xtUfeuy``tE``p)n3kjLwBONl&V zpS*1C{(Qob8TA}tzO?p(LsKa2Mf=$l-7m3gv-fg4e}--gw2_KG+Uy_gAl+kD?gjat zKoLaUq}^ecm-MeRQqBzeDr0}pqgUY!*T8DvTHY#rX1X3|i$i&R=POs8>fZYA#U|OW zX3GQC6m6;KH75XEK)lSCN5!n+y&yb~?@hc0Tj|y+@QlOHNSjZ$wm&KCc&kA_RtYlv zXPAYPpfpSU@pr3WDN~V`5d9tea*|=O@2AF1Ep(C~C~;FKoB5IOThuc$q^NgO2}IaC zpTS47)f>Nza;=G9`ZAcj72`VXBYPr21Cr02TUe+LggnDTb02l`mD$ajKE;@<{`jLk zv~6}Z(1z*nk3X-)b-b#`XH{XH*`qTvU;RP>Fu3s9x^nM3TZJ=cjSZdAxf5I({`_DO zrp_)gkK59jTM93xl$$uMr%k`vc6`_8C%N!s&U0w2%r9ouWrGoC6Sfe$ZSPqZEcYBK zI03iwlrBRGPQh8vJuvP&z|J-y@yV{$D(pF(e$t?O+d=h)A55hQNz~y=YxF+p-^GM+ zg_tyL6l!)M8Z3(cP7L|srb+QNMt8oSTxL@KJl(RG)gelfHe@U4&*_y4#(~?*)|13N z&%aFitP*s|5x70%xQkH$<`97CMOggjhbOVXRp6O}%{3+Qj4Mms3Y#E?MnoC8$~$;2u#GxhOz zhQZq$K(+!5S`;gfO5yaeFD=dxJ{hIj%v)cz$@S9d2-INoXCS1xZBHfv*`ic&6Cg?( zIQaVK?iVrgzUrM_QSYp9!J(IT)HT}#Vk;zMRx5gEX5)O@d9?-%B^dzC)T&j?c{_wJSFJmE8Hup(4`qg+v5Uox1xfEp+IRk)uNprV zto0VT`4C0W$Eg(b9N?hE<)yk!6tXB?QW;2>P`1?)xIMoGL?0i<8Xn}NRtbRQlQwgWI(xv(e|z>MYGNqOJ~W;*G1@L(j&bnl+~%J&18 zb^0zTw_ONwjX`}Ni|jBM+W$t<2*w8H1ybLWegHaB$?!{>iZj2A3PHj zR!%D-Q)vyUH0iIGi>{}=_((lh>r4WO;Ww~VPp?Y0KlGuz$A9ojZAe%7h*S)~V4#RDH`az}y@O}#~m<(KjNhJe2 zIZ&~wV>(!}zQRmkZjW==+!B3HTFxuzF4Z2iyNozwa+{d3%#laJ?0_E*1h`&cj;Ih* z)}TiXpZYzAU_H^a?APJ>)v@g5`owl?)dWl-V#^wwg9D~9yiA5 zpJ-?1-LwHLG!jU_)CAn*Hd?sP9B>i}IbE`7ky7mM`<7Hx#fmbp>O^FTk!_D2FJA=< z?0frIbML95g}2S@(TfEzlt(Gj`Ui1;`@vEssp#*o)zHm1V~8jxx)2(;@XaOiy}m;F zf2C73DYNjOLg<`EyhOvd)8mpH%b-0M;gs%Czt}}swOzFCY=u|umU;1l4Pw95y-&U1V2uvL|>?V?Wq*T z+|Lh%W}2!^pPNU@S3^F(1S#Y30&;BYf#lq1G$}YYX^E^~zT&w5G{osPjaB8gv z8Dr~Zy9zsJTg_5NIaqugII0&~eD7yS@5A9XJB;&7hQ=sLDRj{y`OLNtj#5R6Cjm)g z`mH`8Hpi6?e__A>90_3!lMLiJwt;VtmR{Vyepxg!$k;(rb#NNjKXL_~Hq?s9Vp-C+ zhW?Wf#6M{~o=NcK)2^;eM4H&Vylqx}{I<65d6eH0MRa{)N!;yvJH;GWoabx>Z4V6B zFv|PKm4u5y-^^{j?P2>WT(X?g;V_t9Zeii2 zQ^HNHsJoMY2?so;{wtHL?$183bv{h+X>2xsLE6~Q=aZrCv5kn=>-M!@1C`a*Ui1$d zr0fn&>Gzc)XFOP+BTozx10X12_fnqmW$$3=cS_bNx+Z!o!!Tg427Ws{WA}WK^Nh!^ zr>}=z>4(8R%+WmXF05!T(Q0@^cMIR+igu5@r(@#34PJRA>$nW+!Q2v+Kz0#h$V%F! zn4p>9H7H)MZOFRf};{0}iTwq_KW5EPOU96@X02eVN3r7!-h6G|+ zl7T}B=aZrVb+o_O<0|`8qf$d}9)4g^(QK>l<^1&b$A8Ip)+w4dD(cTI!pyWhC6mTN zXZr#$!WJLyFUCJ(7k8e}Hza43CkqqGOROKt+E<=jxxf{3@Du`yFFfmxyTfRmR$Je` zN=i)Drla69cITfUxx{;!F3ytU38Zd+bXuRrRxU3}09CRU@cLKgQ&>s@M-u08tuBOE zUg&p*Srb=^qEZV~Rk(NwCAD>m5Hln;b(73qy$Om@R!{}2t5pkQObU02sCI?-7QV&D z3+$T)rBH0VtELQ!iyg2NrN)h&g_%qPa>QHwt`E)-G@+@qwnVQyA*t*P&%Xa3F)E@`hwPY7BLiXJHZY%@_0dufAWyUB&@}bwq>0Js;SP zPf>=u)Q|J^tbC#}$#~InDO)=2Dzv<4qGISY$0dCPc`Sj%cZeZ&Q9k|_$MT!;Q-7^H z5q@&{k-u)q1KqrJo*`G;hl6rkLy|v{spO8mI7XKmxc!n0(z&^S7>3=!J@21CmNV`# z2vzj=3&Tdojm>o#l*0bAub07FFzOTpL!EXpcfsojz=VAA`mdl13V?$!&<%mlvM(OAdD@-8h4Y)s*@xa- zJ`^_p3mO=ef&p)w)SDDkSD5Z2)i%G9@%s_ay_8V~RRm;JTqF{E1#KeLOXF!5Q?3u5rA}cZO={&(Y@Z?^WTUrfP&i#@a z^{U&ryImgNl87fN%5%ZLnFPqA2`}tNtJG%>onFWAX#>5+R%6SQv4-V>dzFLvc(57Q zBd7c}pBUq#w2c?`{mYE&b`>T_v&;{I*r%sK#XqA57_&nFhpOb|{dgjbaAXCJjfpZ8 zVk0~TBwTZ?&JboL2WQy6D7PfypKRFyRyscN2tbU-jHSiZvQIx}g!=tu#kaQwe}=qR zE?aCLBgXD9v-x|r`CPNi;qxNTpNaZdS-z(_f3^Rvy(JOtyc-*0Xo()HIew*o(3i6v zm_dy$9yGa|U~?Yml_BXzA54JZa9Yv+ zdiol}Lz0XAA#WBo$5b+bWLtr(lKbOlm!*O-7^){GTh|ere>StnNp7uX!%bQ~(`s;I z0hU50<&R$f@>tWKhJB2^n?4(=ZP>sPp-p%VCeV@6lpOe03sHj<*u^k0V}O6FdaJ$~ zH#9V~U)ln1X9HMy-}q@8LtY?vA3C)6PxVo$Qf=t29c6-&h*Uj*6@u1d1odQaux58( zpYQ5;L*zD@%Q$kYcA}j5mnJ15RSm==rA%3D(S$siEG1-%!6jcprSvy;`N6~^G$9n4 zcDl;T>6Q_3?6&imi<# zPG2s%^GLcvR(se9^pWw$-pmIt(_KqohqVXRQF}*rFRli*Bp+{oc4=<}~ckW?i_g%L= zr(jj|ecs(EJl&VKi_|0DfBR8FlmF|*WFit}BQOja$0dWv=cC_tKzm1UyZs3B6+BBe zo(p(3{6HAc)xC^G5Fjz*SJY!b?ld>`)$BW+z%A`L1znxhRz`_|?d=q9x96AHctnO6+MtrzbMc|XSld9mA9bvU1h(2hLy%u}Mux9UUB(4QJ% zc#ZoFn0&mf;t9QiZJ(c9xGH-1~9bq_9wM^%{=Npc;bK?N~j5jy-hSy z;?%7E*ab6%XtNa6sJ-_2$`eq*A|V_$TaPt_Rl#kfKcCT896~V2Ptd?~q+A4YhnJpK%NmU{JjcR?%#{O5B_$TfyMU#*u*i!O2ExSV>0|~Zf%2Q&KTUT zpGfA4{RR513iqaC0Wd75lo1@h0mRz?^-J!bB7R1RHVYRd%v%K3d=k{q)VpxOSopaW zw^9Dj_}svoD(Zg>oE}*^KPTBfs`aJ%y_~>xn>9TB9eRdO)Q48AJELVLGpeUn+(?{v zgAHAEgSEF5U2At6tB=(^>?!H@>pq%W2Awn=+TWyhZ*VUzF}9Q$r(j&N#K%_>M8=;k z-|}N{#5EERcM^rlkxi=pgYQM%VL5E5G!Czo_x=xAKEkDv4if|ZZikjM|9{rMMK|~tP1A;-SmRV8G%fyjsuzk zXow)(U>Yvq*MOY2D8emx%VR*w@Z(Y2)7;R+JvZ5=Sg1{NdN+LgFOFdNOpW@MzR?Px zNY}3;s2)oQh;$!mQtH3!cy_Py+YegN;a&ESv)oHQ{uV;E3$ICW%cKo8+JB?wnaULG z6WR+K+A%b6R4MDUAYrT`jnVrK`5bwKLwdzXLh9`^S-#G{oj%g;dR7eJWJjS&Mkbde z1+4NrY8`GhVmRlU@}ltYb0jvk3^|-ZG7(3sG&=DU@$eH^f5|&j`YL8hW=q4dO4kG7 z|(Bi|G@#^WT^9HNSx- zJwn74OXnt!0CbM!2J^hEmDGPQ3J@QITi4G%mQF;ETMwaS(A?OTZ9DCXvA6%ZI$1G_ z4zm`qO_fJIiM;-;hCjmB&Fsg8~)tx-t3b`C{i8wI_v2sJQ`v-q?Kc zVc6C!Xd10pH8NjxfTn;76Z{FzKJW#1B_%vT@H@rJIM^{icW=tExbTAPt7TB)`Zhk! z{U0!0VYv#U?tqnKNWU`U;ghtEgh}xN>KB#Rp#o9h1}UMf4|z$+fPJ8~n$Wis@2+==LF z9CahRzITDv694$gp%&0}g6f1;9d}2rG;wM+}bkzO|>m$z3lR z8TU!0+rBu2ZsX0lx@=GJ9r;<2h_nIe_7^E zqS@Hn{k=RdT<#zu3yv%58hDE9roCLZo*xpSqgb4pdKF%b7k4F)OhBJHgKhV0?KRJk zISKTb#03HKY0gr!q=Q^el*tn7RUYko)Yv@J-|lGjbEsA@2YA?fux-z9weho;-KWj2 z#@^d8(okO!G~eV@6Lu(;+HW2PQXMu_~oT$IwGs$yaob8I5uNhnzkrWtFqN*Y01QcaxrF7~#g&pH@56GH1%a=QKeN z-e-;LPq$>aIP-+>E|uqm6xAWDg-kejF0%$W?`z4RuMPhzid<5beOJQo3uV(@afL7x zw><**bfz8dlZHIP40*7I;Q(P_w`Z!@s~5lniOWo18nKU@YLMZPtYNFWJB0}sSaN#2 zjkf?Hnj#z!2DimQzlqMv%uLx;cgh!0APLB0lWG94@5d03c=Rq{7TSu|^z(xuFNBIX z?hDs$uGfZGKoGMHImQzJJ-w7@+J1pmP4n*-rV~q~kACy#*&j+)HqKo^Rh+xDU2HJA zKmN7PiFhd<+6N>VkU<}rg^!#}m1s{FXueZm4a|2ThWm;s;_c6-r{PH&Boi8LY5pWrJ$(eO#ecB|*_HK=nUu3{j>8X&H^m6%PlS#(s|lzqVC=!S zWuQ)ZXGa?oQsmDp>lOl}1yrHW0u5YM;`d9I%Zxhcp2dK>+gPCw*9^AtEl*a)A{dko zresWY)Pd_=Pz1cU&PsTcXa|X~fB=De0}fotI+@r5grf*~Y;L{e*$l>dVf9+u4X6^j z-q=B$E!&u_pZx?-4Vaz*5|Gpn@oy~(ZOZMOYIhjNLy&%RPG?H&z?A??W%8 zSZ6Fu2+KTU<#jj*6Xbf1^maw9ZSy}zjx-VD8}FQeUkWS=i)JiOg*LBxNNcYXJy+k& zzfN6ytrf~PQ-?J~0NTF%49ai&A15mO+QG=CtI&-_dcJ*y)m=J)-~;o`M<*a3LVz?(Q8uYun4bzaU<0_`7Y1~_sXX2YSM$%-{cfvI1F*3&VWbBW^{k7>J%-H>$bgq3>fs?Ls6?g{E@qvX z)c@$U6#Hu-J0I6C{+tnK305%N_bYuFXE%RY4Sz`O@Q%azg^BHdNM2r1WdBFF0#EVu zf;kL~Ht8?Zcmd-K8g1i~S+Zuvs61}|6YJ}dW2N6;peRFC@2eLf zc)RWzNA|w$vfcv-1)cyPB6|fZ4_pkonZnw5RGwbaa_#f?vWdO4>e)v}YLq*WR_A-@ zYUoEbEY0T%Eeh$y8YMUAxm`DL{tbZ&KM>Xui>i+faZlGpyJbTng*VQ2qN1!QL*AG- z<)EF0_R2tBT!5YzgEDz@7`(*uOqJcIvzu06TSWj5rc0EhNaN#$#I&JC;vYjV%c^)1 z)o;glw8Oz~@!QWx`@khK0e50DNzyg732H~e@-2wbT!@p;K-VWrHZ999EERK4?ml^f zIp-Y`xMj2e4UJ?#O<`dneS#0fM>L;|{}H|kddH7gFlZpt?)8CWJqA0DA%n(QS5jD5 zKccYm?B~$jK!Hq%sq2Wzx}G{G zx?Q;SZ8TvMEvl_MTlGW`1th_(mb89<&RX3Pix1KeGgbc|u#jpZhA6et?Dxw{g?H&X zcZohQ`3@rNJHnf%Q*dg_Wem;?d^=hr^{nbGaF^lXUgv^pIV20;?DLZ&>p9>5S9{Rm zHtsP$h-*O?AEAN6X-KRH+ATBo7{5Hic0Y3UN&1ZbhXx$=^zu7$%vBQwJ(KTj(Ftle zU;-C)5~4Y~nf0I#F9&EPwa?H77L=`~&N4frpXA-!Y;DJF2eyL)dTe1zz0hLx7^Lu& zh`j=LY0c358+L1Dv4s;PMI|#@0X??(V@a$I!q{)3gbg?W4!n^~@S8|#mIz!tu+*%H zHm2?67Pco6Uc+szR^TlHa5eNE6GZ>L9` z_FwJJb`^Gti@kFTBG={kWKL>DRlhj*=i5bAv(Bga->Nf&UbcI{)}<|;zfEcSd<^jR z`_EdrgV+>40Z({^tZ^g(57CYJ#zkxTMJ#GB64q|Xzmz{ zhV#U4BV`V%^Xo?MdN(_uiA!ELr=zoozbX2xdx)@fC<8<*00CKm1k$cHGEYC4rzJu$GyV~B=`n`WYTfk= zX|*nY?j6Uv&HCe>9-V0v{Hca^kn8)~=JDH)N5r&@GERrSPf;Hk5SoJfl{vN@qa)l{ zwC?z^N@0NQ1yQv6<2FRrC*0iACjY}Li-hkSv?|*wmF{_nLBLc#FpjBtu8ByBA_Sqtr#3qpdZ9GIBR!Fwu%-{U6p0(7MzZC%bGbkf;NaACuR!pe+yRjnhkJeH|Er0KKDZ6YS?)yKI=*zDom+MHo*UTQFV0zWbHLec{#l>J zigN7+jo*CpuNG~$lV&u~J{kDu?yiDhk`eVp|n^a$|6?Gt>@t ze?Zvl?zRK>*NQ`4}EWAo{3Uh3e8pu zt+(^*6(@aZBno+ECqyD6q#i3GtcDDMWGH=shD0U^x%joq6u>ohz(oQ18M&h<6-n~3 z4cA}xs;AAAZjL^EgG`{6AJd2K$4f%igIvP%DrR38c-eh>C5p=+ykfR^TvGp$gY-2!X84>s1^C$#ar`Ly=Hb4o7#laKo;0s=ODwq?7f#J^U1_LZhfY zbkq~;cClvVQFw7#X1b{p*7vM`c)j13W?IUNBHbH$t`#Hj&6*tF$G)SdCg3AYuHLzK znjy_dqVF{_w%1e7>W-4j)NE)OzGa`{eKoU0c!W>M;9%(yG$xb!A6`HL{3|4>FJIvZ zd)V+MbLi&@%#4{;t+gg|C>_QmfKroq2*g-jX#-c@{Sq*!kPQR5oTccCM|9RI`OKR9jp^S z@78iBXt2tcJ_y+|2c>xjyp}Nop!5elv-QKy;Dre1yCAHId76pw2d-U|=LI0>E+VCF z(0z252HBe2ECdvQyPXIR^Fk$>8_aEF2``z4S~#Su{8r zTYo94hqtuBzp4PQpFNSnpa@spq?tBakR#DfRsnKPwUJfVF(ERy`fW`7lPT81*KzU# zXzmt=cdV0Es&h}Rs(>-@$E~pNnEdOw9FHofPyA;s-;Bu8Mwtqjzy5eykr7#Y&b>~> z%r-C>&G%S5?h6Bx4_;$dT(c&)+QH%Kz`^xrVoM)&TJ_a6ft=Es&XgAu_{TFq4O} z|8*!}+VI&GD$(WJ4K_cb5@&y5HIS1YLvB6PnBN?Lxq!@%>ylgf&p`95MbSjP*Ow#g z+dmfWv%iqVfli(x$XUK|v^zLeV~64!8gxo{dMyplpeRN7zSeE+|R=U$DA zQXI1QrOI3~t^fK5owr!xV@GxRCPZ6K-}hPH%(D7$VhLUlCleO;9}dW=iM1C%eH}n2 z(U0G%Qn{Og#JZsSNBtl#f&h2XAwh@Y!4*GsE8edT4R7Llh2*MPE#^A~Hq_J|M-_t# z>zJlx;Re@(-xTl2t!3XknLHBOJ9Kkv?;d}JUD_43T}cPX3q8%0EIB#?K3d$Q$dOhu zj{tcbSv8QECxv7ILiClcoaV*`z``E`moLJU3BNM~=Kt#=iC&}aZZvcseR+a~+XfhV z;IB-`07!eeK!GtLAUi<#S3Q0j6MY^U!Mg zmgmCkX=~<&w(i{T^w*;lB^2q9nS;f#*TOOWFrN;Kul6lVH`Lv;FW`WZTQ>(ok*SvI?YnKC1wUA5o<`08J*?8rq407_Y$0px*D#Vg-Lv6t2B90+o`4g~t@ za|MM=?iH$M;K&S3(hWj~N2&oe1TgU;90d^ZwkKw8=5o)H1^D?dl{UBC%HGm=DY)H2 zo7vp(sqfym>O0W^)4ymhi7}%)HRoR<-fd9J>Jl94>h4ILfM=c(FnsBlbWA@{O~T0y zb{PU2hf##f2lp+UACadu!tS8zt!|=Y%JZx*N zL|)3Gy>kPo>kgCeBJz|XQ#Q*lN@mlcAu7Y!UXs|K?U!&6TCR8@Q^1BY$c4NLNUlSd z7Kakxh@rSR+;gEK(fY5a^+@Ql;F zfWM#03fO)hmZbC@x{*OY`(GlV%_MChK--c3$d&VCzAIOIhosR!^0a>YAR-KTks{PF_y@fb)RTnV+q*={+WxW@ z^!VCtuu%{xYq^XYHPOUns;p1zyY~(`ZxaETTIo6}ZNz?XY>(2)B2jJpY*E5I3`#Hb z?o8ol>wn+11Ze^e#Y(%G9ZchK$(44?eaaE$B|*Y-%}-Zmp>zh;jKx;%|9=?kLeU_^ zM+Y^k_d>7r>|>QB$)Mh+bJp``JLWv!>dQkM)+c~lRU~VLwLA9X2>+BME@nn}ZZ?YY zt(tX0yo==QSz~bHdX*3%(6e43I(BLIltjdt1~*K{x(j5y`&@Cb#Cqk$6gQ}~h3TpM zq@Q<}-l}53WtA8tN7q-p|Nc-NgK8^7=Fh;pYj8yu?f|clZG(onReL_^Pf_8F;)z>A zS3^q(XHn{!UBm&wF@5npj!hi_RMg~5=(UNjUr8$aH{NNu>xn4#M?^DSA7^q~%9wZX z@yiZ1?S9&ngea2zTE`y7xnqwqUZPvEs^Q{W7(9zGk9_pw&6z&E^7}bw@<5Kd2<{m? zC8QOcV|M+*mol9Z*b=7GWeGqD2D=4S8^H!JP{WckvP7v@N@T_YN7pm%X}XP3UqKbO zJVfEXe!n;82@e-w$q#+=IICER4RZICz*g;fvDNzR4_Yo|qsx9Ai>{KqQr?8V9%cNfS6-*0tQ$(XC-4!C2-mNPRUH{lZ{q0(5^)#@V~MqXSaZd6m;8MWpq z?H)pNX-^{V`?#%tSF4Aqqdb(7p^*3QX7eCxRyAs4gT*?@Wu9>;R(2- zFp3!ldDf?xI?$xgDTc2rIl+@s?%vFA-(R(X5-Zf5H?P6J%&tmssDPswls}klUKFnC zv(;atI6;66R5xOx+};>|23FRU7#Jud1mTIW4z|ft_Tb6=-`ztUV9Mty7*-7;QU4sj zTf0HQrU9@bQNlfZ;ud^`Q&IOXR8!8{lQlpJIrjA4*j-lC@&8!)T7eLIKUmUX^uT%1 z0&~aid;0QcH67P2a(^p({0KfX>+#q3esy3Vo*}kb5so}3*AC}G0Kp$FCTN;Z=s$w` zS7Kwf=@H5c1zOYkpL}beG6cCN5}oeaH$6T?geg*_Db{44Y>+gBILcxp%_*IHb#L_F z5N2ybb@T`Am4ZAc1fJq5Ty%Bh9Bo91EhtO4=J{=eE+oi6<{2C6;|fhOB^i$80KLFw zi=czN@5|HT#=R$YX>w3ml?XYY;~qfNa{m<{bDU|6030+FO8e%8H*r)P@bF0zipuqx z&*ahRWViQXe&o(>ThDv`!w-3UwS%k!@yrJ|LV|+|FKHbMI@lLw4!fsDKxYz`5BgyO z?lIB_mi;dJqa8j?kJeCq^ZGn(LvIMBpDH&`Mq*LWqFtaQ@aesFi5_q5VWYEOC$&b< z@}+N(-xTW*_FA%0 zj|9+i-P$LW3Ae*uv<(Cg4L}B|{wX!L#gQG7*v8%Ohfdd^sCg&e%Zz!Lu@e3fbkllD z#Jv3aUFCtCm$%h6#6&$74_8HuvPW4PsZUKj3#gJ-U*Nf1=keuESCi*TMI}m*hSI87 zjTx2*%-GTRmifBx*DSh=c(d3=3GLp|#%*Fd00kaB*`O`d$8c%Z8A#Gu`?6hY;MtdK z#bv7R$$G?4Sv6z^XNBTyUl)o@4E@|QcD`p`id4YBRM42Zwnkz~1yV7NVhyZ$W?xte zHJk|jfslo#*IIBDi1fbSV_RR!Suc-5mi;|GSIqGOlQj0rp1;Ta8d@dq?BekSrqKfC z6nFlIA#n<=P4SsX#x?r<{VeiG~ZebkMAYHZ=!|^(H8DwgVfFg{{VX)cwBsT$) zo6@*V6o4%ETde@CO@%P_)nia+d)PC18-DKAuE5bqo~mpyOnT3e9zmE-G!D??loEg& zh<485G#WoYIPk3a(vT?uo*vcWP+$*~)A! z3oZt!LM>AM$+6S!y~VeLSC+k7O52szpChCHNt0As3-@*8DOm0)ieWC7{?UJ|E6v@Rr^4E#!H)!DIw0uL1yk0-!sP7MR~QGAo!GGvMj@ z8M5d#!(|BfD_&Xxf4{uLz*vBmdvtckH4N|T9c4@K6+0ocjRhd6o5G>AnkVdJZ@DtR+{kFpW3UeEO$1k~c8xxfgR+taUzg1jZBH-aTK&K6fl|}qS1TRm&#VvV&!swMl>?397Jza)L3VggmM8ZF6&do{=%m?V7`;syUl+fR}_~6Lj}Y^ zI^78p!Q^c#GTS7Q+6JQZpRzWqqs&Bcz}H4%vLh+0g4q2@_dnrgwV}SK9?AG>3%zYn zX;rfO2$P?|y8v?2ne-YjRkOl|Qas2MN7?v|;|(p&3X)aSJN3W2`syf| z_S+;Of7YE%Z7)YwcfJ&9Kho!Ltos=b@~opPkm8e}Y!u6dA%v8>^wG#)Z>~*T&4N=q zMcRvW+K2{_I%VBS^ax_jBFBp;mi|)nYksu6nqhHYY+V}rfVuq-p}5Di_U#t$c3;o* zHsqD?@lGpu8PTM*n|ujxod425Z5xDG?3aJN_vaqu$Fz8cKRPg$09p?Ngz~5?0fHSc zh{Q(1{4OgKP8U?pe?{_0>h6!+ZJf*#=eGf*Q3Uo^um{ht1ki26E}i=P1Q(~1lR9+j zdVx!lKTp+%+v(UemYYZ*iFZI3srB;>Nszzc7ZbgMe{TTCWFOD9}4X~c^_LEZt3t=k@ayZ*S={H;AYt*~})-Z%W+<7-S`0fBlv0QxiyqWhlj1On>29n)xk-kzLiEnb{GW;g!3loTIKnDUi`f2Vp|W^>`p@x$$WyGh;iX0~_nw|#|08xr}Qx;#Fz z6E!(Y^P*Rg`I^j!a*h_~dN#?rd%@GeIM)l5X8waGn!7h3?cydns)W#XEG?ORa`!s4 z0+J!`W_{U|p2>1FZ}y-p1NmtPD%_;q5{mV9IkL#qCL%F+*DwQ5 zb^c=r_zw|z++Y-|9|(O zWkI85a4Shx;G#Jz#4ZA1Q4WNh3%hI&KZm2Je@%fr9C=L*;`(2e@465dM{f^5{-`z5>ygd>4I9`EPbX#R9Js4jmRJw^&j-i4$@YSerh-JZ;R2`*pKPdg zt@khK2a>xVo<TX5#7ZJKi8Oqv~c;mW}dwGy$}7aB7W6H?{I>bqHwHeLEz z^o>~ZJH?+*9-h737n}Y&SVOZllW+zLY^+;yewdhT-hv*Y{-Heb@{*>e8INtzh=7k3 zBv1C>Oc*|#D2rD?cVsUL*zCNijKZ}-DoQz$dT|E+vaaHS(7fSsN6;Y`H%AK9%T^rHrdPf@B1;250@!;ag*%`qcfWA4n< zw=Iu{mN-P|aT|#Vj>AuNoN+;!`3Ry6R+m0MR6K&4wcILPU(!E`R^cY%xU;$6qOJLs zYf^Ao*qf8O$I6i6WBQkK$k>W$c}8T=jdLi`r3q++$<(EdcOOawJZ*mvxvjbC@qovZ zrImi!d8X^TzYEO3as2EV&{S*ztPNtEeFp{QFc1WHlE~eVbU^#rp5B5Y5;0(EFFwLs zZX2w>t-#*$k)S3b6(w5@1hd)zQYX}JzduGD!jAGad+?~=%{9y4i_dK>^=(-0K-xCM zd`1C>;V(}D0sjHOF&iKuQE7K_qk~mTJ2lpwlk*hH_w1s9Kue}J(`*6OnX*o3? zm!8Xkg4Ew%HfUR#$;^U*2>ODvq;-7mZ?sCek8B%UtvuzOgIYs?huuf#K}1~_ZC|u10?;Q?U4YAdMaC4~tRc62(4g z-g@tLOH#*8>8x$Z$c)FMH|s9nCS^RWS(=5&8Vf-N?6U5;cq1~kgpfM?S<5VMvKCTP zNK{|#dldVmmoMlve{_Fy669PZ{trB{qGl=_ZGb3@-cc^~Ta_|W0_NB-!K?6$LqB>u)3s22%}Con`4nz4V8L&D#RRU@ zX9uLUH@#{nYTefwZFdP@S{P^-^@()x5t=5}4a{pkH8|ev^L~-M=2>^`YvZ-5V@=C@ z+(XT3OS0&sF}TsCo79P;LLaPOmz7nKx?6pu3;7%~hjj5G=s7*P;=w=`DwoBy53CDn z4Ki6W%DWVr&%ph4JZ6;?zZcbrNXJYD5F|Y18RmF&k~taz*D7W)<8N(3$jcM{mOQ7X z{=8>EqN7GVq`egfK3b^2S$`fM9~X>INZaq~GA43gTEJ-M{blkZfP5&&IM)w4{KK@L zpyZ_aqVuttpp|j$d7MB18;0+l7WLYm> zE8=FCAI+Ji<6=CME;jsn=nJG*nemL5Hx{35*|vJuf3p*zp6 zaI};L#Df;L@$v|Qe5)`bsgTO6xWUq{Twu3f`$M>r)&5)N10)L7Z!`d za_Z1d>}~$oKj3M*#bNwVF6@@X>+O z2>7I9WR9U>p89vJF09KsXtRe-h+&=kg%1|b2Y>#;n*uva`B#{!M*vPJ;mQj{ov49c zGz9IxLZj|0mZr{8W*fp>d`Y;v$glAuX(*=`neKL@D z9-sg3GCG4v-cLv81(q>%x%AMkSk#q-;}l~X-}`b7HcqhyohP4UxQb z?=!C@D3gjVZf#E?S-&0rfD3x-Np?VkxDTd-U$O5NF?^}h30GyrW-sbUuY!4vz4k^E z@{d4CiRr2GLssBw@I2~yGxz5JdpML+`qsOC%Kkjqy&+GkqJ=g1aH~nL1 zn~vP0zaKb+bJeKJd|~)m5;p4ma|A9(2k~qA-VI+9KlDU|PxR|4x_=qi;c|GgGMkh- z|Hrc%(I{@4^%(@xH#BM?%I7Kg9ZBd-46$1yy5c-u1s9IpGx^tnP#$E(Yok_RBSEL& zD_W4zX^rVrviGKr{^Qd^x&l^py zWaf)(6em|P_4gpUm7jScr3SZW#z|nc7vwp$xdh<^Q4cVuplek2DRROmQd`+}3$8XT zDZby)RRnG8x_dsW`TSat$C~*YUE;SoDwYy&S&n=tL^F#@`zlhM>#{g?96-}lq z(NjxD?)sler5qhKI|b=Zzn>_SuR&TJy-^K=FYw7b{)yU=@Yi)#drr3t|BjQVJN~o; zwAQ@D13t*-jhZl37qsDdd!Hl9&_AC@8aapx31#wrd)@g1FLiDw|10Rhfaqvv@cLg& zJ+saVmdX$O$4xK?==qjFACkZcq_aME0P?yZb|I@HK>hZQSNY5oa4&@&cje6u@@C`c zmZnb8yK+vfJVYNt+OxB;hmxVdvf=p_v9SSO=!d@P6!CfFTxOc~Wn2f1OLcEIcGnQL zkv-3z=t=#Co`=5euQ=b`VtO#@r?5kBaFi?T@5f4+kP?YQw-zNeVhlY|kUQ3R3NjFk zun=>rmK`Pi3yTPAX5LNS3E`jdiE)ibCt5Z!%VKK1pL*Hf%5{~1$MMs_m|u}C1Fm7v zQXaB!(#vXQKAX)UMGNV-%&?S;Neu41Ul`V`L{7k!;p?*uz3K*fPn3;Z8!>Pd5%_&>tAql=qr6R6Fn$ zYGn#gGby`q8wu57d=+J@8oYu<55}na&%F=B{T_Z)bks5GT*!ef2YPq4G+xQHSk)-1 zV(<4~tTSenAt77Xzw+!a2eo+YQ?I+DXRwfDwCB@66iokcOP#AXhZ!q`A5<1M{-<|g^LR*_Ox{67MT zdkG@|m@wz@*{?x^h2Z`FuH60sxhr4=fiOaj`9GKuq;-qgK*CuZWVxuzx08}5u=F;~ zsDP7>q$593$(@LbWLKEJ9+ndXgvs6{JGqbcA&#F6^|DxtWG9}-itGVd0(Vzp15cbf zg%+aFbj1*iRh26asn4Y#izXJY2^@M`YqFwGDpz}RG)y}qu}re{yuZ(qTEt3Y=KJq) zA_C6GYGZeMogF5=Mnne5<7!hr*4FHVo|~^4nV$;Y&R&9CqVGr~pgIFN*StLs$LkLn z(HO<%@hy^A5oeun=!sRQAjfDF&{ZgVUnb9BGz4W>6gLAU8GN*Qmf8&c$>ZwR?=6p?l)tb`i{LGk!?-B{CD;V7? z<9cLF#8XTPZP1f_{o2Aa7DL%j?;j;CLUTjSNbHk4lkg8tCM!Q%$(B;t*U>yBzDLN#4p%X0)D}zWb$|Dn)LjNfBW2+G1 zY_-kajBhw7!V=+ptRup#EvS^yIo5DmVwPVg5N}3f82rkB(o;@8SNj3~?&-*RJ7a#X z!(c*B_h$HDiDqNN-j(WtYq#OAf#)oXbkP~Tj9Mh5`!Df8p#W)*wUv(D=nlLIY15%S zNWcI|ZD96hK@ff_aV@y;F3fy`+ry0+cXZ-K7Zgt|zo)+kw#hrJSTT04-SeYHLM_wl z3?n7g$T=YGpFP!B-yn}0EvVSWEiLVC_?=Lyb`0nQ>eM8Km=hz;_= zK{MI3!)gPyne2D|g+qu(!*R&;rP^byh30o^Foz%BzILdhRRn8C-bCu}RGt=^5jeRV z{w6UrGO?%$A2~@GYbVyxTb~(5BCA62&>kKqY3{Zjwaf9re|=7H$@}YCgICd4ZIY8J z@u!JS7=2F^fsUJ~%NB3W{k;8!r!H^)cuC;z(M}}K&UV>!V_;=zgctbGEo0syOsokb{=osv*?=!)ET1efp(syvy#@n(eH zkRlSKuZsUwx?2c9a%=zW>uBIPTURRp*a%=xrto~1WJUda^2hUCf1Piudd?~d}J z^qOOGl`^KAIFJDh?B6$ssn^Kj)4!`@kzy-Tt=o{t zEW@h{p+~OUqxs4~ZHTh;UicEZnvR@=_#HBn47QdwEtda&!V(8f9gy?1p{ctgRLH@JN#JP4>-@^HK4HkF7^FBo>UJMcl=6 zq{E#bzIhcqo}@1LtLup;F+xm_1W_NAeuYmpsy$voB8?iu}Naq zqCJ#^=-XVLHC1POyeJCaaCkYc<`3f;zxrF!{4Baa)M*Mc zJnpmR3I+$mP{D#TtvxaUQM6d<$KSpzwV|#DRw>;|jfKmK)N@Nw*G87!%HQ>h_yyMd zL=l_p$k(BJlFS$-Gp-iX@TMgYl5#r4RB1=N(sHeY2@|qO+s+TLe$N;WMqr~$*c5tL z04E{fEPO9QQ63;x68hHQJe&l72Y@*Q&NTrlgVLRGqfJw1@BE$_9c#-{JW=2)(R36j zKmq(fy_N*~?@z*E6SAy_Y8-Op#oU}YIHz>9ywAGn>^jK#@m})yZ#9@aWeq34Sn_&7 zj#|+CF`BRtdN@icnEIXCFNUs=EvV*sFtqcf%NtT-U~`ER`Qo#@H5b@i!L>hziPpGU{Kp!|Wxy;z**Mo{uBGDDu>nPiV9fRvHyTOtHfdzya-DLt~@)&22}n)VrStY5gm8-tvnhF_BT4O$P;K(GU$1u=kud;jGhnju>111QX({`0XsE4^u=?M8hh)IFxhRSvez;_^&DYX=e-spHSn`Lf^Sq zEt~XY`)X8IE$au`WLOZ$bE#UwWvnW!y}Hda>T&O%BGzvUO~pR`H-3-$djVYjhkkv}ZqEHo?mXx{i3} z^kKNRp?hzA0~O1MO!ge-YN4bS?EnwPoakze`%eG21Mszc#O<8zae4P3ux5L_+WR3 zWh?Wq7K9%5;c+-11BybqbO-44l7EpHq0t6C#Yp(WvU4pMzF7v| z#huQ!p7Srvck$=n=js09{R)~s`3Q=YZ+4V`9Yt(Qcu0~a{gn%W4FDmmM+$vRLgFkO zdx)X{Tt5n-fzX;MC^QBKaO>SCG)n(#Bj=CBjFtSki};_1yw0CX)L=ZCgt_0Iz5Fc$ua`O_+B# z^5RbQ>rM~U)wvN z3-Je8ATJHG7W5mow!uoAVs(+!ekE+JZ7lkAV0bHWdTPBf3~YT7p4Y2}{u5<8UlYsI zz?ZcA^BHZVEyA|f4Z}YFUP&rxshBojD;RjwK7D!Bmb0<=>+z?*CmlX~LrAnCBqHVG z%?ttzv@ilEL*$nlYpUV6;=l%ikLZ*hV-&$@yd>Xze)^upa8Ta-!G%p(i1Y4-jtSGM z7AY_Xe@gr_C8jQ4Jv&jiJa`mEY>vS7-2rWgXZ^!fc76-;1KGD3yLpvMZ{+;swHkj9 z-2SIx_mpQj?+nIngRh*RHOLUAoOP&@?-}_0Am!DP7%0_LZZQUN6gfQRdl~U*tcO{9 z0$?JYNQ!R;ges3k?EZ!jqe~3`tv+5=Eoz{#=hOdyT3j>hi0M_qiY#t|81V4C>8Cp# zl4u8#rvLAK50r|ggK{L-fX(Pl&i$G(EtJ#k4cKUGlaajFP)rP6`u<}ph@ygWNNiY| zUe8p%7LpD64@H1Ogf~e+)B3_dIQBo1s8YtQ@q_<&JfBH@KYehO~5Wp;*cS|7&U!gtB3qBr}UVlWX?I`???)87bn*kcQ zDgc=K`(M)k&3CUGJ=FIhaIQbt3uYHImDA1+w^b^ovM8|et0dhkWVMwD^NBzQ+F`XK zRhW6(ISRK}KaPc=6|A2AIvNI(FwGpCBGo4%Ax)ao<9PwWt6_Qy==wQa$2i)OfUJS= z_jLagv~e>BELA)um1C|L?HpSuHYOW5_MWo=#d=F z{-1SNkFRxud-<>p)XIGk$}9tqyKRxSwJ(n~Prh9eq=7=EUx;i`NB!*A^Sr+TQo>4cN%cMiY2h+=Fu(YjsrT4{(bPcjpDZ zDrbM%EmuV@Ug?L>I%v#kwK8=t@x(g11hhq@M}B!cr*8PA+A3yn_a zUIc|-AwfW6Kh$_kTsgo~`J(i!FX5zbCf5*w$t5D>@N7{X{O6hWQn~ z6~+l2-A$Oa7t2}`R|J*T#glFt)7iO)r7-^aAHF{r0wo=p8yVm!Yp}QQ-)#k1+;t~; zyNB={#udy@49Fy|2(@1V0>FQ(&@-w3gv8FVaGZJ#t(itajTaV1c?9&`k2NPeE{~sd%4o*Q3wthY#O~j( zKNu8u^KC^k4M<|VUF#jf*E8J{z&G-D?U)PY3WjBN%V1G8vuYLNBI?7) z$O2u5Fd%S8(XVT99W|jssC41Aic!*V`Ovq z?wQZ(uEM?DHbMjr1jkn(+X49K;`-3brtD#TTt&&5P`0a9aTaYGw=i)I<@3CCbyH64 z;t?t*=ffAiQm?slt87tU;s6tLU(mIO@V!~D35|q6t7k}q8Rmb0&qnWVe6>*STUo>N zvwD!Ch$2)Hd>ZB1kKPi7#L-%r3dx)bvXVE2^M)t%@L!;W^JwJQuP`*ERZtCt&0~+= z7{GsA7T;Mq1r0?H4Vv)3=tjh|N+1-%_|%!(G?&^;OFmL&%IA{Ndw))eEO`q&=RODd zyQ{iDKX7+bJO(ZiVxp=9(p;ZgoBitp`yi-i!;+PNB0!P^i2wDCaXT!mm{O(PvpwoH zkMP@~oKU^{)4i$TXSD2z0xrZ*%MXGW5B8yn?jIgPBKOmQoueZ+CCFAIkyIw3Bn-k|x(M?*nL^N)9^_l#Q9+fsFP=gr`SyKTfvYdmimyLuK0Cd( z{4egTqPKAL&|KBaHSWG`yqz0^+ZAlo^`1%B{QV>*4p*8KG0s>WJags6)=veG9|z)z zj5woe==!Y(yP)i&OQ8;L|GQ#;?luB2My{llaR3OQ38;kJHBef z?}l6%`A}xa_cX_Q!Bvm)B|hrW3`^fdnD)k*n7{w!&0gm=Ue9hHmYxiA3%a(WbSx`8 z*;F13O$>Up1FeQRU6yNSUR8cG5H|blPV8)cjI{MtdVT21w4RwJ(TRLd=j^4zuNCZC zyY-28{_8-zbigg#Z*W>G=*B7Z*x}KAVPUt^IiAD$)3Z2~dt(25gNTiA>fZqL7G(N{ zx|juL%JqTt52wmPN#>TkX+$1PD_byTiEK=t|EPY7sUNT$p>HcPDSW5SKik?shRf=hs| z^))8}BlX5PCr@uKDq(V%aeh({Z#9>C@#R`lX3=3NltPn#QV)BCXkKQ&aAgHur zt^~)Em{_iYQgiIQ&wj-$&dUk$rCAV_q#ODG*<}AYR=5`VNp1>iYN777dg|o*=_dRh z+32LX<)LFQexJszd1#}w>XVU8Q0TAu8+!l>ZgslP|CIQxRwPYU@TL5RbEt|jF*FcM z!e)RD7`N9;80;XvpKb)D0nbouF+NeFJ78qL=vYf!*|&47$!R;(29 zzX?)#d)3gPgOq+_61W1lo#g8XXq=!tF3@&$*5I#FF=X5P-lj9MenDe7Cl@&%ARd7^ z5PSYcyDU^{Djgn_k1YvQtsXuQ3XMF8?t`{4d*8IaR}z-LpuO3AOSJy=yZHbp*$4_$ zfVDVnKEEK81j$1QEr=R#KjmBJI0d+S$c8${JDG(uZc9YqF6^K2ZU`sjdFWqKYt39V z(f6vLU(T&A=V_NSaP24m7apV}e2y*iLIE)l<+4aR)cmLx_uq%5&e%d|T}=@OYAxIR zJXixU&J+4K5164HM`?+yuG;k)fh4zVAGL+ON!+`NGlAMgNE4SNXWWKTVm%D33+362nKEOxkfs>(h4#-QQ?0g#HxkP-NdRIcX7&F1}Y2bTGAy(N$1(o1gW2yUGdS z8(YByr2TJnM@8DwFa~D5a{`uFSW!tTPoolv*L#6q@cko zc~oH}IFJ&RLe#ht$0ZuJ`frQIIHKrvyLvU#ND+iOB1qA*#I)Eee-26TAkXJUnDQsU zOXH z0Z~b}yMDKtO6_|ziHSBINnF|^Szo;t7=cIlP3~z8lNk8r2*mR-!}{%gaiv)wCv_32 zl<`|rvid{kwzpcH-%#}YrVE_oZ);??n{;;ZjD7Z>(*1NdJlHu-B+@}@r|t1OW_^Ht z?u*`8d10Fut5z93BqPrn+tNIe%z)7@GGFq++9^UR*-mee)BFtfQgF;eN)Z1SMC9Yv zOBsOyu|6DUZ*EwiQG{p`<>Khtu#Zy_wlCVFf)FUET!X^Gp|;!kQC(%>}FFOWv+%g9HD^=k|gAtx@@6w0#n zxPGxH|2w{#k%;T)K}e{g6u2oPEEZsU=7HIFj3MYgLRzKnNCl3+mn*ee5|lr{M}J`8 z&)4U)?8PNd8-f2Z<5d2ZFz!wLO;{7p0hA9Ke(a@Oz67e=p*t6MCXyu;_Zf-3}7mw?;;NI_Qr39J_vJO0Vh4wBB)|f^YJvChh#qN-_lOx@!wYC?1^p&!JI{%L@n+UCH}mfr2bN1#x8V_38^IfF-BcJUk#{CPv~)&IywqF zD&f_4h$0KrvT7L%0y#i?h%L}w21#vYTzYT3ckSr0e-pZo&yLy@ERZXR9TXsN0hC^N z>bo0RlDcD7tSsmCjWALv$ixnl#j#7CBB|%#A1+WTuSl~Dmg#uR+TM5IT|YLcBlY;J z*t?Ex{HBy`JbnK=)_YXCGsyl6f|))*)mf`^a(oNHz$2ZpJ1I!)f75#Qs>UNNh=Nia zB@}0e{d2a9Nur7lVx^oek)R24Yl>KapKHG75Qt6xHes{5OP0UPDTz`H)SWjX_CMVG z;gg$6%H5tcA4IqT4BWR*H}E{}DSogpnH(-=?L`gI*3!+b zVv~sxf$zEn=4gUrG2_CK3h~=5DxR_HkvIG%8zOxIJ^LkYJ*dTZ`j`4lw?3@(Kk*oO zFkW(i>&pT94hVB`j*drSy!vmu8la^o{7*x+tSsbyJK|*s+9~@$xpGy!)T?D!L0sxn zYzKlNR)VY;$5?>01;A-5{~egvJu#Nu6}Tj(a^0@visIgj!Nxh&n?=?+69Y_I1bCH( zw=UihZzCf-!7L`I-xIv(FbfVLBx+fohXKaEQ7jaB1SQ#N*Q^gtXg?gJw9Enhay9@o z@1mHupyJkG@+IAfIUTG7=u(DhRe)ix#6 zt5Ch@GX;kV%oF6uc>!fK&zHcKpyH1rTkQb^QP2J##<|FPL0u^wNy1Cggm`&gB2?BG zFYyk&U`~Df(PNN3ke6vw8T!eBN9!ah!=;MXnIaay2MI; zn;;Meh`Ot}i=iQ)CKQ5Ns4=M^lS@h&RKZ)ynH$rfw9suSHI&#BK1ipA|qw09D5Hdq^SoK z_W7Ui@=@?xzzL;H>%GHKYOoTUnmnwp?yx<;T70bOKxlWKq#&*gYwOF@ijm58h(J%F zcVh1C_#j!ML|mo_3O@Kczcbq_>^A5J084*?%)ZU>9`~~^4#@7kd7{aN&RndZ%hvb} zruzyx|A2c`>J^>)^8rY_%b4O*dxe--bcp<+4vS>VJ9hyoaU1E;QcGyp-kXR4U1f+` z8`Qci*rveDM&T95pMD((dFx-8SNo`P@X+*lG_PcQ zmVmPQ$+i!@vGi%ZrnBu(%`nsY3BBXNCs}P%AP-ae$HV9(vvg#{ZzZ&`82k|Tc!d2- zE5Bb<{_O!+Bl~o|99Z2C9)G6pBam?=TZO^yeN>8muVMuJbdxSg{MwI44r!e`aQu6i zz@Y&U*;@Fd2%8~aYYCo$fR>j6{l9Ae76hs>V!kIg#j586(I?IZzfOM9^6D(W3d=Y! z1u|e0?l2B1>|C)q+1#v0;cAZMC7T^nR-LUK72$({@e(8D1O4_;+BUmOna1eFTUt4H z-r*V^L?-nh2E%Uux@P$OqnoAZ3Vc1%$RE}|74}``5wGN;P>J&>CK-v%gbIR>5Q^|l z6uL`8#Lv6S8_f*-gads#n`b;8@b|`sp`rJre^eO_xF#bB@>7ejENLEp(efMFNbD$a z0_5sCZ?l_HO!nGu&jb5DM2Bn_2Leu9nr`!z4J$dd&?T%bM*E3j{H!}Ene`p-A~QO8 zacjIRrBZFIoWXqojF<%%)qs~Q645i;w(uV?AjAf^ZHJvdK|>^d%JH0g;$TNPg{0hu znZ)QjxwyDIc{j1Kyl^HRu7CvcuD`l*qWe)8@W8hsJdYZAI=M2xUE~@HmM0a$3{#V< zNIk?&j_FW{I@bGawb)5(^B&vh_glu7=ZcX%ugzR4{a_swL@mO=z~0~{&sC}d+6nXW z`IN1^K7YclG0zjE>tkdxR2vpWHPAd40#Dq(e+FG4CqX^!29D8oK6Fm%X>&tQt*vuD znmKxTT8|vjhFjTlC$XEjkCL;`VjPG1?x6bFYzE;KTodr~NH+&nlzVbcn?fUyr_b}50`_svcv`4Y>Xi(IFyeOfjd#o{dus3kSX_u7s%<{E=2Fb z{F3<$J{MsD@>b|Af(MB*SqCY#_;CAC^7MlZOc5ym`rl{8Z6StHo01o}5-iN98%^_} zp)!b2V~;UmhnoAfOR!XgU*?CRi=*(7l_LMmkNguApSbkxD85#8{7xUQytQ?y0`6>F zg7upKhv)XsR0he#HejmS#RnC7ruS_dxjp8e4ocvkVf-h8cb2w#1)?)Eff4tCglpuS zRB5l@U-i~t`Q0J^7I~YUiPSsRQHAu_Ya}2Lk#N4Gu(pT z&dWRtk8Ccqj|sRE#(z-{PegSfUJd2rogPJ;{HE-FtmnHJdT2XS?kbTccjKE^)oGYF z4Vv+eK0zK33yeww0}B5<_CFC2^>>J;&xJpo?HKFuuil3|9+CltJZR;5Kb!}@I@Tt?326_($<6S0lEHl!grL&WMad5rsMaP4}+ca5_HtA6YY?aL*qG9ho2!g+uaz z@@zy(c*$jApCb&tbq|jE4E?K*NKrJ5Cm!^oIL&%uniIdAEMc*pIkDximwC0}h#y() zOyk_nz80qTqnUb2z#XhQmwC@yM$eaTUcPqpH&>n5e$hY`Nx@Ihs93m3KwNBC9QZXs z9=|o9u9_MC=QgN{Vm=$*q$A%vy8L0F{!5Ky{#*?s{Ji(ke=`*xYVjgU7;!AvWM=yo zNVE(%qz+^rf~t`l%$$ekuhQD9k8%<px14ZzQ;wb`XKUg6ySn0o!%U6=b+$HIEA zDX9hW<^X(}Eb-R>@&yT6&6&}~&#}}5=d?Idm<}j1#?^esrBU!|qM%mBJ)doFUcNjt zvZ-&WcevMn-6j;v1`FZC1_iLM)qf(_yf$G=oPZOG#ZM|;D>x*VEfirv!tzrP%XVIp z`j*mW#2!D?G$YGy!fanr}Zw)f5R{5Zm7*F z-3udrV)_t9-#U8UsUmJyU+$`tYYrNT>sB>mr0$O#N2`p7Y@T-OTrjlwGP^&Y5B|wf z4>XM}ovdR7)^>E-ui%9tu1P!@-@qjd#?y_aG3Yc$gJT344h|_o2VAWy4K9)(3(T{s z35%(f%T4%?)8|w%9JyQ;Ewk%pJ+@b0tZe9{5*L##xB`G$x+y%t{L`+0FS95o-_cf4E_5ou5=28$yo2c@*P3t`m^z5WBC0 zYQ1W*_O78Vb{XeUorWZQLsTQQXl*Q&fYmkkq8~U9k&`IlS^q*Eb+orM0f|UK3Vk@C z$lfjJQOBCpFTz&kHuGpR?7mfx?%Sx1X06A4qCn#r#{EZ881?qJIcWeLSg?*imV{5d z+*SHBcO5?x*QIL8DA@nzC9lj)A1rAWQ#b&(Tnv4W0-QKl` z^}=evek_n5yq$Y*UtCDleIA`PcRLu*qcg%;&->>g8 zUzIyzZm{sQqdvvHniG@h_GQH9Xq}enKK|#YbS`q)f-5#43(dLh;Q@D{*{O`Q##)^w zQUa|YkAx~p7+N({_X(f<*|>@gyxur3bRpImuz|XXA6Zu=P`0_0*skf;8KMF+?^WmF z&@`Cm-8{A$!FPj2lgIvis#)YZL>Zs+?R;V*k%J-xluk9Im9Q}d#g&0mVTXcNK{n8T3OjGLbuQPdP(+rLF5cvZGBPvVb0@EH`7z4}`|4Y`Mz4DWkrZg}e4 zlh5~VHqF~RvCMPS(0@7zQ$&~_$B+V#+e$VQkRZ{%;M`N-Cl zz;Qmqy?YOn@Dww~+x3)wu$;`i6}V)x*;UIfR_?Zdr#f(gr^B3$8FAe$wRrRa{(+Yb z*Ce@mMI35eycU2p3vhT7^9F2x?JoFKbY@ox=5h=W0p!yW!1k5r@S*cnfN8B-%S8U$+DOe&ypSPx0y`P+Xf+2P?qu)yTBO-!j#&6cumgx;$N6&_c3 z^~IL~zilFEr&6oLGy$r{z(wmQ+{CGnfzk4GHZ@zd6T;RqD8Dju4aHIBUtFJ;tt9Hb zHhN}WZwB7`weq;|i6OV)E4_Y&<=GJXuu3E($+@H?+rCv)xOJkA#N{2HzrB;6vD_}a z)+<@-pTwYtM(y@)_V)U$&igZi;wt=F!z}NcHurj^4{{{cGYs}r`KESRd%iLN&;e?} ztd@QIZc*IwUrG)z+jS~~+Uivd^YdsFQ{<6n5w+#TP3#}A#6 zzVYT?&j+C};zzdWDQ$RM*bf-C4+epi?+^q_;gJ3bo0zy{8=!2q?d(K?zV_om-icRA zPy~6hRkic8cMFvt!OpMPE?L4=7nrp|YTzg}rE9`nDXG^(l zZE5+xj05%iFhj=J0}b6fB0|64v0Er^8z0)d(y@&x@vf*sq3TrlQqF&jd-Q`1VP4Mx_{Tn z+xvs_woFnUxL{J_zn@`p9p$Be|K6_>o3|}*03OD@8nFE7cl_Xv*)OIP7a?^mUmN|4 z*?yFehY$rYrx37V!M-U#4j6O#2S!QUF?@nh=$_guzdw5xwG7Q2DeopKm$K%&>dE_3 zN(#*dFNz+KJAXCQEIY~VU9V-C zjR3NrSMk8s!0Ho84IP4KsrIQy^Zs!@wZ_#Dk?%8GU3dz8O783Oy{T}a*w0}Dn&mg! zF0=a;e)q=>nV&&D5=U9O(sv$1vpA8Ry{GZdpO}pL>S@MQ_HOgEuo#M@Z~-^e7X@LV z`eLYRs=0=n3v_6srG&cGC291xP0aaKRl3nIb-WgayVrur{yjc^=RJ`Uymv52j^thD z5W;_>gf}s^48rI>asZ;RdMs>njy#JfS#-c;f^lxbS_Rz}k}f_|s!pz-(QOD-URZeT76s5`dc)zJ2xNgg$&tA zj%WJ;Blr}@I$vv9xNs8;uRh+$GOjPZ-5yG;xXDSZD6As!w8yGIQkyeq?_zzD_P}HT z3(s#|zwupZRQwdFqVPT%&{jtS7rIeUH)gJddhtj2A!hP8XhLhp@#Pk);FmSuyicq- zmY1XI`zI^@fc70PMQ^XgCo#q6kl@!5e6advICFHmXkAK+egW8xX5Wm5|W# zGv!%xC7zosbQUBu`Sa;gu79wyzcD=bN;5cXeMu+5R(25YX!x7%B%dMTN;TqsXXFJY|F1&|1{aucB4HEzDt=yS z)o>I;W2{W*oeh9MeEW`AD_xw&X&>19>)n&N_!#%@c82Y3G|$Ssp7SHKM6635fm$sb)i)5D>QB{#+AToL|$=YwAa zuUtN-ra>{kmtt5J^B*IR1a5o-owk>LZx}5ErGfXk7mf@|$=)Zgk>x%X5}Y4R!Ozgl z&+k+L=6rO~TJ}$&+{s7}TAWG@pVASRQF2FYZJ@4^2SIWS7(1_+32u*8hL%1ctIRs1DCxD8ctyin!Pw+xu@MHA@qqB>eN!n%SqWFzPrALFYw0bgJWJfmYu`9DC6OX_nMz zLhyPnAd4WVu~z~|b+K=#V*#CV5zxkf{V3>0n9X~0EVHTOFHCk_3D(#H5O@%$0^-M5 z(;mzQH;oxz|F7p!pUd0y=`mYd*T>J>yP^$i=;S72w1l=}I=n<@GtBf%VDw98)sXpS ztzn1#;L)A(yXcuLOV#?vNPpbINwjfsdq!_8?N8{D3+kcc`Xca*)p8iot`FVG4N%CWAu1(o5+)c{91$|mqCXjK=@Co2ewwU`taalI=n)zz>(AGNiCv!$$*DP0}zyQ)>cv3x%Z~E zQxc5S^sIu;10@JyeL|Ck*fP$?-t}FR^r~M=-A1~<;JYNWPIay_w^;RCZpVP4NxCAL zJ*qjIzHr}GyfIjCG-h_XwSKs4MX2YZTA^-^YCxegu|QM){ds6?>Zm20uivVzu)?gz>oOsByV0)mpdA!Tq%8mXc!z*owNx*{pwnVdT45C+&49{ z@8L0Ub;(7LU=zFJ$@W`^@;Q?i|l7+Nn*FGxpwrmJIh%On8Yg1EmcXu}Gl(c@x(jLp9eAPN{Np zeES**9+gMzxrWT;@J-C}vl?)lC06rKkU<(5?AzJB-(q=pc)df(ExC`yTFK}x8?;@y zL({=f#{Wt)`sR=8ouGo-BTZ;{0rj^teSS-+c%<=3@4js`5Hx(XW3yoX~i<|5lA zAH{oMdZ6U`B1S<3hUc}XCiIK(KUYAnX|2pa4d4T{6CM9uhCS>R5Egv`onz_2kjFTl zX#9^gGf6NaZ(&^I#x7=bhnD}bujFG8*o&c8zgxWJ6D^ugpOFGP5Qn9z8CA5WwRl0J zkMkH2Aae2FM=w6ydt@`e4Q~RboCc2ZZUfewgyS73Rs%r--|*globXn@xZ{eaIO4ZN z9eMhuKF5hi?m53{MS51V&C42gTP*_EGr+I4)idakjp9po3w+NJtfrLi z`Pa?YR-sXBCYg<^P_7`J?O>&)^3(ey^0v%7!H|w+v9VYrulN&m~uYywNwjDV^h&SJ%zg?%+ zF^X6S-@(HV@dnU)*ta)tn+~5~)6A48&{nbJgustSVL6uNgJyW<{=Di7PWcq({EEks z%tctzHExJ8FJw;*dpOBaoUv{G&2ez>$@ho0kH=}ZZbjE@l%L(*oo`eTI@qQ7p>EUs z4s(36my^OC*Zpfu(2aTw%>L^Ze?KWvLq8{M5DD{~KbZdcwy$<&S+)EzyDBKpl{r0X zGSoU80kgEut>iP9xlkU_9)wUkHu`^xcjOIYxy<|0 z&$8cc^bxaDEPFh;z{N8F+x{zlU`>O?y8rL7I}2hnDE;Im*>+mH33CtEKJa|{3+)OP zLyp9?k@YQ-e|0!-Ub!<9G>7Fv6Z07JaxW+IG=NpTMP`ocUA1>Oq3kLVAJ)>$308K3 zHdQZ&{E5^TkL$poc|=vw9`h+Ur>~Fs;6aZYG;?^QAHc6B;-Eb$+FxST&;SG^d#Aum zXzU*Jh6TJQy=WDDk#eJc9ODfP!4(b|dEidaivw;uc-9wF@B7hf`ClF^U{?6ut4x0F zrNna)I2^eND@stY_{n0N3q;ys8!)$#3mI@qk-L9%M9OPGYWNxj-5ObD)dX9!CS&+nf{v?Xk@k&<~FWcgo<=gyNbev$qqDzJ?CI|EznB&~8_ ze9&SAp8sTgxL-vTRiD-VfH!k}2%|im|w=ja|koSN98Zfmy z+&(@TA?U*viZew+C!$c0)Q6bXI|MPcl%{ZK&2T*Jd=qs=2sqJeh4R-`WfKtFItA?z zfT*o#Qs1%yTKTl6LpOe8BjqKYkH#q9e@3ne?4V}L$Y-niGG%?>SqHwmSD?Yw=R`R3 z=U&`eemUKdz#?%{1GvQoOlSgHazHwq6#=v1blSbFi%o}{d>HWbeINE8rRvl1ZgZc6 zV>zUb1o(*VpQXd8oGjni5eR4c2En_{XJSu;+Z7gZO=1xKZP(8(U#)|kxWR*ZNBz5g z>OP=u*fj~MC_qmK47 z4=iRFZH-$n^80pDbT3N?gCrhNfVa`V)dqMWAyEa$-q)qvxC&J+gA9Zp{0IIYkv(b| z5=yW7Q1WyM{u~~^LwKnKR05Tl0vMyEbcLn*V(qO5ZbYs_5l=B$&mFoqQ(6~es(qfJ5?BpqrMxtq& zPZ$R>NYKLis1@~oGQa1SNwYH+^DF4*b3oVyppVz?n$HTsV5G9ZJtvgS*b1x&`Uz>|aPlcOc)K=I`A31$aqGeZTDfU+3fIl2|j z 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 diff --git a/osu.Desktop/lazer.ico b/osu.Desktop/lazer.ico index 5051c00ffc79eceac173442cd0466750d8e3aaa6..f84866b8e93b4c7a449371b71a99b1a8c5567df1 100644 GIT binary patch literal 67391 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 `fTbt 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 From 33738b5285bbf8d78182c2b33d908b1928607d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 26 Jan 2024 19:02:44 +0100 Subject: [PATCH 120/915] Update android icons --- osu.Android/AndroidManifest.xml | 6 +- .../drawable/ic_launcher_background.xml | 618 ++++++++++++++++++ osu.Android/Resources/drawable/lazer.png | Bin 39318 -> 0 bytes osu.Android/Resources/drawable/monochrome.xml | 24 + .../mipmap-anydpi-v26/ic_launcher.xml | 6 + .../Resources/mipmap-hdpi/ic_launcher.png | Bin 0 -> 6403 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 7232 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3582 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 4040 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 9537 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 11248 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 16409 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 21398 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 25006 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 35444 bytes 15 files changed, 653 insertions(+), 1 deletion(-) create mode 100644 osu.Android/Resources/drawable/ic_launcher_background.xml delete mode 100644 osu.Android/Resources/drawable/lazer.png create mode 100644 osu.Android/Resources/drawable/monochrome.xml create mode 100644 osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 osu.Android/Resources/mipmap-hdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-mdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-xhdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-xxhdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 osu.Android/Resources/mipmap-xxxhdpi/ic_launcher.png create mode 100644 osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png diff --git a/osu.Android/AndroidManifest.xml b/osu.Android/AndroidManifest.xml index 492d48542e..a2b55257cb 100644 --- a/osu.Android/AndroidManifest.xml +++ b/osu.Android/AndroidManifest.xml @@ -1,7 +1,11 @@  - + diff --git a/osu.Android/Resources/drawable/ic_launcher_background.xml b/osu.Android/Resources/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000..1af30228ec --- /dev/null +++ b/osu.Android/Resources/drawable/ic_launcher_background.xml @@ -0,0 +1,618 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osu.Android/Resources/drawable/lazer.png b/osu.Android/Resources/drawable/lazer.png deleted file mode 100644 index fc7aa8a092cb616233bc83a3328413740bb57953..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39318 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 + + + + + + + diff --git a/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..7133c9c861 --- /dev/null +++ b/osu.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Android/Resources/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7870430484b7a5d9433afea0af2fe479ac0e967c GIT binary patch literal 6403 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 Rc+vm>002ovPDHLkV1m2~j8Omp literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..b2ec3e49da191d5840d72a7ae2e5421dd468fecf GIT binary patch literal 7232 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 Ef^`evu>b%7 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..e22f2565625261d8ad104f2d09c70ffccb5d2ee8 GIT binary patch literal 4040 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 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png b/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b5e1a9e3798869f72105dec0643dfe18e8634a54 GIT binary patch literal 9537 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�>IX}``GPV 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 literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..1cc3fa9072d0bddb5511ec97d47bd80a7513c78a GIT binary patch literal 11248 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 JIpTig{{TBU2Ppsm literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher.png b/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..65751e15c9432447c18a4af6a03ec970ad82c945 GIT binary patch literal 25006 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 E0Sm8>N&o-= literal 0 HcmV?d00001 diff --git a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..05c6829a47625e8c647bcd3141594d1d5cea7b3a GIT binary patch literal 35444 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 Wm9}oz-ruXr00f?{elF{r5}E)w6xqZ8 literal 0 HcmV?d00001 From 2ccd0e3692d66b9b1dcf29daa666a09a459d2fde Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 27 Jan 2024 01:45:22 +0300 Subject: [PATCH 121/915] Add visual and failing test cases --- .../Visual/Ranking/TestSceneResultsScreen.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index 866e20d063..dbbfac75f7 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -26,8 +26,10 @@ using osu.Game.Scoring; using osu.Game.Screens; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; +using osu.Game.Screens.Ranking.Expanded.Accuracy; using osu.Game.Screens.Ranking.Expanded.Statistics; using osu.Game.Screens.Ranking.Statistics; +using osu.Game.Skinning; using osu.Game.Tests.Resources; using osuTK; using osuTK.Input; @@ -44,6 +46,9 @@ namespace osu.Game.Tests.Visual.Ranking [Resolved] private RealmAccess realm { get; set; } + [Resolved] + private SkinManager skins { get; set; } + protected override void LoadComplete() { base.LoadComplete(); @@ -59,6 +64,9 @@ namespace osu.Game.Tests.Visual.Ranking }); } + [SetUp] + public void SetUp() => Schedule(() => skins.CurrentSkinInfo.SetDefault()); + [Test] public void TestScaling() { @@ -132,6 +140,46 @@ namespace osu.Game.Tests.Visual.Ranking AddAssert("retry overlay present", () => screen.RetryOverlay != null); } + [Test] + public void TestResultsWithFailingRank() + { + TestResultsScreen screen = null; + + loadResultsScreen(() => + { + var score = TestResources.CreateTestScoreInfo(); + + score.OnlineID = onlineScoreID++; + score.HitEvents = TestSceneStatisticsPanel.CreatePositionDistributedHitEvents(); + score.Rank = ScoreRank.F; + return screen = createResultsScreen(score); + }); + AddUntilStep("wait for loaded", () => screen.IsLoaded); + AddAssert("retry overlay present", () => screen.RetryOverlay != null); + AddAssert("no badges displayed", () => this.ChildrenOfType().All(b => !b.IsPresent)); + } + + [Test] + public void TestResultsWithFailingRankOnLegacySkin() + { + TestResultsScreen screen = null; + + AddStep("set legacy skin", () => skins.CurrentSkinInfo.Value = skins.DefaultClassicSkin.SkinInfo); + + loadResultsScreen(() => + { + var score = TestResources.CreateTestScoreInfo(); + + score.OnlineID = onlineScoreID++; + score.HitEvents = TestSceneStatisticsPanel.CreatePositionDistributedHitEvents(); + score.Rank = ScoreRank.F; + return screen = createResultsScreen(score); + }); + AddUntilStep("wait for loaded", () => screen.IsLoaded); + AddAssert("retry overlay present", () => screen.RetryOverlay != null); + AddAssert("no badges displayed", () => this.ChildrenOfType().All(b => !b.IsPresent)); + } + [Test] public void TestShowHideStatisticsViaOutsideClick() { From 47f0b860186c720619b24df1ab0581bafb80b1a1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 27 Jan 2024 01:46:12 +0300 Subject: [PATCH 122/915] Fix results screen showing other rank badges on F rank --- .../Expanded/Accuracy/AccuracyCircle.cs | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 0aff98df2b..8cec79ad90 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -351,24 +351,28 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy int badgeNum = 0; - foreach (var badge in badges) + if (score.Rank != ScoreRank.F) { - if (badge.Accuracy > score.Accuracy) - continue; - - using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(accuracyX - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION)) + foreach (var badge in badges) { - badge.Appear(); + if (badge.Accuracy > score.Accuracy) + continue; - if (withFlair) + using (BeginDelayedSequence( + inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(accuracyX - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION)) { - Schedule(() => - { - var dink = badgeNum < badges.Count - 1 ? badgeTickSound : badgeMaxSound; + badge.Appear(); - dink.FrequencyTo(1 + badgeNum++ * 0.05); - dink.Play(); - }); + if (withFlair) + { + Schedule(() => + { + var dink = badgeNum < badges.Count - 1 ? badgeTickSound : badgeMaxSound; + + dink.FrequencyTo(1 + badgeNum++ * 0.05); + dink.Play(); + }); + } } } } From d25262944ecd3a6a2d595b7ffc65c9cbb058e1f6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 27 Jan 2024 01:46:43 +0300 Subject: [PATCH 123/915] Force results screen to play default D rank applause sound on fail (regardless of skin) --- .../Expanded/Accuracy/AccuracyCircle.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 8cec79ad90..60c35e6203 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -10,6 +10,7 @@ using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -98,6 +99,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy private PoolableSkinnableSample swooshUpSound; private PoolableSkinnableSample rankImpactSound; private PoolableSkinnableSample rankApplauseSound; + private DrawableSample rankFailSound; private readonly Bindable tickPlaybackRate = new Bindable(); @@ -133,7 +135,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy } [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { InternalChildren = new Drawable[] { @@ -267,6 +269,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy badgeTickSound = new PoolableSkinnableSample(new SampleInfo(@"Results/badge-dink")), badgeMaxSound = new PoolableSkinnableSample(new SampleInfo(@"Results/badge-dink-max")), swooshUpSound = new PoolableSkinnableSample(new SampleInfo(@"Results/swoosh-up")), + rankFailSound = new DrawableSample(audio.Samples.Get(results_applause_d_sound)), }); } } @@ -396,8 +399,16 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { Schedule(() => { - rankApplauseSound.VolumeTo(applause_volume); - rankApplauseSound.Play(); + if (score.Rank != ScoreRank.F) + { + rankApplauseSound.VolumeTo(applause_volume); + rankApplauseSound.Play(); + } + else + { + rankFailSound.VolumeTo(applause_volume); + rankFailSound.Play(); + } }); } } @@ -440,6 +451,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy } } + private const string results_applause_d_sound = @"Results/applause-d"; + private string applauseSampleName { get @@ -448,7 +461,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { default: case ScoreRank.D: - return @"Results/applause-d"; + return results_applause_d_sound; case ScoreRank.C: return @"Results/applause-c"; From bb6c7a0a82f7a19da7445706698c67360968301d Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 26 Jan 2024 15:26:22 -0800 Subject: [PATCH 124/915] Fix edit mod preset popover buttons overflowing on some languages --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 8bce57c96a..9554ba8ce2 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Mods { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Direction = FillDirection.Horizontal, + RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(7), Children = new Drawable[] From 567d2bedbf928ab4260fd7fa90b48ac906e8d109 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 27 Jan 2024 03:03:01 +0300 Subject: [PATCH 125/915] Refactor ArgonSongProgress for same CurrentTime meaning --- .../Screens/Play/HUD/ArgonSongProgress.cs | 8 ++--- .../Screens/Play/HUD/ArgonSongProgressBar.cs | 36 ++++++------------- .../Screens/Play/HUD/DefaultSongProgress.cs | 6 +--- 3 files changed, 14 insertions(+), 36 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index cb38854bca..a0e74dd6cd 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -114,12 +114,8 @@ namespace osu.Game.Screens.Play.HUD protected override void UpdateProgress(double progress, bool isIntro) { - bar.TrackTime = GameplayClock.CurrentTime; - - if (isIntro) - bar.CurrentTime = 0; - else - bar.CurrentTime = FrameStableClock.CurrentTime; + bar.CurrentTime = GameplayClock.CurrentTime; + bar.Progress = isIntro ? 0 : progress; } } } diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 5fe3b97f15..196d8ca278 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -22,16 +22,16 @@ namespace osu.Game.Screens.Play.HUD private readonly float barHeight; private readonly RoundedBar playfieldBar; - private readonly RoundedBar catchupBar; + private readonly RoundedBar audioBar; private readonly Box background; private readonly ColourInfo mainColour; private ColourInfo catchUpColour; - public double TrackTime { private get; set; } + public double Progress { get; set; } - private double length => EndTime - StartTime; + private double trackTime => (EndTime - StartTime) * Progress; public ArgonSongProgressBar(float barHeight) { @@ -49,13 +49,12 @@ namespace osu.Game.Screens.Play.HUD Alpha = 0, Colour = OsuColour.Gray(0.2f), }, - catchupBar = new RoundedBar + audioBar = new RoundedBar { Name = "Audio bar", Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, CornerRadius = 5, - AlwaysPresent = true, RelativeSizeAxes = Axes.Both }, playfieldBar = new RoundedBar @@ -70,17 +69,6 @@ namespace osu.Game.Screens.Play.HUD }; } - private float normalizedReference - { - get - { - if (EndTime - StartTime == 0) - return 1; - - return (float)((TrackTime - StartTime) / length); - } - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -113,26 +101,24 @@ namespace osu.Game.Screens.Play.HUD { base.Update(); - playfieldBar.Length = (float)Interpolation.Lerp(playfieldBar.Length, NormalizedValue, Math.Clamp(Time.Elapsed / 40, 0, 1)); - catchupBar.Length = (float)Interpolation.Lerp(catchupBar.Length, normalizedReference, Math.Clamp(Time.Elapsed / 40, 0, 1)); + playfieldBar.Length = (float)Interpolation.Lerp(playfieldBar.Length, Progress, Math.Clamp(Time.Elapsed / 40, 0, 1)); + audioBar.Length = (float)Interpolation.Lerp(audioBar.Length, NormalizedValue, Math.Clamp(Time.Elapsed / 40, 0, 1)); - if (TrackTime < CurrentTime) - ChangeChildDepth(catchupBar, -1); + if (trackTime > CurrentTime) + ChangeChildDepth(audioBar, -1); else - ChangeChildDepth(catchupBar, 0); + ChangeChildDepth(audioBar, 0); - float timeDelta = (float)(Math.Abs(CurrentTime - TrackTime)); + float timeDelta = (float)Math.Abs(CurrentTime - trackTime); const float colour_transition_threshold = 20000; - catchupBar.AccentColour = Interpolation.ValueAt( + audioBar.AccentColour = Interpolation.ValueAt( Math.Min(timeDelta, colour_transition_threshold), mainColour, catchUpColour, 0, colour_transition_threshold, Easing.OutQuint); - - catchupBar.Alpha = Math.Max(1, catchupBar.Length); } private partial class RoundedBar : Container diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs index 48809796f3..be310df3a9 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs @@ -99,11 +99,7 @@ namespace osu.Game.Screens.Play.HUD protected override void UpdateProgress(double progress, bool isIntro) { bar.CurrentTime = GameplayClock.CurrentTime; - - if (isIntro) - graph.Progress = 0; - else - graph.Progress = (int)(graph.ColumnCount * progress); + graph.Progress = isIntro ? 0 : (int)(graph.ColumnCount * progress); } protected override void Update() From 3387565ba934acf70c6276c675c7c506e0b08d9a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 27 Jan 2024 03:11:12 +0300 Subject: [PATCH 126/915] Fix song progress value may go beyond 1 --- osu.Game/Screens/Play/HUD/SongProgress.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/SongProgress.cs b/osu.Game/Screens/Play/HUD/SongProgress.cs index 4391193df8..962752ba5a 100644 --- a/osu.Game/Screens/Play/HUD/SongProgress.cs +++ b/osu.Game/Screens/Play/HUD/SongProgress.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 osu.Framework.Allocation; using osu.Framework.Bindables; @@ -96,7 +97,7 @@ namespace osu.Game.Screens.Play.HUD if (objects == null) return; - double currentTime = FrameStableClock.CurrentTime; + double currentTime = Math.Min(FrameStableClock.CurrentTime, LastHitTime); bool isInIntro = currentTime < FirstHitTime; From 96dba035134cae64d86a602236a36c7d60cfaade Mon Sep 17 00:00:00 2001 From: aychar <58487401+hrfarmer@users.noreply.github.com> Date: Sat, 27 Jan 2024 00:06:01 -0600 Subject: [PATCH 127/915] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d5dc0723af..d7e710f392 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ A few resources are available as starting points to getting involved and underst - Detailed release changelogs are available on the [official osu! site](https://osu.ppy.sh/home/changelog/lazer). - You can learn more about our approach to [project management](https://github.com/ppy/osu/wiki/Project-management). -- Track our current efforts [towards full "ranked play" support](https://github.com/orgs/ppy/projects/13?query=is%3Aopen+sort%3Aupdated-desc). +- Track our current efforts [towards improving the game](https://github.com/orgs/ppy/projects/7/views/6). ## Running osu! From 71dd8e2729a6e0f3d44606cf1d0d5622e030c71d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 27 Jan 2024 19:16:54 +0900 Subject: [PATCH 128/915] Update iOS icons --- ...80-5cbe0121-ed68-414f-9ddc-dd993ac97e62.png | Bin 0 -> 278451 bytes .../AppIcon.appiconset/Contents.json | 15 ++++++++++++++- .../AppIcon.appiconset/iOSAppStore.png | Bin 350640 -> 0 bytes .../AppIcon.appiconset/iPadApp1x.png | Bin 10106 -> 0 bytes .../AppIcon.appiconset/iPadApp2x.png | Bin 24966 -> 0 bytes .../AppIcon.appiconset/iPadNotification1x.png | Bin 2227 -> 0 bytes .../AppIcon.appiconset/iPadNotification2x.png | Bin 4485 -> 0 bytes .../AppIcon.appiconset/iPadProApp2x.png | Bin 28089 -> 0 bytes .../AppIcon.appiconset/iPadSettings1x.png | Bin 3192 -> 0 bytes .../AppIcon.appiconset/iPadSettings2x.png | Bin 7156 -> 0 bytes .../AppIcon.appiconset/iPadSpotlight1x.png | Bin 4485 -> 0 bytes .../AppIcon.appiconset/iPadSpotlight2x.png | Bin 10768 -> 0 bytes .../AppIcon.appiconset/iPhoneApp2x.png | Bin 18204 -> 0 bytes .../AppIcon.appiconset/iPhoneApp3x.png | Bin 30946 -> 0 bytes .../iPhoneNotification2x.png | Bin 4485 -> 0 bytes .../iPhoneNotification3x.png | Bin 7458 -> 0 bytes .../AppIcon.appiconset/iPhoneSettings2x.png | Bin 7156 -> 0 bytes .../AppIcon.appiconset/iPhoneSettings3x.png | Bin 12085 -> 0 bytes .../AppIcon.appiconset/iPhoneSpotlight2x.png | Bin 10768 -> 0 bytes .../AppIcon.appiconset/iPhoneSpotlight3x.png | Bin 18204 -> 0 bytes osu.iOS/iTunesArtwork | Bin 142214 -> 0 bytes osu.iOS/iTunesArtwork@2x | Bin 350640 -> 0 bytes 22 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/300076680-5cbe0121-ed68-414f-9ddc-dd993ac97e62.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iOSAppStore.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp1x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight1x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings3x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png delete mode 100644 osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight3x.png delete mode 100644 osu.iOS/iTunesArtwork delete mode 100644 osu.iOS/iTunesArtwork@2x diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/300076680-5cbe0121-ed68-414f-9ddc-dd993ac97e62.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/300076680-5cbe0121-ed68-414f-9ddc-dd993ac97e62.png new file mode 100644 index 0000000000000000000000000000000000000000..21f5f0f3a0901ed465ec468164bce1817fb4ea22 GIT binary patch literal 278451 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

b;UQhmR-aO6N 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�k+(fIDq7qxZKK zx!+vlQIWW=8XN`}>!6cz+Ch$K>sykMy6XCYPhZHXfVceD^90_><~0>+|nE5Px~!@P4Bg>?h1;c&F91;*3)pddrSz4l*6Un!2e1aS9*3u#)@Bp$sz})Pdj(GL#(+(1 zX4qic?Z(t-cz&d(8tqvy-|>qKH45XqAAL7_4pEl})%7|VNd|*80tHZI{#pL$zO2}h zrwc+-RLn9|o~_;ujX`tnJ~Ml6wrah;H!dPfH5mUFF*RyUP6k_$n_);ox7lt4?2Bes zJKRG9_PhcjBb4dyEc{sm82CF@KfMVG*mSN7jY3ox76H1^9H=bc3>KP3Up>(vAagt`fwW4%b z6-1G+jNEgVz4Db!tv?bL^v2C{5pj z6;U0ReWd2(Y=h~#ad^yK1I^-XxBRoZV3;m{XLhJ2Xr0i?q#3Uhj?xnd* zC9In2-cGv~xa|e}d%?+%wAVlfbG7@(w#FsPPO*76qCHQR=So-vt~;U$_)cs`is+!} z&n5K!+Eqe@YNQCtK6w+$p89W?1L`&jOtHf0lIf*e2>`w z#c8}wZbhYc5dp(L;SMPeF`v-5?=}|AERdLLQz_-ATD=Urb9xyd zVxU-5jBdqQzzylLKDgl{WaAoR5p>5XiR#pxT|sR~mwMzK$p0+rqXVbe8Fy|_(P?Bf z(<$pEn-K7%I6GDcB?>$@V(C(?bTO;GEY%&XKbD@f)(!Sh(9R+ukE*ew4D^Q(4t>da z)AM9r*R*iP+v6++LAs_ZVP5PFvk%occ^TOtE`-@XGxJ1!exWHC^PZ8SYK3qaW2I)} zcqE-T@g)_ zdxE&|TTQKLBcslIsoC=Zc#8okt*R~{`rEjh~JD^rbRtCI9( zjP!fCSLSF+&wRnU4QyJXuzapajj_sC7pS!*0Br_-jP4&D#ksO-`oH07Hbo68eM(q_ z502)9JsD7reTD+z1E3hUr51NA)YOs}OBwql7AVy0()W}Se$D+U-9LZXe+#)JQVh9; zO6ctfRy+|knP6GSJouwfuxMMr%BS~4RfUN2yS%(v-by-UVX9hme(|q|Se4hDK}A|` zMx@xmb$Krtj8J3e zm0tT6u6bZSHjI8u@KXP;tGSfmcY}u*|G!fmy3T7l4N+C+OM0VIVuN3a{&D)=b^8ue zzJpEDwl;~W94N)D|A1|h*J4b^thX=ywtk7;)tueeA~z3C{UfD8G>kL!D{9w{9km8c z3v^v3yr;Zqg*u5Zy1$PTX%sX%cbdFt-JFAN*1mv_vr$9d_Qm~TMAfzsBV5scYP)K8 z7BGCYv+{CX3%&>W{Y{%Drii3I{wAS!<#?98Uj0vE^LE+q2s8hq<#l>4l>Yrc;W;qgUn5l`xCs@wmB2Hj;?LR^yF4=MG{#!ER{l zR)7XRjtzO}fmmPR=1+`i$3G*WM@0h}Dq6Gc%bIW)xRgnQwFv621cdRG% zHza_3*e&3CKskn!{3qMcAn_~;t6-j@a9-FjhFE>Sp32^&P8iX1M(BLh6hRA6)EJR# z<~k*%w$d%`U3qdo^}L^+_tnBcwUCVAXcY45J$^h}jiCl1IxxqR(U8V^=Pm8M*FAr8 zYi}>*Olch?vUdhiD&Hx=^qWeg2RoJ>*6IH-S7wFb%(KkAEs$%l@$ZxxQF$B_-eq~) zs)~Zjsug&9k*!8k=}|vm-{c`%jEWH@F+U{ErLfzmLsy@N^x{A%PrgFQ>rL1+Bj3QG zG{tL@T`7>V2HAt%>o%3XCO99#Jri(Et{FAqDmAL>2VS1yHy#gojvVQIT! z4!?WK9?ykmx7iHZyb-+H8ND}4+ph$$&SrxqTa@~j(b0sF0iozjm5HeEBnniWP+E7C zG>+56b|05v9aan->YSV&(f!$m`ILw=Pw2RHyc3%XwmX$`)|lWQ8==@Ojg;uQkCQH# zTk#6X$k!AgCFQ&_CR7D{c#DBwP;vN3(O*2s(>kb5eT__V2c)$h4mW3ezKpiZMXB{hDapb@8(`B}(%l|M8O>Cs7<|4^{66lb-TOF$SpV?2)lrgQroP!&r^^Fey%=nHgU0!1UBX#pjn`)HiB zmoad1!h3vt9R7U{k!L|}v;4d?Av|ZqYeJ^s>6V+Hx$bnIsj2Dvvq>e}ie^Bj`E6-F zBnRu_>w!ad9xZTfN=~p<-29$ZOc5{(FEQAd#bBP8b3CO5GC=(Bxv(t99l{mPRexax zQpmWR8FEm{6BsSSX?OS#-lm#0k$h|Hmr*`yt^@4a!dK#ZvPK?fcW&S%v9Xu%B_02- zpb}tvZDjqzUNO8-;#1}NyX>#C03W9bP7c-&@48A1Al+VjE>hPComQQ?x{K;G$|hJH z1{2x~o?y8Lx2cu8otO8FwL%-K^Ty{(pG>u4OZdRr1mm$Z!Zl$O$Tz%kC$PC3U%>cFHZNcNzoLz!!aq!UoaE41s^TN6gA#X!7!AI}MV=Qk(S)FvbB9YHSO%dsd_jz}kE(n>ep6W}3$c8V`pJQ@fXB8- z=$1VXF!)FjLC#G89FlFR$XXHh0M*$S(~I8U69DAb{=E6meL_>hOp4#;lXAp||ILSBHV z%F67doUYp-a6bPy!TrXQ*M5jGK__V*PLxxDSeJj|Vb{#)&r7-&FliOKQNl?8i)xV* zmYX<@mE0y{@)7dXvSuScmSn)|T_gU>xYtCk{Kg;I!5812(5YKn>=F`z7-%E3oKi;mP^pbjJ&+YF-(AYs7p zELbcA7w`kU4&;V#p2yVk1IK%ujXgN5Q=j&g)UO3*``1XWaL4QBz=uy$5G4{Q+VY{F zHGA?Ripe5-qDGB@WUYnAXP``rM6bjI(Vm*K(MpKZYb3~p;;o%Xzhuw(eGj+?-0A#Y zqS35zP{p;eT(yx<)A2v$CnqeX=wQ9USr^3zlaVXC=n>5OhXli4)N2xlDf9S{P{lnP8ux% zRVBXxX70|Zi_PQCtkmxu&fmYIDc-7o$;)iUJ<;fU;U>xX=syF- zWtlOwrD%BMhmtaAyf?4wi2c`EOfA7vg=}tuhTK~k$o81)N(RFPo|uw&vmLBItS;C` z4bz|5NnLzCgGZ7`jKl@Lb7tkG0b<~}cdg-dVEKKN*@e6wHGnew05-q#vkfXr98QtW z@xrkrr4OcJOca!9b-YwlM+|oRr}uDEs%L`Dn4M!-C;k@oGye)54|+asnihO4c279B zAu?<7*Z9Y3*3nr2pf(^o)3fP{P3yA3ucYCy^+sKRfI=RwX!S~xbubxwZAsD-sg}1e z6u*jP`6uKL?>j*Lr0Z~2K{A^M_F6;F@onpNjSd)(oJgxIQQ9ywDfWubJoMcw@2}U< z^*uv#5ltoJzT&+OZ~k@j=x;r!599je*d^99AjKy_WBo`zJhDh6P>7%CE=nNwZpJr( zwDfO>uuVIt2vS==!%yYg{#g>l@y6_L{`!Z$9pA#j`;M~*^(DW6k*xj!b+^!`@%LP* zsxc=lql|9{r1fnj=RWJHg| z*7kio#w|Mxy&!oUkbZu|9b_kcU)+K?x;nEWS*x}@&-Xur&R{$z%{&>(?oZYL1onCz zx6T)lhFP*NbS~%o{3PA<5L56hmShdkhCq-di>pw_1yDa_Ba3@YFc6qd{Y zkKL>x37S`Vl&)z)?7AEbXKcS-M@&7|nfFm!cP+N#$~IpAK8hmJ(@rXwMW^j_ED+0?Ju=uakbIC3p}zc9?~&cppe#Ml;Q2VA(J$&oHcxH)u-urj)-tEs9dH z*fN5%O8O8+FF%B;wD8azzSD4}F4J*7N-TEmb_FHR(dH1_c>aY$RfuT5m0ZrH z=)TSNwn0PtEEeK(mg8`~^QJB5(WN3d-osfWs$C{n75rt zH1;_C7qgFl${LjkIu0ZZ-Q0D#&HGt&YF`q=qWyT!4qmX!40x)EEN0pbz9F#09G0L< z|B1){@9F2}DMB^}HMuplo>(P)5gXwT+i~0bz{X$;L+fXH73E6MQ4x0xu6X0~0rce$ z;krP}g+ChyPL~&@=U~PkrD_J1q-3 z93=9~a&sMu{JX(>Q{o}71-~U%=3E6>c~|VPE8rg{H-A3Js1d{>p!4kk&2e#T@7&U@ zz8|yVU>RJ<)7Bm{e1sU4 zGKp4vWrsE^j_I2<5=U~P{FW8WPtsCl{X=FY$v=mS${|FCD2O`bs~yB#ISI(G zjH73IwoqeeC^1xzk-_VdND1^+BP|=ju-Er)`8e*VKzy%^E-5|*&PgSCOF}r1VB}h_ zcT8@<+!6`>LfRp|KZnETK%f=u`EmfjthtbRCA7(uuR*Rl94hlia2^7`*)TPAU z4aXXFJ-U95HTn>RVwWc%$T6W{?8BcTMu;?*ps!*5s9i2BH4YHT#e-5og!zzYKUUvm zp0`vW*L_ZH!CAw^u0xgV#mI~$+5sF=Q9$}LfW)};Hqcz~_79Z!%YpQqVJ|%GET%*C zBQE_nkirWt@3pA0HzY}|7vP@=}>)6AwGgBoYPAx3TbloEkxBzoZxuGe~Z{d|vD zoyS~A1j*sUa5V*L%X@-|XmG6gT`_jpM;XME35 zIUf~rCKM3!(>q~~C|ZD2&COO!Bfmjbi|w5VRkdluuex}h;h~UEGpa#C9v5a4rE_bH z)u1WW^(xF4Huj%VsbT)CRil}3<(x*r)mEb%0yxx z1J0U?G^qc|{PUoS{o1%8-kgD?f6525j1mvM91Y|u5iwAYi!BR$tsEL?r1T0`;-5G6 zB{HswLf@1Khkc8&jOg0uT3T;oW#QV|-^fU>OewTy#0?gZ_qs&n)nvemFm!mL4eRSLrTIiWuvinn1Ji3vHEJi?^EdkGk3K zrq)oDwMEEsSN{!bjP17+465QHdA-!vgw&k=SJf8N3$0BF%>u@)=dWko?DKRJ(mol~ z(WgGY5HfIm8Yvyiad#05n8G}yk^4`zUSOZM5%$ubO6&3GHuPOzg>ao31=j}I5JEGS zV6fZ_hd~t>p`sbMYqR{2beix50M-;@V0U^lt_vvNA9?|l4|%(0xPdFn5<;vuDhZG{ zB%ZWvhjA3T6x5y!e0f(g&~^6XTmFSQl0#-uOJ1c2WB&Z;s~zZAhg?vr875{JeCFL9 zg{CRq<_R^dbbAU52}$P69_Rdzq_gmAy6wXFMoEK6gCL;NAPoWoLAqNSq(neMkY=ES z(jC&>-HkM(6p&Q9n~{UDy+5D#v;W}UcJ6bZb6wv{M5i`@=e4%~{^)nBr8!}>(G7=< z^UGKBH`RWz%}vea9#FP~H0PC6+vu$X2HDIFEO`Byi7ZX5YrH4P1Do1r?kMdDtGvP* zb`p`sC9#iTR`dtI_%T-R2+u>CE@GXx{gpPM{y1Y^Cj@xnUB2|QAxk%9l02=*=36l{ zvkv6WjpRSdoo8Ci-hJ`I)$Y z61U%OqF**7hhS{cuF`A9D|*Y&hWXsu+ry`l$H!(y@7#B{2EyH|aR7(HevOi)gMo#kNgmE4gA}#SvSB65R3LG0O3h_m-t#9`Y zpb4SMfOSdO@ASM)`g3NL_qAhdv5#!tsTJJevkh)}Pwq#xp7%l8kI1zzdfsfs&`NlC z=Q%FxEr#;v6&>G3@0FOsNIfvUM-@1$!kvo})<4e0UH?9qTQ{AN>4i|6-p}Blyx(ZG z5uZ~XwLAnYt7>oOtLX2-yo1)|Kf;Dy-V6#Hi0N+i_!}$`Cqm|wmrnajFJ9|W7dcBN z?665OmvisyWQ`y{jl4+KNvgwwpG?&T#u+env4@TPY$$`T2;sysG$Zr*3RG|?PDi71pK+^vzK6?9LP`lA14UvuKOp=-%VQE8RI7%Xq#89&<~4F zu@rUDw7AWz@awGbg~*!Y|JMi-ULH-2Q1*Jmq>7=blp^UQJeU^Y-Dk2N-Q2#5P{-}8 zASOKb07-Rz?vy~bw^#+@QK3{1p8~ACXAbNr{^N~Y?lI=RqNzn>PNesf;q9<#XMcs4 z&C-w=wmFP5^1d;jI%S83)g&p&d*rTC^l;$gc(u-SV}boMMMdxHmt=bTLj)!0e3!-nfa>`Ba1S& zs{YMrI=S^-gtXJwU8H-i=~I($46!jg;+kwI?0`Me`06IRPz^15@ueF+4IHEu+RMC< zXDXF&4kiA5C7wl6`Mc*Pqwmk1wcFfB=PM!t2nm%~Mv?#8xmV{E!RNCNzEPpH9)7_2 zdcC(7sX#S*hfBgw7g${R*Op`eWDof2&2F}`m31&!LY{pdIcF@wRrgPQ$p$Kqn7~}+ zi}LzxG`YRCvlGlD-Nh(l@fQQ$G$tqQq~e-Wb8I@#&B5E-B~R1zJ$M>bIz%n~h@OO- zq%|#o$HqO#%X?X*tDRg@ys}MY@7>>av8^#3SSd?&mtc%C3US{)S#PGz0$}+8*55Dh z-MW$P^hd=J3?axzjd#3>p2P^LVLG&&#)+8`>X#fR3!2AFWBg8w@SgwCy8EX|UyP&f z8!#;gVEpCuK7yuPcgtxH*%-V?NxOBCblx6^rUcFJ&KKsp+=sm+`0rhayI)T>ke|#Vp4Ta_0uZE}j-pK7FDQMDflrU`Hn< ztXMAKhiF7Ufh*l=#VEnEZtfSndu=_EE2Hw7rmLuJO4w{X(8e`g?@p3h{s=o)jhURJeWJD4 zU5NE|2_{)|7V2F7dP{=VuO-Vz*gLF2)T6V|`eLiLgo~$ll5{g0ypS}m2IuLTzQH0~ zxO+>n1$|%KAOiQHhgVNg8%hF%G!)Zx{q#lW_qE_OH~>6KN`V?IY6%DFu7KH~=V=a> z?5mo4N6nKP_c4`Y6VyAf`dlA#gP^ug8+JY!2Pnn|m*ck7`&@zl{0$+Gs(&5UlU*6Q zFz(ROU7(s#>tS|eMIsv!F)85FFvpS$%VH| z6fAeHboOgEU703Gs5|)q%8FND@POkHv^2k?Le#4}R_0rK`w~*uJWikVZcrt{obkGg&E3l-2W~2aV0}M#?>f@`Y{#S+97^l0_(xz~IKb=8DdX z$c#c70(!9zw<6r#^*g{S=21hFfQj6p2=u%>)2m!AzZohzQ+&ZwSKztu^m4xP&tupGk=zC&fPZaf!IJfnULo?@>EG$K`Iiab0Q6aC#buAB#BwsZ#*_kIyp4 zX$L6qkl7dq9(#W2qu;;$`<}nuigIVxSA;*c(UlHcUpa?OVVCa!V_G5Xfjhp!#^Hol zT0``Ge$&(<##sazhr_(*Lc4v3TqXSXg|)deN9fsYhsF(Y?MZ^%yT#n#Mn(4O9X5qq zE%vT1NWCN$ra2j~9AKRIvho+uKm(~0X&}I?&W-Rhfv>>YZDvwg(LY?oBqQuQm!%sb z^k1RQF9N0{MhCn2oJ{T}eL<3l(v){4{X;1K^Yj(Mx%c|7`$#p9%MDeMnqyKr~sLp3(X<4tB9%G75_k(1WZg7*yyNkgv1+@0M1IL{|KO zE4hPwbzu_q4o7t47r;oR>U<@L#^z!~(!8LkPU==qLK zOjbNvGCk6+#oPhD<>2wqP#d~Xd!f|W{8jZ0&S^ns6BEN;6X4DBuIC#0QY^<<{7h81 zs()nF^(D8Zy$KsO-|u?t0PhiS^@2xf&SjdLtq3Zi>lKiDF?d_@y9mES)+}q$e_AMO zlLoESZjdEjJ(v9{>f8SJ#TkQ*WVjuEdb&b6efh=WWk25mfXG=!b-|~?I(cIs7;z(< zFV!5ba3Q|b@a*&Jzw)7Sn@}I&LUGSyYx!!&-*jKA%8(Dzd471ETjZ?OkUQP)-M`Yf zw_CqYNUex>W)IclRu!D{6Q0V?dy(M&(g~6-Qr;}br4m`ZkT&T1zINlp(s#y?WX(?u z%Ci$7On#D%-BX`D(SzW_`uCDGWxF&SxUC3Ax_M{lyuVE}BTRTlNcd*{?Ags0FEk`n z73d2dHK4luK?GYFtAzX}XuC#&{wCa|!O!KIx(}XY^TbMhHfi1N{>Hb8OYOA9R+EQ) z*a0pfhV8C@co4Q$cQdn||^)2h!!3txAiNc&JvdYVr0mS|Li!wSE4XYSj^r2ae6m@wp>&;qt}q9?DbL1N zLKEV!-Gp?WLZbo0pQrqS2ms3OX}4j@aO#VA;l$7kG(hp`kS>N$q>5p}Qw?sT*C^+| zExG)_+ee6IYo+*gFV5V{<0Ang`TJ>h-o{9Q+kjPr0NbBBXy{$@Wi9lEv*2XZ75Z$R z`(lE2Z%v1>syn+8?RdIDgU!EFtMY_@C<$M&o_AT&Q3Eh%S$F2bg|L#FE z&qynz&j|y0d@`2N-odL(+84>^+}*ElLWU;289~dWrv&CV5=3$9+JV_cC&ddf9 zG(@beMd~w?1+7#K;a8dY8H3Aai?R=lurs4M#q+6!oi}EjJhYhn)kUfY3q}Qp_78v@ zioFP{(S7B5O)=d^8tpsvQwwyov*C4~s9EmCFMn_DZqAD6oqH)J$&1Z~tk8L7HI1FJ z>BiS2(svy)0a+rGtrdQsqS~wY=JpdHh2zms`gBu&R>4dG{g*?*czygwo&D*;i4j$w zGFew-6QK+T5|`#(B7U9Y3WMWaeC2FtfB!~YshuRK?~2Ir-R^{zE>{0ykBWqs&ac#J z169R`%PDZNXtu#J{^-bo*D2{kiTQ_?&Lg@N1|v1J#___Euclwyt5mP6vj& zqIt?z9GB6H(+#1;FuTb{-sE`RLk}vOcOA?l=vbFL4?9*gomd!IBm?&QE_agr2Y;Go zeGH)bGZ~4Y;uhTe%vEqgJcRI@_u92~#7^!wi2A=@xd-0s6~iw7y-;cR!}XQD3srEr zfthy*&g|v9*{d+fvG~v zG4Pl7YEvQo8@Uj?;^DFmGO5a!^AdM~o>Ytxpu?)R1qWmG)y~|4+`Mm27T+}HT1NFx zrrA^!!W4e!ygw)3AW2r~l0^s~vAZ7(s=17})LgC1{+b1s@p2mNX~(Aly3fcH^LF_Y{}bP}tkDe` zb^tHZRR?!oYKdqLV?w`S7!<2UGA=7C>_3-GUom~qyqap7Lc@NvAuwmCC0}ShFuIqJ zvEya&*k#Lmm4d)C%EzlOeKUI*uM+j#Yx0SCp+qs9@E5CVzFAx~I|U14_DSDlQ?_qB zD~D#qI&}_Lx8+9uZ0gx_#^Uo@*lU$m z=`HznF05Nq(+6BbMML~7r0%VzZjh>mBy9A2DAWF8aFtoR*<#S7a<@l$e~8q0Q+Xnj zpY1myg16SIZeD#n!lxeWY!QC+RQG`#h0PACG7=TW4jG1^MOghhx2M|Q5BiqVs#?6f zm1lqAzfm^sv(Isp6t4$`ckm=2%@aY?O6pAztv?u+F400Mh>(v@$zmZXfNl+!>Hv& zm;E+5_`#Rw1MwgN&8cR?7`#%es_TH1=q^!F`x%^+BINYn&8nbsrD;+;BM9�IQvA; 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

-2ku4wGs_zr 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 z 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

?+l7 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�Kv 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 z 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 VRQY{WNd^D_002ovPDHLkV1gW!zV844 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png deleted file mode 100644 index 8c483a0a7a92ab5a46e6cfcfa49f8fdf5ddb173b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2227 zcmV;k2u$~hP)Hg1+lHrgWSWcKdPn90sKGrRqvPeo9CG3uKX#J{(IASm?@+di}}l?o-=)F3E6 zwD^Ni=!>T7nL9I?X}YoAW$t|Qo$sD|?zw001?ah|SeB6#0T!CBEf+H4bBB+JJu8re zhoBb*p;u8ID_yBf0ya+zcePvJL&AGs+11_tpRKn>9TgyPA7ZoSs0)aX0r00)%XR^J z`jH<$>RKN5V(7OqK*TS4xZz{h!*f1C3ECFkK$#7nA@pGN!$;%jYv zwjAKwmYb0gKL(K8-kPtb5${A?tlI~wzMrJ6wTdBr=Y%%%EaEMQ&o}4FQ^DA)s*}Z> z!FI&AHCpoWI|RUqx?7s@$8!5^Q=anY%X@i5{QA6kNcMelpE>R6eCYFpmMsVT zrI(b06~u#xf1yS}_UGdMvD``!0~u->P=lA4?YN`hilQ z|3tHka)7T{2CGqwjZfMwx$5irQN_*|e4l)UHmiYuz74Yp1t^#>hrJ3-SOXDcC_o0^ z7T9R1gAN8V6s;5)ieI5-7aQlmJn}lUna#nz!j%5V$X|o`xX!dHWQRV27P1=rj;t2b zW$~+pTw@bIek?ZvKPDL<64`^#UNTAck#RBsB6*5DP4<%UA_FqU$I>2EH_cM;u)Q~SI+rg`Rn{L z_AC5qq~L$#SMj%U$6Cz0vP{G5Y*=%5RT^yu;}-DInZ=349rJPVM6C3K^oO)8y(fJr{l>k`ead~!ea?NsT>_Ci%bnxC;Vy6= zb6>{xYV#Ue-+LB$7`JEXmTRm^AtP)R9u{)KHsMiWGV&)32xCG~*nyU<>-!d;FP=Re z4r3qYr~6#KE>;1F`>_J_P5xC?ROxV(DIHdCO*p$HRQI@7^PwV@Pvuf+ z5K}u-6REM(K@W$srgorh0{i?O)v0c>QtHxU-hBdD(>iYJ4b2sIOVX2K8m~4gmYVA5 zh^QEb$V`rCQ-|7ZS{nuL-t>?3n=-o(6I(7vocj#GzCZEo`!3>+v;dYIfPu#&ZWzzX z2i^rZ^Mu;6+rb@?NPG+6)c5T6zxpzGe*M(x+{AON=PiJ>H#?ob-|uwRK0yDg0B4PV z0id6JRRdfL?*ISMZUrf*k6*ChPpT+|w%)~?&LZ-nb17Y3hFmq)L#-QuEuI;_O zzdYwVMi9SEyY}95Kj(ZtpL5PcPfu@12SNxudH9;=dGLK-UFP3>q#+@7`M-E|lkan2 zys@ zorE0Ap?WEYT45b7G0=ntUDA7d4Dr5w(B4hq`>|1+J^LjBdXArGR(fk|>o5blu7^*C zhH&QS2^2s53C@*y$^wvzu%Z^E89^XI1a%LXdjKQ5g5HyFA|iE6{544lg_2B(W|JOA z`VM1o;60Q+y9jS_6`mpB2fnJBvxh-IMri7xNZdkrw}jw}-*CF?b@cbXjDWM#(Kwj( z`S625gcoiAOC@Ngp(xZnR|)U>9z3FD5G8)ssDP>-z+NpwpIyP3L+`*eO$DiOU?!bb z22?N4K@bIsMM%^_a#nbx4X83o>eOsiv0bSm=uSZI>x46V2dTz3?0c?*l6sIn^;(Jm zH_ z3cR%qB%7KMl6D%2MNLb#`vEp=qC%iSp+X=o{8AMgKl}l?zZJ5j5#BvAB4&`&F0kPs zBu0ibsGTAVqmIUoEZqCu5ogS#E@u@E> z>r`o56Rxe@#&rH~NCxCGTmty!yK^v(zX*NTGtfwIp%#Up&7vb>utu93iTlm6O!%au zo@j*3wBg&!7nGsA7xZK@In2TTEG)p--hjiWjv|eGe5%Z?o1@8a=002ovPDHLkV1i)_ BI!^!q diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png deleted file mode 100644 index a45b01b91c65e3a8d8feefe5122bef85c77a78fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4485 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 X5L}ax?^OsQ00000NkvXXu0mjf-pQ8F diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png deleted file mode 100644 index d2ba8f3a7ee97837b87d619cb0f7c1f3243d7591..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28089 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 Y0}pcCLt@!TD*ylh07*qoM6N<$f{85HlmGw# diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png deleted file mode 100644 index 43d577040eeca37d88ca15030a9994678c44f14a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3192 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 X5L}ax?^OsQ00000NkvXXu0mjf-pQ8F diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png deleted file mode 100644 index 717603dd684e9a71f55243678b954a70b89f0a13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10768 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

rD-NlRi2>YR3M-xKh z9c4Kh`=aD%&%Ndl%vr+n}RYro+f%j>+#f{sNr+KALrZ~C8bYLjxa@X>BCtfCeq)hRhhs? z-~Ze8kq>^v>i6|nL7#UsKJXM&7f7IQ(oXjL*|Yt8=K*~{qg%%f_dd1Bk3Ou|TxhF~ z2R;?RLiDUj3Ce<@%1B4+NMiZeWYZ-&PXE^PtU-h`2#bZxI%d(;2}@#BvKTk7g^9y+ z+U;{+_?&&}Z$B#>X-AnK$A@;mOJC9E1dwPl($bZjwyd%li%*|(_C-NEjWm9lkd#unpyJ7=zK)B?Fr-tiZ9*AMTJ!78ttRC177RC3a{L)=iQ ziNBvx0*C4bl^qiqLU&7=r|EkGzy7Q5w)gz{do+<;#bVEI`ukM=gjLIj!l=b9RwR4E%ntJ5Nj4jgyMV-8EAae!#FgIqyHd;Ln%J#0GK3n2Lw@H zPOxDKl7?(WCIgPBKjzp3S;`I}e)5!*Pkzh*=?iYABQ3gyyY0?zf6Ko34}WhPHg5Fw z%Pf+kp9L2IAED0;S)Ite8lKa6O&Eb8T<~F|dU&Q1G%5_S2m`Pnd6&2*6C;dSET#$1 zSiZvE^~>+Hx4h*oHhbD>a&4-gdu@LrK_DAM$HY!DEFoMEs5|;&JZ3CH;4UU`=SfKC zeXQz&M3W~MV_BZ5B6*|pQNW2oEqIP|o-hK3X-0@iC1^yb3=IoJrf|Z;l@L0SW+c0>FCp}T zdGqbfx7}vH@C$FV^UlI zm&P;iCWOEgL;*C6DMuuk`Cb4*QYqY>G3OE<-UoGqt2C%@^62f=7dF*@tz5a%ZWFPu zx#k*Mdio-{Je5-YqG|Yq)5JdkAfro#C4_?Lz*xlNy;nhh{LXXfH|dd5so$LXW1Fkt z5MSYz=HI-1tNrwW2kh><@3!Zjd(I9YIqYq1(Q+fS71{|zC+$s$OHpy#c|H*ccqV`F z9r6U1xH&Og(|Dc`0z-_@$52=x7!^QrA#iw~ZrBK+QQILcgdQ1Q^(j3cyO=72?ELf3 zvsJ6Ew5zVVQr7n}ecwsQhu}yxYr{B2R(+|TMTPGhwHs6~1Oy-;#22FY>;T6y<~UQD z)B89wP^SmUf$jw5sNM~mHrk_)K5CCW`k1}2<^|igZ@*7=z|eT1KsfCHxvY9*+|RqD zDCaW&eX@TL9&ieAacAei|!XHzExT4OpkF`aOI1+H0FO*{kc<+nP0NY~9**wr9^CKeYf=$UJQzCddS- zTrf2T6`6zhKwxs8C}5*m!a$|tCQE`v{z&&JBQOYu2q1k#MN0zIScHaE4{6m=t7&t@u~Y|Q<0DTDG|KIji;*;3ty(+W(J|SkPoM4=Gc;4COtJP!?WH|E$)b3s2>W__ z{iO6GI&1mxp+k01*Wts5?TAj;?a?Rg1T{nTY5 zCkz6vLia^E{00JZHF9E}97$meJU|`*_sVO8=!8RL z`X1CI4W!}D7`)SSvfQ-P&6YGY5}eeIsZmLw(lV=rM6w2pIo@P}d3;a$(?lI7e)fP& z+8Pi|dy(W5T|+ezrb%0a=gSP%fKLzBFD~X zK|*L2AB;#ijT;)O(?!3Bkt2nx#uB%#o&GV=BA!9UpM(z+0tG_F_k_@}LmY>-QpxEy zw2zB2xv)7-6>+IPngJ#Pz%u}oSHts!5g4S!SOts>9 z!U!B1L!$#{g|Lad2LvW}2$vuf1cP*xaft`Y#2&x=K-?r|D1)a!^sGFHmz0_H_SA;e zisuO@@TqN9I`>M#ByW>2BsnHjI%WF#c;cqh{=fYE|2cuHqxRn`!K$}7`_2Ca1L!4r T1Z_6R00000NkvXXu0mjfx&MOR diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png deleted file mode 100644 index 78ef8d12b73234c4a0d842db591fddf8646b5efa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30946 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 Va~q+uY%u@;002ovPDHLkV1i*114sY> diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png deleted file mode 100644 index a45b01b91c65e3a8d8feefe5122bef85c77a78fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4485 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 X5L}ax?^OsQ00000NkvXXu0mjf-pQ8F diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png deleted file mode 100644 index 46ddf1179de6fe5a5d0ea2907a1b2823ad0d14b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7458 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

#ey>)?|3_`yyL|7a`H`_C`|$RPW{X#!{8F#Ruy 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 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png deleted file mode 100644 index 1ebec1390b7d9dd55bda6e79f655d2ddbf5114dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7156 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 diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png deleted file mode 100644 index 717603dd684e9a71f55243678b954a70b89f0a13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10768 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

rD-NlRi2>YR3M-xKh z9c4Kh`=aD%&%Ndl%vr+n}RYro+f%j>+#f{sNr+KALrZ~C8bYLjxa@X>BCtfCeq)hRhhs? z-~Ze8kq>^v>i6|nL7#UsKJXM&7f7IQ(oXjL*|Yt8=K*~{qg%%f_dd1Bk3Ou|TxhF~ z2R;?RLiDUj3Ce<@%1B4+NMiZeWYZ-&PXE^PtU-h`2#bZxI%d(;2}@#BvKTk7g^9y+ z+U;{+_?&&}Z$B#>X-AnK$A@;mOJC9E1dwPl($bZjwyd%li%*|(_C-NEjWm9lkd#unpyJ7=zK)B?Fr-tiZ9*AMTJ!78ttRC177RC3a{L)=iQ ziNBvx0*C4bl^qiqLU&7=r|EkGzy7Q5w)gz{do+<;#bVEI`ukM=gjLIj!l=b9RwR4E%ntJ5Nj4jgyMV-8EAae!#FgIqyHd;Ln%J#0GK3n2Lw@H zPOxDKl7?(WCIgPBKjzp3S;`I}e)5!*Pkzh*=?iYABQ3gyyY0?zf6Ko34}WhPHg5Fw z%Pf+kp9L2IAED0;S)Ite8lKa6O&Eb8T<~F|dU&Q1G%5_S2m`Pnd6&2*6C;dSET#$1 zSiZvE^~>+Hx4h*oHhbD>a&4-gdu@LrK_DAM$HY!DEFoMEs5|;&JZ3CH;4UU`=SfKC zeXQz&M3W~MV_BZ5B6*|pQNW2oEqIP|o-hK3X-0@iC1^yb3=IoJrf|Z;l@L0SW+c0>FCp}T zdGqbfx7}vH@C$FV^UlI zm&P;iCWOEgL;*C6DMuuk`Cb4*QYqY>G3OE<-UoGqt2C%@^62f=7dF*@tz5a%ZWFPu zx#k*Mdio-{Je5-YqG|Yq)5JdkAfro#C4_?Lz*xlNy;nhh{LXXfH|dd5so$LXW1Fkt z5MSYz=HI-1tNrwW2kh><@3!Zjd(I9YIqYq1(Q+fS71{|zC+$s$OHpy#c|H*ccqV`F z9r6U1xH&Og(|Dc`0z-_@$52=x7!^QrA#iw~ZrBK+QQILcgdQ1Q^(j3cyO=72?ELf3 zvsJ6Ew5zVVQr7n}ecwsQhu}yxYr{B2R(+|TMTPGhwHs6~1Oy-;#22FY>;T6y<~UQD z)B89wP^SmUf$jw5sNM~mHrk_)K5CCW`k1}2<^|igZ@*7=z|eT1KsfCHxvY9*+|RqD zDCaW&eX@TL9&ieAacAei|!XHzExT4OpkF`aOI1+H0FO*{kc<+nP0NY~9**wr9^CKeYf=$UJQzCddS- zTrf2T6`6zhKwxs8C}5*m!a$|tCQE`v{z&&JBQOYu2q1k#MN0zIScHaE4{6m=t7&t@u~Y|Q<0DTDG|KIji;*;3ty(+W(J|SkPoM4=Gc;4COtJP!?WH|E$)b3s2>W__ z{iO6GI&1mxp+k01*Wts5?TAj;?a?Rg1T{nTY5 zCkz6vLia^E{00JZHF9E}97$meJU|`*_sVO8=!8RL z`X1CI4W!}D7`)SSvfQ-P&6YGY5}eeIsZmLw(lV=rM6w2pIo@P}d3;a$(?lI7e)fP& z+8Pi|dy(W5T|+ezrb%0a=gSP%fKLzBFD~X zK|*L2AB;#ijT;)O(?!3Bkt2nx#uB%#o&GV=BA!9UpM(z+0tG_F_k_@}LmY>-QpxEy zw2zB2xv)7-6>+IPngJ#Pz%u}oSHts!5g4S!SOts>9 z!U!B1L!$#{g|Lad2LvW}2$vuf1cP*xaft`Y#2&x=K-?r|D1)a!^sGFHmz0_H_SA;e zisuO@@TqN9I`>M#ByW>2BsnHjI%WF#c;cqh{=fYE|2cuHqxRn`!K$}7`_2Ca1L!4r T1Z_6R00000NkvXXu0mjfx&MOR diff --git a/osu.iOS/iTunesArtwork b/osu.iOS/iTunesArtwork deleted file mode 100644 index 1939459992eba68e1067c5af904fa25624cef86d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 142214 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 Z{y%t>pLdzx&T#+$002ovPDHLkV1j&!dny0` diff --git a/osu.iOS/iTunesArtwork@2x b/osu.iOS/iTunesArtwork@2x deleted file mode 100644 index 0e8bb029bc964d313c07fea891a1fcfa1b10e139..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350640 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 z 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

?+l7 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�Kv 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 Date: Sat, 27 Jan 2024 20:21:27 +0900 Subject: [PATCH 129/915] Update framework --- 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 a7376aa5a7..969fd52340 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index 98e8b136e5..bbcabc6360 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From 9d73d0e04d08a235587a874f56d1492aadcfba51 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 27 Jan 2024 19:06:04 +0300 Subject: [PATCH 130/915] Clamp logo triangles along both axes --- osu.Game/Screens/Menu/OsuLogo.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index a39d552a90..25101730e7 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -187,7 +187,6 @@ namespace osu.Game.Screens.Menu }, triangles = new TrianglesV2 { - ClampAxes = Axes.X, Anchor = Anchor.Centre, Origin = Anchor.Centre, Thickness = 0.009f, From d38779f9620deae86c6ce0be2d0d916411c3b359 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 27 Jan 2024 23:22:29 +0300 Subject: [PATCH 131/915] Add failing test case --- .../Multiplayer/TestSceneMultiplayerPlayer.cs | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs index cbeff770c9..aaf85dab7c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs @@ -3,13 +3,18 @@ #nullable disable +using System; +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.Play; @@ -19,14 +24,37 @@ namespace osu.Game.Tests.Visual.Multiplayer { private MultiplayerPlayer player; - [SetUpSteps] - public override void SetUpSteps() + [Test] + public void TestGameplay() { - base.SetUpSteps(); + setup(); + AddUntilStep("wait for gameplay start", () => player.LocalUserPlaying.Value); + } + + [Test] + public void TestFail() + { + setup(() => new[] { new OsuModAutopilot() }); + + AddUntilStep("wait for gameplay start", () => player.LocalUserPlaying.Value); + AddStep("set health zero", () => player.ChildrenOfType().Single().Health.Value = 0); + AddUntilStep("wait for fail", () => player.ChildrenOfType().Single().HasFailed); + AddAssert("fail animation not shown", () => !player.GameplayState.HasFailed); + + // ensure that even after reaching a failed state, score processor keeps accounting for new hit results. + // the testing method used here (autopilot + hold key) is sort-of dodgy, but works enough. + AddAssert("score is zero", () => player.GameplayState.ScoreProcessor.TotalScore.Value == 0); + AddStep("hold key", () => player.ChildrenOfType().First().TriggerPressed(OsuAction.LeftButton)); + AddUntilStep("score changed", () => player.GameplayState.ScoreProcessor.TotalScore.Value > 0); + } + + private void setup(Func> mods = null) + { AddStep("set beatmap", () => { Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + SelectedMods.Value = mods?.Invoke() ?? Array.Empty(); }); AddStep("Start track playing", () => @@ -52,11 +80,5 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("gameplay clock is not paused", () => !player.ChildrenOfType().Single().IsPaused.Value); AddAssert("gameplay clock is running", () => player.ChildrenOfType().Single().IsRunning); } - - [Test] - public void TestGameplay() - { - AddUntilStep("wait for gameplay start", () => player.LocalUserPlaying.Value); - } } } From ea641bb8d2cf7d307d508c0f1d8fb81e3ef773d7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 27 Jan 2024 19:09:46 +0300 Subject: [PATCH 132/915] Rename `GameplayState.HasFailed` to properly clarify its meaning --- .../TestSceneTaikoSuddenDeath.cs | 2 +- .../Visual/Gameplay/TestSceneFailAnimation.cs | 2 +- .../Visual/Gameplay/TestSceneFailJudgement.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 12 ++++++------ .../Gameplay/TestScenePlayerScoreSubmission.cs | 4 ++-- .../Visual/Gameplay/TestSceneSpectator.cs | 2 +- .../Gameplay/TestSceneStoryboardWithOutro.cs | 4 ++-- .../Visual/Mods/TestSceneModAccuracyChallenge.cs | 4 ++-- .../Multiplayer/TestSceneMultiplayerPlayer.cs | 2 +- .../Navigation/TestSceneScreenNavigation.cs | 2 +- osu.Game/Online/Spectator/SpectatorClient.cs | 2 +- osu.Game/Screens/Play/GameplayState.cs | 7 +++++-- osu.Game/Screens/Play/Player.cs | 16 ++++++++-------- .../Screens/Play/PlayerTouchInputDetector.cs | 2 +- 14 files changed, 33 insertions(+), 30 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs index 9e45197b04..4b78e0a005 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Player.ScoreProcessor.NewJudgement += _ => judged = true; }); AddUntilStep("swell judged", () => judged); - AddAssert("not failed", () => !Player.GameplayState.HasFailed); + AddAssert("not failed", () => !Player.GameplayState.ShownFailAnimation); } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index b251253b7c..369bcfac4e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State.Value == Visibility.Visible); // The pause screen and fail animation both ramp frequency. diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index 6297b062dd..4fb6e9783c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("player is playing", () => Player.LocalUserPlaying.Value); - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddAssert("player is not playing", () => !Player.LocalUserPlaying.Value); AddUntilStep("wait for multiple judgements", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits > 1); AddAssert("total number of results == 1", () => diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 73aa3be73d..32f5d7cc55 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestPauseAfterFail() { - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddUntilStep("fail overlay shown", () => Player.FailOverlayVisible); confirmClockRunning(false); @@ -240,7 +240,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestExitFromFailedGameplayAfterFailAnimation() { - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddUntilStep("wait for fail overlay shown", () => Player.FailOverlayVisible); confirmClockRunning(false); @@ -252,7 +252,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestExitFromFailedGameplayDuringFailAnimation() { - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); // will finish the fail animation and show the fail/pause screen. pauseViaBackAction(); @@ -266,7 +266,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestQuickRetryFromFailedGameplay() { - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddStep("quick retry", () => Player.GameplayClockContainer.ChildrenOfType().First().Action?.Invoke()); confirmExited(); @@ -275,7 +275,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestQuickExitFromFailedGameplay() { - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); exitViaQuickExitAction(); confirmExited(); @@ -380,7 +380,7 @@ namespace osu.Game.Tests.Visual.Gameplay { confirmClockRunning(false); confirmNotExited(); - AddAssert("player not failed", () => !Player.GameplayState.HasFailed); + AddAssert("player not failed", () => !Player.GameplayState.ShownFailAnimation); AddAssert("pause overlay shown", () => Player.PauseOverlayVisible); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 5e22e47572..a4f71bcaad 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for token request", () => Player.TokenCreationRequested); - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddStep("exit", () => Player.Exit()); AddAssert("ensure no submission", () => Player.SubmittedScore == null); @@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual.Gameplay addFakeHit(); - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddUntilStep("wait for submission", () => Player.SubmittedScore != null); AddAssert("ensure failing submission", () => Player.SubmittedScore.ScoreInfo.Passed == false); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 1c7ede2b19..b0bb42921d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -353,7 +353,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("send failed", () => spectatorClient.SendEndPlay(streamingUser.Id, SpectatedUserState.Failed)); AddUntilStep("state is failed", () => spectatorClient.WatchedUserStates[streamingUser.Id].State == SpectatedUserState.Failed); - AddUntilStep("wait for player to fail", () => player.GameplayState.HasFailed); + AddUntilStep("wait for player to fail", () => player.GameplayState.ShownFailAnimation); start(); sendFrames(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 98825b27d4..e2e5aac734 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("set storyboard duration to 0.6s", () => currentStoryboardDuration = 600); }); - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.CurrentTime >= currentStoryboardDuration); AddUntilStep("wait for fail overlay", () => Player.FailOverlay.State.Value == Visibility.Visible); } @@ -116,7 +116,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("set storyboard duration to 0s", () => currentStoryboardDuration = 0); }); AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.CurrentTime >= currentStoryboardDuration); - AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddUntilStep("wait for fail overlay", () => Player.FailOverlay.State.Value == Visibility.Visible); AddUntilStep("wait for button clickable", () => Player.ChildrenOfType().First().ChildrenOfType().First().Enabled.Value); diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs b/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs index c5e56c6453..4fc6fe1b77 100644 --- a/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs +++ b/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Mods Position = new Vector2(i * 50) }).Cast().ToList() }, - PassCondition = () => Player.GameplayState.HasFailed && Player.ScoreProcessor.JudgedHits >= 3 + PassCondition = () => Player.GameplayState.ShownFailAnimation && Player.ScoreProcessor.JudgedHits >= 3 }); [Test] @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Mods Position = new Vector2(i * 50) }).Cast().ToList() }, - PassCondition = () => Player.GameplayState.HasFailed && Player.ScoreProcessor.JudgedHits >= 1 + PassCondition = () => Player.GameplayState.ShownFailAnimation && Player.ScoreProcessor.JudgedHits >= 1 }); } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs index aaf85dab7c..175fd3127d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for gameplay start", () => player.LocalUserPlaying.Value); AddStep("set health zero", () => player.ChildrenOfType().Single().Health.Value = 0); AddUntilStep("wait for fail", () => player.ChildrenOfType().Single().HasFailed); - AddAssert("fail animation not shown", () => !player.GameplayState.HasFailed); + AddAssert("fail animation not shown", () => !player.GameplayState.ShownFailAnimation); // ensure that even after reaching a failed state, score processor keeps accounting for new hit results. // the testing method used here (autopilot + hold key) is sort-of dodgy, but works enough. diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index f59fbc75ac..083a5dc833 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -392,7 +392,7 @@ namespace osu.Game.Tests.Visual.Navigation return (player = Game.ScreenStack.CurrentScreen as Player) != null; }); - AddUntilStep("wait for fail", () => player.GameplayState.HasFailed); + AddUntilStep("wait for fail", () => player.GameplayState.ShownFailAnimation); AddUntilStep("wait for track stop", () => !Game.MusicController.IsPlaying); AddAssert("Ensure time before preview point", () => Game.MusicController.CurrentTrack.CurrentTime < beatmap().BeatmapInfo.Metadata.PreviewTime); diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 7911701853..a9a666a360 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -251,7 +251,7 @@ namespace osu.Game.Online.Spectator if (state.HasPassed) currentState.State = SpectatedUserState.Passed; - else if (state.HasFailed) + else if (state.ShownFailAnimation) currentState.State = SpectatedUserState.Failed; else currentState.State = SpectatedUserState.Quit; diff --git a/osu.Game/Screens/Play/GameplayState.cs b/osu.Game/Screens/Play/GameplayState.cs index cc399a0fbe..f64bcc9a3c 100644 --- a/osu.Game/Screens/Play/GameplayState.cs +++ b/osu.Game/Screens/Play/GameplayState.cs @@ -46,9 +46,12 @@ namespace osu.Game.Screens.Play public bool HasPassed { get; set; } ///

- /// Whether the user failed during gameplay. This is only set when the gameplay session has completed due to the fail. + /// Whether the user failed during gameplay and the fail animation has been displayed. /// - public bool HasFailed { get; set; } + /// + /// In multiplayer, this is never set to true even if the player reached zero health, due to being turned off. + /// + public bool ShownFailAnimation { get; set; } /// /// Whether the user quit gameplay without having either passed or failed. diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ad1f9ec897..ff1deecc3d 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -489,7 +489,7 @@ namespace osu.Game.Screens.Play private void updateGameplayState() { - bool inGameplay = !DrawableRuleset.HasReplayLoaded.Value && !DrawableRuleset.IsPaused.Value && !breakTracker.IsBreakTime.Value && !GameplayState.HasFailed; + bool inGameplay = !DrawableRuleset.HasReplayLoaded.Value && !DrawableRuleset.IsPaused.Value && !breakTracker.IsBreakTime.Value && !GameplayState.ShownFailAnimation; OverlayActivationMode.Value = inGameplay ? OverlayActivation.Disabled : OverlayActivation.UserTriggered; localUserPlaying.Value = inGameplay; } @@ -586,7 +586,7 @@ namespace osu.Game.Screens.Play if (showDialogFirst && !pauseOrFailDialogVisible) { // if the fail animation is currently in progress, accelerate it (it will show the pause dialog on completion). - if (ValidForResume && GameplayState.HasFailed) + if (ValidForResume && GameplayState.ShownFailAnimation) { failAnimationContainer.FinishTransforms(true); return false; @@ -733,7 +733,7 @@ namespace osu.Game.Screens.Play } // Only show the completion screen if the player hasn't failed - if (GameplayState.HasFailed) + if (GameplayState.ShownFailAnimation) return; GameplayState.HasPassed = true; @@ -922,11 +922,11 @@ namespace osu.Game.Screens.Play if (Configuration.AllowFailAnimation) { - Debug.Assert(!GameplayState.HasFailed); + Debug.Assert(!GameplayState.ShownFailAnimation); Debug.Assert(!GameplayState.HasPassed); Debug.Assert(!GameplayState.HasQuit); - GameplayState.HasFailed = true; + GameplayState.ShownFailAnimation = true; updateGameplayState(); @@ -1002,13 +1002,13 @@ namespace osu.Game.Screens.Play // replays cannot be paused and exit immediately && !DrawableRuleset.HasReplayLoaded.Value // cannot pause if we are already in a fail state - && !GameplayState.HasFailed; + && !GameplayState.ShownFailAnimation; private bool canResume => // cannot resume from a non-paused state GameplayClockContainer.IsPaused.Value // cannot resume if we are already in a fail state - && !GameplayState.HasFailed + && !GameplayState.ShownFailAnimation // already resuming && !IsResuming; @@ -1142,7 +1142,7 @@ namespace osu.Game.Screens.Play { Debug.Assert(resultsDisplayDelegate == null); - if (!GameplayState.HasFailed) + if (!GameplayState.ShownFailAnimation) GameplayState.HasQuit = true; if (DrawableRuleset.ReplayScore == null) diff --git a/osu.Game/Screens/Play/PlayerTouchInputDetector.cs b/osu.Game/Screens/Play/PlayerTouchInputDetector.cs index 12fb748e7d..13c94f7b32 100644 --- a/osu.Game/Screens/Play/PlayerTouchInputDetector.cs +++ b/osu.Game/Screens/Play/PlayerTouchInputDetector.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Play if (!touchActive.Value) return; - if (gameplayState.HasPassed || gameplayState.HasFailed || gameplayState.HasQuit) + if (gameplayState.HasPassed || gameplayState.ShownFailAnimation || gameplayState.HasQuit) return; if (gameplayState.Score.ScoreInfo.Mods.OfType().Any()) From a25be9927df56d845f1a95f8a74bd535c9273fa0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 27 Jan 2024 19:12:03 +0300 Subject: [PATCH 133/915] Fix score processor no longer applying results when failing in multiplayer match --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 ------ osu.Game/Screens/Play/Player.cs | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a092829317..7d50dd4665 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -211,9 +211,6 @@ namespace osu.Game.Rulesets.Scoring result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; - if (result.FailedAtJudgement) - return; - ScoreResultCounts[result.Type] = ScoreResultCounts.GetValueOrDefault(result.Type) + 1; if (result.Type.IncreasesCombo()) @@ -267,9 +264,6 @@ namespace osu.Game.Rulesets.Scoring Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; - if (result.FailedAtJudgement) - return; - ScoreResultCounts[result.Type] = ScoreResultCounts.GetValueOrDefault(result.Type) - 1; if (result.Judgement.MaxResult.AffectsAccuracy()) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ff1deecc3d..e2470285ba 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -357,6 +357,9 @@ namespace osu.Game.Screens.Play DrawableRuleset.NewResult += r => { + if (GameplayState.ShownFailAnimation) + return; + HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); GameplayState.ApplyResult(r); @@ -364,6 +367,9 @@ namespace osu.Game.Screens.Play DrawableRuleset.RevertResult += r => { + if (GameplayState.ShownFailAnimation) + return; + HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; From 5f689998930a5b37021a2ace9f6c76d69d07239d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 27 Jan 2024 20:44:34 +0300 Subject: [PATCH 134/915] Fix `TestSceneFailJudgement` asserts no longer being correct --- .../Visual/Gameplay/TestSceneFailJudgement.cs | 2 +- osu.Game/Rulesets/UI/Playfield.cs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index 4fb6e9783c..339746ac8b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("player is playing", () => Player.LocalUserPlaying.Value); AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); AddAssert("player is not playing", () => !Player.LocalUserPlaying.Value); - AddUntilStep("wait for multiple judgements", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits > 1); + AddUntilStep("wait for multiple judgements", () => ((FailPlayer)Player).DrawableRuleset.Playfield.AllEntries.Count(e => e.Judged) > 1); AddAssert("total number of results == 1", () => { var score = new ScoreInfo { Ruleset = Ruleset.Value }; diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index e9c35555c8..176223729a 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -78,6 +78,25 @@ namespace osu.Game.Rulesets.UI } } + /// + /// All the s contained in this and all . + /// + public IEnumerable AllEntries + { + get + { + if (HitObjectContainer == null) + return Enumerable.Empty(); + + var enumerable = HitObjectContainer.Entries; + + if (nestedPlayfields.Count != 0) + enumerable = enumerable.Concat(NestedPlayfields.SelectMany(p => p.AllEntries)); + + return enumerable; + } + } + /// /// All s nested inside this . /// From 64b61108ad5b389ce136385393eb3eba9a4f9bc8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 28 Jan 2024 00:34:23 +0300 Subject: [PATCH 135/915] Move solution to multiplayer flow instead --- .../TestSceneTaikoSuddenDeath.cs | 2 +- .../Visual/Gameplay/TestSceneFailAnimation.cs | 2 +- .../Visual/Gameplay/TestSceneFailJudgement.cs | 4 ++-- .../Visual/Gameplay/TestScenePause.cs | 12 +++++----- .../TestScenePlayerScoreSubmission.cs | 4 ++-- .../Visual/Gameplay/TestSceneSpectator.cs | 2 +- .../Gameplay/TestSceneStoryboardWithOutro.cs | 4 ++-- .../Mods/TestSceneModAccuracyChallenge.cs | 4 ++-- .../Multiplayer/TestSceneMultiplayerPlayer.cs | 2 +- .../Navigation/TestSceneScreenNavigation.cs | 2 +- osu.Game/Online/Spectator/SpectatorClient.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 8 +++++++ osu.Game/Rulesets/UI/Playfield.cs | 19 ---------------- .../Multiplayer/MultiplayerPlayer.cs | 2 ++ osu.Game/Screens/Play/GameplayState.cs | 7 ++---- osu.Game/Screens/Play/Player.cs | 22 +++++++------------ .../Screens/Play/PlayerTouchInputDetector.cs | 2 +- 17 files changed, 41 insertions(+), 59 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs index 4b78e0a005..9e45197b04 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Player.ScoreProcessor.NewJudgement += _ => judged = true; }); AddUntilStep("swell judged", () => judged); - AddAssert("not failed", () => !Player.GameplayState.ShownFailAnimation); + AddAssert("not failed", () => !Player.GameplayState.HasFailed); } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index 369bcfac4e..b251253b7c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State.Value == Visibility.Visible); // The pause screen and fail animation both ramp frequency. diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index 339746ac8b..6297b062dd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -22,9 +22,9 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("player is playing", () => Player.LocalUserPlaying.Value); - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddAssert("player is not playing", () => !Player.LocalUserPlaying.Value); - AddUntilStep("wait for multiple judgements", () => ((FailPlayer)Player).DrawableRuleset.Playfield.AllEntries.Count(e => e.Judged) > 1); + AddUntilStep("wait for multiple judgements", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits > 1); AddAssert("total number of results == 1", () => { var score = new ScoreInfo { Ruleset = Ruleset.Value }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 32f5d7cc55..73aa3be73d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestPauseAfterFail() { - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddUntilStep("fail overlay shown", () => Player.FailOverlayVisible); confirmClockRunning(false); @@ -240,7 +240,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestExitFromFailedGameplayAfterFailAnimation() { - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddUntilStep("wait for fail overlay shown", () => Player.FailOverlayVisible); confirmClockRunning(false); @@ -252,7 +252,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestExitFromFailedGameplayDuringFailAnimation() { - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); // will finish the fail animation and show the fail/pause screen. pauseViaBackAction(); @@ -266,7 +266,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestQuickRetryFromFailedGameplay() { - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddStep("quick retry", () => Player.GameplayClockContainer.ChildrenOfType().First().Action?.Invoke()); confirmExited(); @@ -275,7 +275,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestQuickExitFromFailedGameplay() { - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); exitViaQuickExitAction(); confirmExited(); @@ -380,7 +380,7 @@ namespace osu.Game.Tests.Visual.Gameplay { confirmClockRunning(false); confirmNotExited(); - AddAssert("player not failed", () => !Player.GameplayState.ShownFailAnimation); + AddAssert("player not failed", () => !Player.GameplayState.HasFailed); AddAssert("pause overlay shown", () => Player.PauseOverlayVisible); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index a4f71bcaad..5e22e47572 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for token request", () => Player.TokenCreationRequested); - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddStep("exit", () => Player.Exit()); AddAssert("ensure no submission", () => Player.SubmittedScore == null); @@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual.Gameplay addFakeHit(); - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddUntilStep("wait for submission", () => Player.SubmittedScore != null); AddAssert("ensure failing submission", () => Player.SubmittedScore.ScoreInfo.Passed == false); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index b0bb42921d..1c7ede2b19 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -353,7 +353,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("send failed", () => spectatorClient.SendEndPlay(streamingUser.Id, SpectatedUserState.Failed)); AddUntilStep("state is failed", () => spectatorClient.WatchedUserStates[streamingUser.Id].State == SpectatedUserState.Failed); - AddUntilStep("wait for player to fail", () => player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for player to fail", () => player.GameplayState.HasFailed); start(); sendFrames(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index e2e5aac734..98825b27d4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("set storyboard duration to 0.6s", () => currentStoryboardDuration = 600); }); - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.CurrentTime >= currentStoryboardDuration); AddUntilStep("wait for fail overlay", () => Player.FailOverlay.State.Value == Visibility.Visible); } @@ -116,7 +116,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("set storyboard duration to 0s", () => currentStoryboardDuration = 0); }); AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.CurrentTime >= currentStoryboardDuration); - AddUntilStep("wait for fail", () => Player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); AddUntilStep("wait for fail overlay", () => Player.FailOverlay.State.Value == Visibility.Visible); AddUntilStep("wait for button clickable", () => Player.ChildrenOfType().First().ChildrenOfType().First().Enabled.Value); diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs b/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs index 4fc6fe1b77..c5e56c6453 100644 --- a/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs +++ b/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Mods Position = new Vector2(i * 50) }).Cast().ToList() }, - PassCondition = () => Player.GameplayState.ShownFailAnimation && Player.ScoreProcessor.JudgedHits >= 3 + PassCondition = () => Player.GameplayState.HasFailed && Player.ScoreProcessor.JudgedHits >= 3 }); [Test] @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Mods Position = new Vector2(i * 50) }).Cast().ToList() }, - PassCondition = () => Player.GameplayState.ShownFailAnimation && Player.ScoreProcessor.JudgedHits >= 1 + PassCondition = () => Player.GameplayState.HasFailed && Player.ScoreProcessor.JudgedHits >= 1 }); } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs index 175fd3127d..aaf85dab7c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for gameplay start", () => player.LocalUserPlaying.Value); AddStep("set health zero", () => player.ChildrenOfType().Single().Health.Value = 0); AddUntilStep("wait for fail", () => player.ChildrenOfType().Single().HasFailed); - AddAssert("fail animation not shown", () => !player.GameplayState.ShownFailAnimation); + AddAssert("fail animation not shown", () => !player.GameplayState.HasFailed); // ensure that even after reaching a failed state, score processor keeps accounting for new hit results. // the testing method used here (autopilot + hold key) is sort-of dodgy, but works enough. diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 083a5dc833..f59fbc75ac 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -392,7 +392,7 @@ namespace osu.Game.Tests.Visual.Navigation return (player = Game.ScreenStack.CurrentScreen as Player) != null; }); - AddUntilStep("wait for fail", () => player.GameplayState.ShownFailAnimation); + AddUntilStep("wait for fail", () => player.GameplayState.HasFailed); AddUntilStep("wait for track stop", () => !Game.MusicController.IsPlaying); AddAssert("Ensure time before preview point", () => Game.MusicController.CurrentTrack.CurrentTime < beatmap().BeatmapInfo.Metadata.PreviewTime); diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index a9a666a360..7911701853 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -251,7 +251,7 @@ namespace osu.Game.Online.Spectator if (state.HasPassed) currentState.State = SpectatedUserState.Passed; - else if (state.ShownFailAnimation) + else if (state.HasFailed) currentState.State = SpectatedUserState.Failed; else currentState.State = SpectatedUserState.Quit; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 7d50dd4665..9d12daad04 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -181,6 +181,8 @@ namespace osu.Game.Rulesets.Scoring private readonly List hitEvents = new List(); private HitObject? lastHitObject; + public bool ApplyNewJudgementsWhenFailed { get; set; } + public ScoreProcessor(Ruleset ruleset) { Ruleset = ruleset; @@ -211,6 +213,9 @@ namespace osu.Game.Rulesets.Scoring result.ComboAtJudgement = Combo.Value; result.HighestComboAtJudgement = HighestCombo.Value; + if (result.FailedAtJudgement && !ApplyNewJudgementsWhenFailed) + return; + ScoreResultCounts[result.Type] = ScoreResultCounts.GetValueOrDefault(result.Type) + 1; if (result.Type.IncreasesCombo()) @@ -264,6 +269,9 @@ namespace osu.Game.Rulesets.Scoring Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; + if (result.FailedAtJudgement && !ApplyNewJudgementsWhenFailed) + return; + ScoreResultCounts[result.Type] = ScoreResultCounts.GetValueOrDefault(result.Type) - 1; if (result.Judgement.MaxResult.AffectsAccuracy()) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 176223729a..e9c35555c8 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -78,25 +78,6 @@ namespace osu.Game.Rulesets.UI } } - /// - /// All the s contained in this and all . - /// - public IEnumerable AllEntries - { - get - { - if (HitObjectContainer == null) - return Enumerable.Empty(); - - var enumerable = HitObjectContainer.Entries; - - if (nestedPlayfields.Count != 0) - enumerable = enumerable.Concat(NestedPlayfields.SelectMany(p => p.AllEntries)); - - return enumerable; - } - } - /// /// All s nested inside this . /// diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index d9043df1d5..c5c536eae6 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -67,6 +67,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (!LoadedBeatmapSuccessfully) return; + ScoreProcessor.ApplyNewJudgementsWhenFailed = true; + LoadComponentAsync(new GameplayChatDisplay(Room) { Expanded = { BindTarget = LeaderboardExpandedState }, diff --git a/osu.Game/Screens/Play/GameplayState.cs b/osu.Game/Screens/Play/GameplayState.cs index f64bcc9a3c..cc399a0fbe 100644 --- a/osu.Game/Screens/Play/GameplayState.cs +++ b/osu.Game/Screens/Play/GameplayState.cs @@ -46,12 +46,9 @@ namespace osu.Game.Screens.Play public bool HasPassed { get; set; } /// - /// Whether the user failed during gameplay and the fail animation has been displayed. + /// Whether the user failed during gameplay. This is only set when the gameplay session has completed due to the fail. /// - /// - /// In multiplayer, this is never set to true even if the player reached zero health, due to being turned off. - /// - public bool ShownFailAnimation { get; set; } + public bool HasFailed { get; set; } /// /// Whether the user quit gameplay without having either passed or failed. diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e2470285ba..ad1f9ec897 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -357,9 +357,6 @@ namespace osu.Game.Screens.Play DrawableRuleset.NewResult += r => { - if (GameplayState.ShownFailAnimation) - return; - HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); GameplayState.ApplyResult(r); @@ -367,9 +364,6 @@ namespace osu.Game.Screens.Play DrawableRuleset.RevertResult += r => { - if (GameplayState.ShownFailAnimation) - return; - HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; @@ -495,7 +489,7 @@ namespace osu.Game.Screens.Play private void updateGameplayState() { - bool inGameplay = !DrawableRuleset.HasReplayLoaded.Value && !DrawableRuleset.IsPaused.Value && !breakTracker.IsBreakTime.Value && !GameplayState.ShownFailAnimation; + bool inGameplay = !DrawableRuleset.HasReplayLoaded.Value && !DrawableRuleset.IsPaused.Value && !breakTracker.IsBreakTime.Value && !GameplayState.HasFailed; OverlayActivationMode.Value = inGameplay ? OverlayActivation.Disabled : OverlayActivation.UserTriggered; localUserPlaying.Value = inGameplay; } @@ -592,7 +586,7 @@ namespace osu.Game.Screens.Play if (showDialogFirst && !pauseOrFailDialogVisible) { // if the fail animation is currently in progress, accelerate it (it will show the pause dialog on completion). - if (ValidForResume && GameplayState.ShownFailAnimation) + if (ValidForResume && GameplayState.HasFailed) { failAnimationContainer.FinishTransforms(true); return false; @@ -739,7 +733,7 @@ namespace osu.Game.Screens.Play } // Only show the completion screen if the player hasn't failed - if (GameplayState.ShownFailAnimation) + if (GameplayState.HasFailed) return; GameplayState.HasPassed = true; @@ -928,11 +922,11 @@ namespace osu.Game.Screens.Play if (Configuration.AllowFailAnimation) { - Debug.Assert(!GameplayState.ShownFailAnimation); + Debug.Assert(!GameplayState.HasFailed); Debug.Assert(!GameplayState.HasPassed); Debug.Assert(!GameplayState.HasQuit); - GameplayState.ShownFailAnimation = true; + GameplayState.HasFailed = true; updateGameplayState(); @@ -1008,13 +1002,13 @@ namespace osu.Game.Screens.Play // replays cannot be paused and exit immediately && !DrawableRuleset.HasReplayLoaded.Value // cannot pause if we are already in a fail state - && !GameplayState.ShownFailAnimation; + && !GameplayState.HasFailed; private bool canResume => // cannot resume from a non-paused state GameplayClockContainer.IsPaused.Value // cannot resume if we are already in a fail state - && !GameplayState.ShownFailAnimation + && !GameplayState.HasFailed // already resuming && !IsResuming; @@ -1148,7 +1142,7 @@ namespace osu.Game.Screens.Play { Debug.Assert(resultsDisplayDelegate == null); - if (!GameplayState.ShownFailAnimation) + if (!GameplayState.HasFailed) GameplayState.HasQuit = true; if (DrawableRuleset.ReplayScore == null) diff --git a/osu.Game/Screens/Play/PlayerTouchInputDetector.cs b/osu.Game/Screens/Play/PlayerTouchInputDetector.cs index 13c94f7b32..12fb748e7d 100644 --- a/osu.Game/Screens/Play/PlayerTouchInputDetector.cs +++ b/osu.Game/Screens/Play/PlayerTouchInputDetector.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Play if (!touchActive.Value) return; - if (gameplayState.HasPassed || gameplayState.ShownFailAnimation || gameplayState.HasQuit) + if (gameplayState.HasPassed || gameplayState.HasFailed || gameplayState.HasQuit) return; if (gameplayState.Score.ScoreInfo.Mods.OfType().Any()) From b48f99ba4bd4f16ebff1dc99accb7a1a5e96abf5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 28 Jan 2024 18:06:09 +0300 Subject: [PATCH 136/915] Stop using SliderBar as a base --- .../Play/HUD/DefaultSongProgressBar.cs | 2 +- osu.Game/Screens/Play/HUD/SongProgressBar.cs | 67 +++++++++++++------ 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs index 4079351baf..46867e7622 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs @@ -98,7 +98,7 @@ namespace osu.Game.Screens.Play.HUD base.Update(); handleBase.Height = Height - handleContainer.Height; - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * DrawWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/SongProgressBar.cs index db9c8901b4..df4df2a783 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressBar.cs @@ -3,12 +3,14 @@ using System; using osu.Framework.Bindables; -using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Framework.Threading; +using osuTK; namespace osu.Game.Screens.Play.HUD { - public abstract partial class SongProgressBar : SliderBar + public abstract partial class SongProgressBar : Container { /// /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. @@ -26,45 +28,66 @@ namespace osu.Game.Screens.Play.HUD protected readonly BindableBool InteractiveBindable = new BindableBool(); - public double StartTime + public double StartTime { get; set; } + + public double EndTime { get; set; } = 1.0; + + public double CurrentTime { get; set; } + + private double length => EndTime - StartTime; + + protected double NormalizedValue => length == 0 ? 1 : Math.Clamp(CurrentTime - StartTime, 0.0, length) / length; + + private bool handleClick; + + protected override bool OnMouseDown(MouseDownEvent e) { - get => CurrentNumber.MinValue; - set => CurrentNumber.MinValue = value; + handleClick = true; + return base.OnMouseDown(e); } - public double EndTime + protected override bool OnClick(ClickEvent e) { - get => CurrentNumber.MaxValue; - set => CurrentNumber.MaxValue = value; + if (handleClick) + handleMouseInput(e); + + return true; } - public double CurrentTime + protected override void OnDrag(DragEvent e) { - get => CurrentNumber.Value; - set => CurrentNumber.Value = value; + handleMouseInput(e); } - protected SongProgressBar() + protected override bool OnDragStart(DragStartEvent e) { - StartTime = 0; - EndTime = 1; + Vector2 posDiff = e.MouseDownPosition - e.MousePosition; + + if (Math.Abs(posDiff.X) < Math.Abs(posDiff.Y)) + { + handleClick = false; + return false; + } + + handleMouseInput(e); + return true; } - protected override void UpdateValue(float value) + private void handleMouseInput(UIEvent e) { - // handled in update + if (!Interactive) + return; + + double relativeX = Math.Clamp(ToLocalSpace(e.ScreenSpaceMousePosition).X / DrawWidth, 0, 1); + onUserChange(StartTime + (EndTime - StartTime) * relativeX); } private ScheduledDelegate? scheduledSeek; - protected override void OnUserChange(double value) + private void onUserChange(double value) { scheduledSeek?.Cancel(); - scheduledSeek = Schedule(() => - { - if (Interactive) - OnSeek?.Invoke(value); - }); + scheduledSeek = Schedule(() => OnSeek?.Invoke(value)); } } } From 23f12e1ea36195ed29fa19955d41290cfbc92328 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 01:49:34 +0900 Subject: [PATCH 137/915] Should not be a container --- osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs | 6 +++--- osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs | 2 +- osu.Game/Screens/Play/HUD/SongProgressBar.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 196d8ca278..42f638c386 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Play.HUD CornerRadius = 5; Masking = true; - Children = new Drawable[] + InternalChildren = new Drawable[] { background = new Box { @@ -105,9 +105,9 @@ namespace osu.Game.Screens.Play.HUD audioBar.Length = (float)Interpolation.Lerp(audioBar.Length, NormalizedValue, Math.Clamp(Time.Elapsed / 40, 0, 1)); if (trackTime > CurrentTime) - ChangeChildDepth(audioBar, -1); + ChangeInternalChildDepth(audioBar, -1); else - ChangeChildDepth(audioBar, 0); + ChangeInternalChildDepth(audioBar, 0); float timeDelta = (float)Math.Abs(CurrentTime - trackTime); diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs index 46867e7622..222d6c17bf 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play.HUD RelativeSizeAxes = Axes.X; Height = barHeight + handleBarHeight + handleSize.Y; - Children = new Drawable[] + InternalChildren = new Drawable[] { new Box { diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/SongProgressBar.cs index df4df2a783..140621986c 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressBar.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public abstract partial class SongProgressBar : Container + public abstract partial class SongProgressBar : CompositeDrawable { /// /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. From f4dd84fa77fe41edc57120063a3df9a4bbb834a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 02:01:37 +0900 Subject: [PATCH 138/915] Fix various inconsistencies and document better --- .../Screens/Play/HUD/ArgonSongProgress.cs | 1 - .../Screens/Play/HUD/ArgonSongProgressBar.cs | 9 +++++---- .../Screens/Play/HUD/DefaultSongProgress.cs | 1 - .../Play/HUD/DefaultSongProgressBar.cs | 2 +- osu.Game/Screens/Play/HUD/SongProgress.cs | 6 ++++++ osu.Game/Screens/Play/HUD/SongProgressBar.cs | 19 +++++++++++++++---- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index a0e74dd6cd..7db3f9fd3c 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -114,7 +114,6 @@ namespace osu.Game.Screens.Play.HUD protected override void UpdateProgress(double progress, bool isIntro) { - bar.CurrentTime = GameplayClock.CurrentTime; bar.Progress = isIntro ? 0 : progress; } } diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 42f638c386..7a7870a775 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -48,6 +48,7 @@ namespace osu.Game.Screens.Play.HUD RelativeSizeAxes = Axes.Both, Alpha = 0, Colour = OsuColour.Gray(0.2f), + Depth = float.MaxValue, }, audioBar = new RoundedBar { @@ -102,14 +103,14 @@ namespace osu.Game.Screens.Play.HUD base.Update(); playfieldBar.Length = (float)Interpolation.Lerp(playfieldBar.Length, Progress, Math.Clamp(Time.Elapsed / 40, 0, 1)); - audioBar.Length = (float)Interpolation.Lerp(audioBar.Length, NormalizedValue, Math.Clamp(Time.Elapsed / 40, 0, 1)); + audioBar.Length = (float)Interpolation.Lerp(audioBar.Length, AudioProgress, Math.Clamp(Time.Elapsed / 40, 0, 1)); - if (trackTime > CurrentTime) + if (trackTime > AudioTime) ChangeInternalChildDepth(audioBar, -1); else - ChangeInternalChildDepth(audioBar, 0); + ChangeInternalChildDepth(audioBar, 1); - float timeDelta = (float)Math.Abs(CurrentTime - trackTime); + float timeDelta = (float)Math.Abs(AudioTime - trackTime); const float colour_transition_threshold = 20000; diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs index be310df3a9..f01c11855c 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs @@ -98,7 +98,6 @@ namespace osu.Game.Screens.Play.HUD protected override void UpdateProgress(double progress, bool isIntro) { - bar.CurrentTime = GameplayClock.CurrentTime; graph.Progress = isIntro ? 0 : (int)(graph.ColumnCount * progress); } diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs index 222d6c17bf..05c8c6c46b 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs @@ -98,7 +98,7 @@ namespace osu.Game.Screens.Play.HUD base.Update(); handleBase.Height = Height - handleContainer.Height; - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * DrawWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); + float newX = (float)Interpolation.Lerp(handleBase.X, AudioProgress * DrawWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; diff --git a/osu.Game/Screens/Play/HUD/SongProgress.cs b/osu.Game/Screens/Play/HUD/SongProgress.cs index 962752ba5a..296306ec89 100644 --- a/osu.Game/Screens/Play/HUD/SongProgress.cs +++ b/osu.Game/Screens/Play/HUD/SongProgress.cs @@ -71,7 +71,13 @@ namespace osu.Game.Screens.Play.HUD protected double LastHitTime { get; private set; } + /// + /// Called every update frame with current progress information. + /// + /// Current (visual) progress through the beatmap (0..1). + /// If true, progress is (0..1) through the intro. protected abstract void UpdateProgress(double progress, bool isIntro); + protected virtual void UpdateObjects(IEnumerable objects) { } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/SongProgressBar.cs index 140621986c..ea2e5b2891 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressBar.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -12,6 +13,20 @@ namespace osu.Game.Screens.Play.HUD { public abstract partial class SongProgressBar : CompositeDrawable { + /// + /// The current seek position of the audio, on a (0..1) range. + /// This is generally the seek target, which will eventually match the gameplay clock when it catches up. + /// + protected double AudioProgress => length == 0 ? 1 : AudioTime / length; + + /// + /// The current (non-frame-stable) audio time. + /// + protected double AudioTime => Math.Clamp(GameplayClock.CurrentTime - StartTime, 0.0, length); + + [Resolved] + protected IGameplayClock GameplayClock { get; private set; } = null!; + /// /// Action which is invoked when a seek is requested, with the proposed millisecond value for the seek operation. /// @@ -32,12 +47,8 @@ namespace osu.Game.Screens.Play.HUD public double EndTime { get; set; } = 1.0; - public double CurrentTime { get; set; } - private double length => EndTime - StartTime; - protected double NormalizedValue => length == 0 ? 1 : Math.Clamp(CurrentTime - StartTime, 0.0, length) / length; - private bool handleClick; protected override bool OnMouseDown(MouseDownEvent e) From 462dab3c90d762de0c9c0918d93fe90472956a06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 02:13:39 +0900 Subject: [PATCH 139/915] Remove unnecessary bindable --- osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs | 11 +++++++---- osu.Game/Screens/Play/HUD/SongProgressBar.cs | 9 +-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs index 05c8c6c46b..d5a6a75793 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgressBar.cs @@ -86,11 +86,14 @@ namespace osu.Game.Screens.Play.HUD }; } - protected override void LoadComplete() + public override bool Interactive { - base.LoadComplete(); - - InteractiveBindable.BindValueChanged(i => handleBase.FadeTo(i.NewValue ? 1 : 0, 200), true); + get => base.Interactive; + set + { + base.Interactive = value; + handleBase.FadeTo(value ? 1 : 0, 200); + } } protected override void Update() diff --git a/osu.Game/Screens/Play/HUD/SongProgressBar.cs b/osu.Game/Screens/Play/HUD/SongProgressBar.cs index ea2e5b2891..40c4e587b9 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressBar.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Threading; @@ -35,13 +34,7 @@ namespace osu.Game.Screens.Play.HUD /// /// Whether the progress bar should allow interaction, ie. to perform seek operations. /// - public bool Interactive - { - get => InteractiveBindable.Value; - set => InteractiveBindable.Value = value; - } - - protected readonly BindableBool InteractiveBindable = new BindableBool(); + public virtual bool Interactive { get; set; } public double StartTime { get; set; } From ee4fe1c0683a26bcb8559ac1918d52a88e6a1276 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 28 Jan 2024 23:11:42 +0300 Subject: [PATCH 140/915] Fix relax mod not handling objects close to a previous slider's follow area --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 40fadfb77e..3679425389 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Mods if (!slider.HeadCircle.IsHit) handleHitCircle(slider.HeadCircle); - requiresHold |= slider.SliderInputManager.IsMouseInFollowArea(true); + requiresHold |= slider.SliderInputManager.IsMouseInFollowArea(slider.Tracking.Value); break; case DrawableSpinner spinner: From 5d456c8d68fe61fa6fc97f8db235b0c6d429a55d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 29 Jan 2024 04:55:21 +0300 Subject: [PATCH 141/915] Rework drawing of graded circles --- .../Expanded/Accuracy/AccuracyCircle.cs | 87 +++++++++++-------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 0aff98df2b..8d32989110 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -169,46 +169,63 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { new CircularProgress { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.X), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyX } - }, - new CircularProgress - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.S), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyX - virtual_ss_percentage } - }, - new CircularProgress - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.A), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyS } - }, - new CircularProgress - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.B), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyA } - }, - new CircularProgress - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.C), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyB } - }, - new CircularProgress - { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.D), InnerRadius = RANK_CIRCLE_RADIUS, Current = { Value = accuracyC } }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.C), + InnerRadius = RANK_CIRCLE_RADIUS, + Current = { Value = accuracyB - accuracyC }, + Rotation = (float)accuracyC * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.B), + InnerRadius = RANK_CIRCLE_RADIUS, + Current = { Value = accuracyA - accuracyB }, + Rotation = (float)accuracyB * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.A), + InnerRadius = RANK_CIRCLE_RADIUS, + Current = { Value = accuracyS - accuracyA }, + Rotation = (float)accuracyA * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.S), + InnerRadius = RANK_CIRCLE_RADIUS, + Current = { Value = accuracyX - accuracyS - virtual_ss_percentage }, + Rotation = (float)accuracyS * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.X), + InnerRadius = RANK_CIRCLE_RADIUS, + Current = { Value = 1f - (accuracyX - virtual_ss_percentage) }, + Rotation = (float)(accuracyX - virtual_ss_percentage) * 360 + }, new RankNotch((float)accuracyX), new RankNotch((float)(accuracyX - virtual_ss_percentage)), new RankNotch((float)accuracyS), From 32b0e0b7380fcb54219fea66b4f46f2a83ece1e1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 29 Jan 2024 05:05:18 +0300 Subject: [PATCH 142/915] Remove RankNotch --- .../Expanded/Accuracy/AccuracyCircle.cs | 33 ++++++------- .../Ranking/Expanded/Accuracy/RankNotch.cs | 49 ------------------- 2 files changed, 14 insertions(+), 68 deletions(-) delete mode 100644 osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 8d32989110..7bd586ebb7 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -76,9 +76,9 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy private const double virtual_ss_percentage = 0.01; /// - /// The width of a in terms of accuracy. + /// The width of a solid "notch" in terms of accuracy that appears at the ends of the rank circles to add separation. /// - public const double NOTCH_WIDTH_PERCENTAGE = 1.0 / 360; + public const float NOTCH_WIDTH_PERCENTAGE = 2f / 360; /// /// The easing for the circle filling transforms. @@ -174,7 +174,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.D), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyC } + Current = { Value = accuracyC - NOTCH_WIDTH_PERCENTAGE }, + Rotation = NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 }, new CircularProgress { @@ -183,8 +184,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.C), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyB - accuracyC }, - Rotation = (float)accuracyC * 360 + Current = { Value = accuracyB - accuracyC - NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)accuracyC * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 }, new CircularProgress { @@ -193,8 +194,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.B), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyA - accuracyB }, - Rotation = (float)accuracyB * 360 + Current = { Value = accuracyA - accuracyB - NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)accuracyB * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 }, new CircularProgress { @@ -203,8 +204,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.A), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyS - accuracyA }, - Rotation = (float)accuracyA * 360 + Current = { Value = accuracyS - accuracyA - NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)accuracyA * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 }, new CircularProgress { @@ -213,8 +214,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.S), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyX - accuracyS - virtual_ss_percentage }, - Rotation = (float)accuracyS * 360 + Current = { Value = accuracyX - accuracyS - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)accuracyS * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 }, new CircularProgress { @@ -223,15 +224,9 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.X), InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = 1f - (accuracyX - virtual_ss_percentage) }, - Rotation = (float)(accuracyX - virtual_ss_percentage) * 360 + Current = { Value = 1f - (accuracyX - virtual_ss_percentage) - NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)(accuracyX - virtual_ss_percentage) * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 }, - new RankNotch((float)accuracyX), - new RankNotch((float)(accuracyX - virtual_ss_percentage)), - new RankNotch((float)accuracyS), - new RankNotch((float)accuracyA), - new RankNotch((float)accuracyB), - new RankNotch((float)accuracyC), new BufferedContainer { Name = "Graded circle mask", diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs deleted file mode 100644 index 244acbe8b1..0000000000 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs +++ /dev/null @@ -1,49 +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 osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osuTK; - -namespace osu.Game.Screens.Ranking.Expanded.Accuracy -{ - /// - /// A solid "notch" of the that appears at the ends of the rank circles to add separation. - /// - public partial class RankNotch : CompositeDrawable - { - private readonly float position; - - public RankNotch(float position) - { - this.position = position; - - RelativeSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Rotation = position * 360f, - Child = new Box - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Y, - Height = AccuracyCircle.RANK_CIRCLE_RADIUS, - Width = (float)AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 360f, - Colour = OsuColour.Gray(0.3f), - EdgeSmoothness = new Vector2(1f) - } - }; - } - } -} From 5783838b07df8420916904ab307f91b23fb8a6ad Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 29 Jan 2024 05:14:24 +0300 Subject: [PATCH 143/915] Move graded circles into a separate class --- .../Expanded/Accuracy/AccuracyCircle.cs | 105 ++-------------- .../Expanded/Accuracy/GradedCircles.cs | 113 ++++++++++++++++++ 2 files changed, 120 insertions(+), 98 deletions(-) create mode 100644 osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 7bd586ebb7..3141810894 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -20,7 +20,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; -using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.Ranking.Expanded.Accuracy @@ -73,7 +72,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// /// SS is displayed as a 1% region, otherwise it would be invisible. /// - private const double virtual_ss_percentage = 0.01; + public const double VIRTUAL_SS_PERCENTAGE = 0.01; /// /// The width of a solid "notch" in terms of accuracy that appears at the ends of the rank circles to add separation. @@ -88,7 +87,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy private readonly ScoreInfo score; private CircularProgress accuracyCircle; - private CircularProgress innerMask; + private GradedCircles gradedCircles; private Container badges; private RankText rankText; @@ -157,96 +156,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#7CF6FF"), Color4Extensions.FromHex("#BAFFA9")), InnerRadius = accuracy_circle_radius, }, - new BufferedContainer - { - Name = "Graded circles", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.8f), - Padding = new MarginPadding(2), - Children = new Drawable[] - { - new CircularProgress - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.D), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyC - NOTCH_WIDTH_PERCENTAGE }, - Rotation = NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 - }, - new CircularProgress - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.C), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyB - accuracyC - NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)accuracyC * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 - }, - new CircularProgress - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.B), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyA - accuracyB - NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)accuracyB * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 - }, - new CircularProgress - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.A), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyS - accuracyA - NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)accuracyA * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 - }, - new CircularProgress - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.S), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = accuracyX - accuracyS - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)accuracyS * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 - }, - new CircularProgress - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.X), - InnerRadius = RANK_CIRCLE_RADIUS, - Current = { Value = 1f - (accuracyX - virtual_ss_percentage) - NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)(accuracyX - virtual_ss_percentage) * 360 + NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 - }, - new BufferedContainer - { - Name = "Graded circle mask", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(1), - Blending = new BlendingParameters - { - Source = BlendingType.DstColor, - Destination = BlendingType.OneMinusSrcColor, - SourceAlpha = BlendingType.One, - DestinationAlpha = BlendingType.SrcAlpha - }, - Child = innerMask = new CircularProgress - { - RelativeSizeAxes = Axes.Both, - InnerRadius = RANK_CIRCLE_RADIUS - 0.02f, - } - } - } - }, + gradedCircles = new GradedCircles(accuracyC, accuracyB, accuracyA, accuracyS, accuracyX), badges = new Container { Name = "Rank badges", @@ -259,7 +169,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy new RankBadge(accuracyB, Interpolation.Lerp(accuracyB, accuracyA, 0.5), getRank(ScoreRank.B)), // The S and A badges are moved down slightly to prevent collision with the SS badge. new RankBadge(accuracyA, Interpolation.Lerp(accuracyA, accuracyS, 0.25), getRank(ScoreRank.A)), - new RankBadge(accuracyS, Interpolation.Lerp(accuracyS, (accuracyX - virtual_ss_percentage), 0.25), getRank(ScoreRank.S)), + new RankBadge(accuracyS, Interpolation.Lerp(accuracyS, (accuracyX - VIRTUAL_SS_PERCENTAGE), 0.25), getRank(ScoreRank.S)), new RankBadge(accuracyX, accuracyX, getRank(ScoreRank.X)), } }, @@ -301,8 +211,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy }); } - using (BeginDelayedSequence(RANK_CIRCLE_TRANSFORM_DELAY)) - innerMask.FillTo(1f, RANK_CIRCLE_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING); + gradedCircles.Transform(); using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY)) { @@ -331,7 +240,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH) targetAccuracy = 1; else - targetAccuracy = Math.Min(accuracyX - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy); + targetAccuracy = Math.Min(accuracyX - VIRTUAL_SS_PERCENTAGE - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy); // The accuracy circle gauge visually fills up a bit too much. // This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases. @@ -368,7 +277,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy if (badge.Accuracy > score.Accuracy) continue; - using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(accuracyX - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION)) + using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(accuracyX - VIRTUAL_SS_PERCENTAGE, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION)) { badge.Appear(); diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs new file mode 100644 index 0000000000..51c4237528 --- /dev/null +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs @@ -0,0 +1,113 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Scoring; +using osuTK; + +namespace osu.Game.Screens.Ranking.Expanded.Accuracy +{ + public partial class GradedCircles : BufferedContainer + { + private readonly CircularProgress innerMask; + + public GradedCircles(double accuracyC, double accuracyB, double accuracyA, double accuracyS, double accuracyX) + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Both; + Size = new Vector2(0.8f); + Padding = new MarginPadding(2); + Children = new Drawable[] + { + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.D), + InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, + Current = { Value = accuracyC - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, + Rotation = AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.C), + InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, + Current = { Value = accuracyB - accuracyC - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)accuracyC * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.B), + InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, + Current = { Value = accuracyA - accuracyB - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)accuracyB * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.A), + InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, + Current = { Value = accuracyS - accuracyA - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)accuracyA * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.S), + InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, + Current = { Value = accuracyX - accuracyS - AccuracyCircle.VIRTUAL_SS_PERCENTAGE - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)accuracyS * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + }, + new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.ForRank(ScoreRank.X), + InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, + Current = { Value = 1f - (accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE) - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, + Rotation = (float)(accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE) * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + }, + new BufferedContainer + { + Name = "Graded circle mask", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(1), + Blending = new BlendingParameters + { + Source = BlendingType.DstColor, + Destination = BlendingType.OneMinusSrcColor, + SourceAlpha = BlendingType.One, + DestinationAlpha = BlendingType.SrcAlpha + }, + Child = innerMask = new CircularProgress + { + RelativeSizeAxes = Axes.Both, + InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS - 0.02f, + } + } + }; + } + + public void Transform() + { + using (BeginDelayedSequence(AccuracyCircle.RANK_CIRCLE_TRANSFORM_DELAY)) + innerMask.FillTo(1f, AccuracyCircle.RANK_CIRCLE_TRANSFORM_DURATION, AccuracyCircle.ACCURACY_TRANSFORM_EASING); + } + } +} From 9c411ad48d81fa384619a6eb8c49c3e56f760fbc Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 29 Jan 2024 05:19:28 +0300 Subject: [PATCH 144/915] Simplify notch math --- .../Ranking/Expanded/Accuracy/GradedCircles.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs index 51c4237528..5241a4d983 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = OsuColour.ForRank(ScoreRank.D), InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, Current = { Value = accuracyC - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + Rotation = AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 180 }, new CircularProgress { @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = OsuColour.ForRank(ScoreRank.C), InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, Current = { Value = accuracyB - accuracyC - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)accuracyC * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + Rotation = (float)(accuracyC + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, new CircularProgress { @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = OsuColour.ForRank(ScoreRank.B), InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, Current = { Value = accuracyA - accuracyB - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)accuracyB * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + Rotation = (float)(accuracyB + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, new CircularProgress { @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = OsuColour.ForRank(ScoreRank.A), InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, Current = { Value = accuracyS - accuracyA - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)accuracyA * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + Rotation = (float)(accuracyA + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, new CircularProgress { @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = OsuColour.ForRank(ScoreRank.S), InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, Current = { Value = accuracyX - accuracyS - AccuracyCircle.VIRTUAL_SS_PERCENTAGE - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)accuracyS * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + Rotation = (float)(accuracyS + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, new CircularProgress { @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = OsuColour.ForRank(ScoreRank.X), InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, Current = { Value = 1f - (accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE) - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)(accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE) * 360 + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f * 360 + Rotation = (float)(accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, new BufferedContainer { From 809ca81b9ccba45aa1ea29fe4645805b8e32e2e7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 29 Jan 2024 05:29:29 +0300 Subject: [PATCH 145/915] Add TestSceneGradedCircles --- .../Visual/Ranking/TestSceneGradedCircles.cs | 44 +++++++++++++++++++ .../Expanded/Accuracy/GradedCircles.cs | 6 +++ 2 files changed, 50 insertions(+) create mode 100644 osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs b/osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs new file mode 100644 index 0000000000..87fbca5c44 --- /dev/null +++ b/osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs @@ -0,0 +1,44 @@ +// 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.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Ranking.Expanded.Accuracy; +using osuTK; + +namespace osu.Game.Tests.Visual.Ranking +{ + public partial class TestSceneGradedCircles : OsuTestScene + { + private readonly GradedCircles ring; + + public TestSceneGradedCircles() + { + ScoreProcessor scoreProcessor = new OsuRuleset().CreateScoreProcessor(); + double accuracyX = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.X); + double accuracyS = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.S); + + double accuracyA = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.A); + double accuracyB = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.B); + double accuracyC = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.C); + + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(400), + Child = ring = new GradedCircles(accuracyC, accuracyB, accuracyA, accuracyS, accuracyX) + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + AddSliderStep("Progress", 0.0, 1.0, 1.0, p => ring.Progress = p); + } + } +} diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs index 5241a4d983..2ce8c511e0 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs @@ -12,6 +12,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { public partial class GradedCircles : BufferedContainer { + public double Progress + { + get => innerMask.Current.Value; + set => innerMask.Current.Value = value; + } + private readonly CircularProgress innerMask; public GradedCircles(double accuracyC, double accuracyB, double accuracyA, double accuracyS, double accuracyX) From 3987faa21cc80c39b42f465d1ef3f3046e235843 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 29 Jan 2024 06:13:52 +0300 Subject: [PATCH 146/915] Rework GradedCircles to not use BufferedContainer --- .../Expanded/Accuracy/AccuracyCircle.cs | 5 +- .../Expanded/Accuracy/GradedCircles.cs | 118 ++++++++---------- 2 files changed, 52 insertions(+), 71 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 3141810894..5b929554ff 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -77,7 +77,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// /// The width of a solid "notch" in terms of accuracy that appears at the ends of the rank circles to add separation. /// - public const float NOTCH_WIDTH_PERCENTAGE = 2f / 360; + public const double NOTCH_WIDTH_PERCENTAGE = 2.0 / 360; /// /// The easing for the circle filling transforms. @@ -211,7 +211,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy }); } - gradedCircles.Transform(); + using (BeginDelayedSequence(RANK_CIRCLE_TRANSFORM_DELAY)) + gradedCircles.TransformTo(nameof(GradedCircles.Progress), 1.0, RANK_CIRCLE_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING); using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY)) { diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs index 2ce8c511e0..19c7a9b606 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.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 osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -10,15 +11,31 @@ using osuTK; namespace osu.Game.Screens.Ranking.Expanded.Accuracy { - public partial class GradedCircles : BufferedContainer + public partial class GradedCircles : CompositeDrawable { + private double progress; + public double Progress { - get => innerMask.Current.Value; - set => innerMask.Current.Value = value; + get => progress; + set + { + progress = value; + dProgress.RevealProgress = value; + cProgress.RevealProgress = value; + bProgress.RevealProgress = value; + aProgress.RevealProgress = value; + sProgress.RevealProgress = value; + xProgress.RevealProgress = value; + } } - private readonly CircularProgress innerMask; + private readonly GradedCircle dProgress; + private readonly GradedCircle cProgress; + private readonly GradedCircle bProgress; + private readonly GradedCircle aProgress; + private readonly GradedCircle sProgress; + private readonly GradedCircle xProgress; public GradedCircles(double accuracyC, double accuracyB, double accuracyA, double accuracyS, double accuracyX) { @@ -27,93 +44,56 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy RelativeSizeAxes = Axes.Both; Size = new Vector2(0.8f); Padding = new MarginPadding(2); - Children = new Drawable[] + InternalChildren = new Drawable[] { - new CircularProgress + dProgress = new GradedCircle(0.0, accuracyC) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.D), - InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, - Current = { Value = accuracyC - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 180 }, - new CircularProgress + cProgress = new GradedCircle(accuracyC, accuracyB) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.C), - InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, - Current = { Value = accuracyB - accuracyC - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)(accuracyC + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, - new CircularProgress + bProgress = new GradedCircle(accuracyB, accuracyA) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.B), - InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, - Current = { Value = accuracyA - accuracyB - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)(accuracyB + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, - new CircularProgress + aProgress = new GradedCircle(accuracyA, accuracyS) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.A), - InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, - Current = { Value = accuracyS - accuracyA - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)(accuracyA + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, - new CircularProgress + sProgress = new GradedCircle(accuracyS, accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, Colour = OsuColour.ForRank(ScoreRank.S), - InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, - Current = { Value = accuracyX - accuracyS - AccuracyCircle.VIRTUAL_SS_PERCENTAGE - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)(accuracyS + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 }, - new CircularProgress + xProgress = new GradedCircle(accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE, 1.0) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.ForRank(ScoreRank.X), - InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS, - Current = { Value = 1f - (accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE) - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE }, - Rotation = (float)(accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5f) * 360 - }, - new BufferedContainer - { - Name = "Graded circle mask", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(1), - Blending = new BlendingParameters - { - Source = BlendingType.DstColor, - Destination = BlendingType.OneMinusSrcColor, - SourceAlpha = BlendingType.One, - DestinationAlpha = BlendingType.SrcAlpha - }, - Child = innerMask = new CircularProgress - { - RelativeSizeAxes = Axes.Both, - InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS - 0.02f, - } + Colour = OsuColour.ForRank(ScoreRank.X) } }; } - public void Transform() + private partial class GradedCircle : CircularProgress { - using (BeginDelayedSequence(AccuracyCircle.RANK_CIRCLE_TRANSFORM_DELAY)) - innerMask.FillTo(1f, AccuracyCircle.RANK_CIRCLE_TRANSFORM_DURATION, AccuracyCircle.ACCURACY_TRANSFORM_EASING); + public double RevealProgress + { + set => Current.Value = Math.Clamp(value, startProgress, endProgress) - startProgress; + } + + private readonly double startProgress; + private readonly double endProgress; + + public GradedCircle(double startProgress, double endProgress) + { + this.startProgress = startProgress + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5; + this.endProgress = endProgress - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5; + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Both; + InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS; + Rotation = (float)this.startProgress * 360; + } } } } From 0c0ba7abefe04e16f3d153964f7fe8f139ba2373 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 29 Jan 2024 06:28:38 +0300 Subject: [PATCH 147/915] Adjust values to visually match previous --- osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 2 +- osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 5b929554ff..8304e7a542 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// /// Relative width of the rank circles. /// - public const float RANK_CIRCLE_RADIUS = 0.06f; + public const float RANK_CIRCLE_RADIUS = 0.05f; /// /// Relative width of the circle showing the accuracy. diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs index 19c7a9b606..efcb848530 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Origin = Anchor.Centre; RelativeSizeAxes = Axes.Both; Size = new Vector2(0.8f); - Padding = new MarginPadding(2); + Padding = new MarginPadding(2.5f); InternalChildren = new Drawable[] { dProgress = new GradedCircle(0.0, accuracyC) From 9c55498058abbb9b5563319abbc942a186b556cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 15:28:14 +0900 Subject: [PATCH 148/915] r# says hi --- .../NonVisual/Skinning/LegacySkinTextureFallbackTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs b/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs index fbe5a0e4d7..98cb66a234 100644 --- a/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs +++ b/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs @@ -169,9 +169,9 @@ namespace osu.Game.Tests.NonVisual.Skinning public IRenderer Renderer => new DummyRenderer(); public AudioManager AudioManager => null; - public IResourceStore Files => null; - public IResourceStore Resources => null; - public RealmAccess RealmAccess => null; + public IResourceStore Files => null!; + public IResourceStore Resources => null!; + public RealmAccess RealmAccess => null!; public IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore) => textureStore; } } From de32e7815b19d8ea5a19114eebc67d3f85ecaa27 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 14:57:19 +0900 Subject: [PATCH 149/915] Clean up `DrawableHitObject` events on `Dispose` This is just general safeties to avoid cases where components don't correctly unbind events. --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 7 +++++++ osu.Game/Rulesets/Objects/HitObject.cs | 2 ++ 2 files changed, 9 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index bce28361cb..5662fb2293 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -768,6 +768,13 @@ namespace osu.Game.Rulesets.Objects.Drawables if (CurrentSkin != null) CurrentSkin.SourceChanged -= skinSourceChanged; + + // Safeties against shooting in foot in cases where these are bound by external entities (like playfield) that don't clean up. + OnNestedDrawableCreated = null; + OnNewResult = null; + OnRevertResult = null; + DefaultsApplied = null; + HitObjectApplied = null; } public Bindable AnimationStartTime { get; } = new BindableDouble(); diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index ec2a4a31f6..ef8bd08bf4 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -38,6 +38,8 @@ namespace osu.Game.Rulesets.Objects /// /// Invoked after has completed on this . /// + // TODO: This has no implicit unbind flow. Currently, if a Playfield manages HitObjects it will leave a bound event on this and cause the + // playfield to remain in memory. public event Action DefaultsApplied; public readonly Bindable StartTimeBindable = new BindableDouble(); From 76832a1495d2d94fc433e46d7413af69cd9e3463 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 15:15:10 +0900 Subject: [PATCH 150/915] Remove `ScorePerformanceCache` This class was only used in two places, both on the results screen, but was holding references to `OsuPlayfield` game-wide (due to unrelated issues, but still). Because I can't really think of future use cases for this, and running the calculation twice at results screen isn't a huge overhead, let's just do that for now to keep things simple. --- osu.Game/OsuGameBase.cs | 4 -- .../PerformanceBreakdownCalculator.cs | 24 +++++-- .../Difficulty/PerformanceCalculator.cs | 5 ++ osu.Game/Scoring/ScorePerformanceCache.cs | 68 ------------------- .../Statistics/PerformanceStatistic.cs | 20 ++++-- .../Statistics/PerformanceBreakdownChart.cs | 5 +- 6 files changed, 40 insertions(+), 86 deletions(-) delete mode 100644 osu.Game/Scoring/ScorePerformanceCache.cs diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 4e465f59df..2208f7d7ca 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -340,10 +340,6 @@ namespace osu.Game dependencies.Cache(beatmapCache = new BeatmapLookupCache()); base.Content.Add(beatmapCache); - var scorePerformanceManager = new ScorePerformanceCache(); - dependencies.Cache(scorePerformanceManager); - base.Content.Add(scorePerformanceManager); - dependencies.CacheAs(rulesetConfigCache = new RulesetConfigCache(realm, RulesetStore)); var powerStatus = CreateBatteryInfo(); diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs index ad9257d4f3..4563c264f7 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs @@ -21,21 +21,29 @@ namespace osu.Game.Rulesets.Difficulty { private readonly IBeatmap playableBeatmap; private readonly BeatmapDifficultyCache difficultyCache; - private readonly ScorePerformanceCache performanceCache; - public PerformanceBreakdownCalculator(IBeatmap playableBeatmap, BeatmapDifficultyCache difficultyCache, ScorePerformanceCache performanceCache) + public PerformanceBreakdownCalculator(IBeatmap playableBeatmap, BeatmapDifficultyCache difficultyCache) { this.playableBeatmap = playableBeatmap; this.difficultyCache = difficultyCache; - this.performanceCache = performanceCache; } [ItemCanBeNull] public async Task CalculateAsync(ScoreInfo score, CancellationToken cancellationToken = default) { + var attributes = await difficultyCache.GetDifficultyAsync(score.BeatmapInfo!, score.Ruleset, score.Mods, cancellationToken).ConfigureAwait(false); + + var performanceCalculator = score.Ruleset.CreateInstance().CreatePerformanceCalculator(); + + // Performance calculation requires the beatmap and ruleset to be locally available. If not, return a default value. + if (attributes?.Attributes == null || performanceCalculator == null) + return null; + + cancellationToken.ThrowIfCancellationRequested(); + PerformanceAttributes[] performanceArray = await Task.WhenAll( // compute actual performance - performanceCache.CalculatePerformanceAsync(score, cancellationToken), + performanceCalculator.CalculateAsync(score, attributes.Value.Attributes, cancellationToken), // compute performance for perfect play getPerfectPerformance(score, cancellationToken) ).ConfigureAwait(false); @@ -88,8 +96,12 @@ namespace osu.Game.Rulesets.Difficulty cancellationToken ).ConfigureAwait(false); - // ScorePerformanceCache is not used to avoid caching multiple copies of essentially identical perfect performance attributes - return difficulty == null ? null : ruleset.CreatePerformanceCalculator()?.Calculate(perfectPlay, difficulty.Value.Attributes.AsNonNull()); + var performanceCalculator = ruleset.CreatePerformanceCalculator(); + + if (performanceCalculator == null || difficulty == null) + return null; + + return await performanceCalculator.CalculateAsync(perfectPlay, difficulty.Value.Attributes.AsNonNull(), cancellationToken).ConfigureAwait(false); }, cancellationToken); } diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index f5e826f8c7..966da0ff12 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -1,6 +1,8 @@ // 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 System.Threading.Tasks; using osu.Game.Beatmaps; using osu.Game.Scoring; @@ -15,6 +17,9 @@ namespace osu.Game.Rulesets.Difficulty Ruleset = ruleset; } + public Task CalculateAsync(ScoreInfo score, DifficultyAttributes attributes, CancellationToken cancellationToken) + => Task.Run(() => CreatePerformanceAttributes(score, attributes), cancellationToken); + public PerformanceAttributes Calculate(ScoreInfo score, DifficultyAttributes attributes) => CreatePerformanceAttributes(score, attributes); diff --git a/osu.Game/Scoring/ScorePerformanceCache.cs b/osu.Game/Scoring/ScorePerformanceCache.cs deleted file mode 100644 index 1f2b1aeb95..0000000000 --- a/osu.Game/Scoring/ScorePerformanceCache.cs +++ /dev/null @@ -1,68 +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 System.Threading; -using System.Threading.Tasks; -using osu.Framework.Allocation; -using osu.Game.Beatmaps; -using osu.Game.Database; -using osu.Game.Rulesets.Difficulty; - -namespace osu.Game.Scoring -{ - /// - /// A component which performs and acts as a central cache for performance calculations of locally databased scores. - /// Currently not persisted between game sessions. - /// - public partial class ScorePerformanceCache : MemoryCachingComponent - { - [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } = null!; - - protected override bool CacheNullValues => false; - - /// - /// Calculates performance for the given . - /// - /// The score to do the calculation on. - /// An optional to cancel the operation. - public Task CalculatePerformanceAsync(ScoreInfo score, CancellationToken token = default) => - GetAsync(new PerformanceCacheLookup(score), token); - - protected override async Task ComputeValueAsync(PerformanceCacheLookup lookup, CancellationToken token = default) - { - var score = lookup.ScoreInfo; - - var attributes = await difficultyCache.GetDifficultyAsync(score.BeatmapInfo!, score.Ruleset, score.Mods, token).ConfigureAwait(false); - - // Performance calculation requires the beatmap and ruleset to be locally available. If not, return a default value. - if (attributes?.Attributes == null) - return null; - - token.ThrowIfCancellationRequested(); - - return score.Ruleset.CreateInstance().CreatePerformanceCalculator()?.Calculate(score, attributes.Value.Attributes); - } - - public readonly struct PerformanceCacheLookup - { - public readonly ScoreInfo ScoreInfo; - - public PerformanceCacheLookup(ScoreInfo info) - { - ScoreInfo = info; - } - - public override int GetHashCode() - { - var hash = new HashCode(); - - hash.Add(ScoreInfo.Hash); - hash.Add(ScoreInfo.ID); - - return hash.ToHashCode(); - } - } - } -} diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs index 22509b2cea..22c1e26d43 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs @@ -5,10 +5,11 @@ using System; using System.Threading; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Resources.Localisation.Web; using osu.Game.Scoring; @@ -32,7 +33,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics } [BackgroundDependencyLoader] - private void load(ScorePerformanceCache performanceCache) + private void load(BeatmapDifficultyCache difficultyCache, CancellationToken? cancellationToken) { if (score.PP.HasValue) { @@ -40,8 +41,19 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics } else { - performanceCache.CalculatePerformanceAsync(score, cancellationTokenSource.Token) - .ContinueWith(t => Schedule(() => setPerformanceValue(t.GetResultSafely()?.Total)), cancellationTokenSource.Token); + Task.Run(async () => + { + var attributes = await difficultyCache.GetDifficultyAsync(score.BeatmapInfo!, score.Ruleset, score.Mods, cancellationToken ?? default).ConfigureAwait(false); + var performanceCalculator = score.Ruleset.CreateInstance().CreatePerformanceCalculator(); + + // Performance calculation requires the beatmap and ruleset to be locally available. If not, return a default value. + if (attributes?.Attributes == null || performanceCalculator == null) + return; + + var result = await performanceCalculator.CalculateAsync(score, attributes.Value.Attributes, cancellationToken ?? default).ConfigureAwait(false); + + Schedule(() => setPerformanceValue(result.Total)); + }, cancellationToken ?? default); } } diff --git a/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs b/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs index ee0ce6183d..8b13f0951c 100644 --- a/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs +++ b/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs @@ -39,9 +39,6 @@ namespace osu.Game.Screens.Ranking.Statistics private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); - [Resolved] - private ScorePerformanceCache performanceCache { get; set; } - [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } @@ -148,7 +145,7 @@ namespace osu.Game.Screens.Ranking.Statistics spinner.Show(); - new PerformanceBreakdownCalculator(playableBeatmap, difficultyCache, performanceCache) + new PerformanceBreakdownCalculator(playableBeatmap, difficultyCache) .CalculateAsync(score, cancellationTokenSource.Token) .ContinueWith(t => Schedule(() => setPerformanceValue(t.GetResultSafely()))); } From eb90ee5415b05dd827464fcd3c715f731da2df1f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 15:39:31 +0900 Subject: [PATCH 151/915] Add safety in `ResultsScreen.Exit` to ensure `HitEvents` are not holding references This is a catch-all safety disconnecting `ScoreInfo` from `HitObject`s. --- osu.Game/Screens/Ranking/ResultsScreen.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 697d62ad6e..410fdf7090 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -275,6 +275,11 @@ namespace osu.Game.Screens.Ranking if (base.OnExiting(e)) return true; + // This is a stop-gap safety against components holding references to gameplay after exiting the gameplay flow. + // Right now, HitEvents are only used up to the results screen. If this changes in the future we need to remove + // HitObject references from HitEvent. + Score.HitEvents.Clear(); + this.FadeOut(100); return false; } From 760368709a4855d0c64a89b03d455a8dd514b987 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 16:12:00 +0900 Subject: [PATCH 152/915] Mark some delegates as static because we can --- osu.Game.Rulesets.Osu/OsuInputManager.cs | 2 +- osu.Game/Rulesets/UI/RulesetInputManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index ccd388192e..e472de1dfe 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Osu base.ReloadMappings(realmKeyBindings); if (!AllowGameplayInputs) - KeyBindings = KeyBindings.Where(b => b.GetAction() == OsuAction.Smoke).ToList(); + KeyBindings = KeyBindings.Where(static b => b.GetAction() == OsuAction.Smoke).ToList(); } } } diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 041c7a13ae..a08c3bab08 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -218,7 +218,7 @@ namespace osu.Game.Rulesets.UI { base.ReloadMappings(realmKeyBindings); - KeyBindings = KeyBindings.Where(b => RealmKeyBindingStore.CheckValidForGameplay(b.KeyCombination)).ToList(); + KeyBindings = KeyBindings.Where(static b => RealmKeyBindingStore.CheckValidForGameplay(b.KeyCombination)).ToList(); RealmKeyBindingStore.ClearDuplicateBindings(KeyBindings); } } From fb24c663425648481a0e6f2006801cc0165e34dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 16:13:30 +0900 Subject: [PATCH 153/915] Mark `ResultsScreen.Score` as nullable Is nullable in playlist results at very least. --- .../Visual/Gameplay/TestScenePlayerLocalScoreImport.cs | 4 ++-- osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs | 2 +- .../Visual/Playlists/TestScenePlaylistsResultsScreen.cs | 2 +- .../Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs | 2 +- osu.Game/Screens/Play/SpectatorResultsScreen.cs | 2 +- osu.Game/Screens/Ranking/ResultsScreen.cs | 6 ++++-- osu.Game/Screens/Ranking/SoloResultsScreen.cs | 7 +++++++ 7 files changed, 17 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs index fafd1330cc..c645b1b01c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs @@ -138,8 +138,8 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); // Player creates new instance of mods after gameplay to ensure any runtime references to drawables etc. are not retained. - AddAssert("results screen score has copied mods", () => (Player.GetChildScreen() as ResultsScreen)?.Score.Mods.First(), () => Is.Not.SameAs(playerMods.First())); - AddAssert("results screen score has matching", () => (Player.GetChildScreen() as ResultsScreen)?.Score.Mods.First(), () => Is.EqualTo(playerMods.First())); + AddAssert("results screen score has copied mods", () => (Player.GetChildScreen() as ResultsScreen)?.Score?.Mods.First(), () => Is.Not.SameAs(playerMods.First())); + AddAssert("results screen score has matching", () => (Player.GetChildScreen() as ResultsScreen)?.Score?.Mods.First(), () => Is.EqualTo(playerMods.First())); AddUntilStep("score in database", () => Realm.Run(r => r.Find(Player.Score.ScoreInfo.ID) != null)); AddUntilStep("databased score has correct mods", () => Realm.Run(r => r.Find(Player.Score.ScoreInfo.ID))!.Mods.First(), () => Is.EqualTo(playerMods.First())); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 747805edc8..8c7576ff52 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -698,7 +698,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { var scoreInfo = ((ResultsScreen)multiplayerComponents.CurrentScreen).Score; - return !scoreInfo.Passed && scoreInfo.Rank == ScoreRank.F; + return scoreInfo?.Passed == false && scoreInfo.Rank == ScoreRank.F; }); } diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs index e805b03542..25ee20b089 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs @@ -420,7 +420,7 @@ namespace osu.Game.Tests.Visual.Playlists public new LoadingSpinner RightSpinner => base.RightSpinner; public new ScorePanelList ScorePanelList => base.ScorePanelList; - public TestResultsScreen(ScoreInfo score, int roomId, PlaylistItem playlistItem, bool allowRetry = true) + public TestResultsScreen([CanBeNull] ScoreInfo score, int roomId, PlaylistItem playlistItem, bool allowRetry = true) : base(score, roomId, playlistItem, allowRetry) { } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs index aa72394ac9..6a1924dea2 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [Resolved] private RulesetStore rulesets { get; set; } - public PlaylistsResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem, bool allowRetry, bool allowWatchingReplay = true) + public PlaylistsResultsScreen([CanBeNull] ScoreInfo score, long roomId, PlaylistItem playlistItem, bool allowRetry, bool allowWatchingReplay = true) : base(score, allowRetry, allowWatchingReplay) { this.roomId = roomId; diff --git a/osu.Game/Screens/Play/SpectatorResultsScreen.cs b/osu.Game/Screens/Play/SpectatorResultsScreen.cs index 001d3b4bbc..393cbddb34 100644 --- a/osu.Game/Screens/Play/SpectatorResultsScreen.cs +++ b/osu.Game/Screens/Play/SpectatorResultsScreen.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Play private void userBeganPlaying(int userId, SpectatorState state) { - if (userId == Score.UserID) + if (userId == Score?.UserID) { Schedule(() => { diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 410fdf7090..82dade40eb 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -45,6 +46,7 @@ namespace osu.Game.Screens.Ranking public readonly Bindable SelectedScore = new Bindable(); + [CanBeNull] public readonly ScoreInfo Score; protected ScorePanelList ScorePanelList { get; private set; } @@ -69,7 +71,7 @@ namespace osu.Game.Screens.Ranking private Sample popInSample; - protected ResultsScreen(ScoreInfo score, bool allowRetry, bool allowWatchingReplay = true) + protected ResultsScreen([CanBeNull] ScoreInfo score, bool allowRetry, bool allowWatchingReplay = true) { Score = score; this.allowRetry = allowRetry; @@ -278,7 +280,7 @@ namespace osu.Game.Screens.Ranking // This is a stop-gap safety against components holding references to gameplay after exiting the gameplay flow. // Right now, HitEvents are only used up to the results screen. If this changes in the future we need to remove // HitObject references from HitEvent. - Score.HitEvents.Clear(); + Score?.HitEvents.Clear(); this.FadeOut(100); return false; diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index da08a26a58..22d631e137 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -45,12 +46,16 @@ namespace osu.Game.Screens.Ranking { base.LoadComplete(); + Debug.Assert(Score != null); + if (ShowUserStatistics) statisticsSubscription = soloStatisticsWatcher.RegisterForStatisticsUpdateAfter(Score, update => statisticsUpdate.Value = update); } protected override StatisticsPanel CreateStatisticsPanel() { + Debug.Assert(Score != null); + if (ShowUserStatistics) { return new SoloStatisticsPanel(Score) @@ -64,6 +69,8 @@ namespace osu.Game.Screens.Ranking protected override APIRequest? FetchScores(Action>? scoresCallback) { + Debug.Assert(Score != null); + if (Score.BeatmapInfo!.OnlineID <= 0 || Score.BeatmapInfo.Status <= BeatmapOnlineStatus.Pending) return null; From a41ba7c381ba66ca432a34dd4ecc9cd655119772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 Jan 2024 08:43:16 +0100 Subject: [PATCH 154/915] Fix more nullable inspections --- osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs | 4 ++-- osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs | 2 +- osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 3ac4d25028..636cd78d9c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -47,8 +47,8 @@ namespace osu.Game.Tests.Visual.Gameplay seekTo(referenceBeatmap.HitObjects[^1].GetEndTime()); AddUntilStep("results displayed", () => getResultsScreen()?.IsLoaded == true); - AddAssert("score has combo", () => getResultsScreen().Score.Combo > 100); - AddAssert("score has no misses", () => getResultsScreen().Score.Statistics[HitResult.Miss] == 0); + AddAssert("score has combo", () => getResultsScreen().Score!.Combo > 100); + AddAssert("score has no misses", () => getResultsScreen().Score!.Statistics[HitResult.Miss] == 0); AddUntilStep("avatar displayed", () => getAvatar() != null); AddAssert("avatar not clickable", () => getAvatar().ChildrenOfType().First().Action == null); diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs index 459a8b0df5..6590339311 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs @@ -193,7 +193,7 @@ namespace osu.Game.Tests.Visual.Navigation case ScorePresentType.Results: AddUntilStep("wait for results", () => lastWaitedScreen != Game.ScreenStack.CurrentScreen && Game.ScreenStack.CurrentScreen is ResultsScreen); AddStep("store last waited screen", () => lastWaitedScreen = Game.ScreenStack.CurrentScreen); - AddUntilStep("correct score displayed", () => ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score.Equals(getImport())); + AddUntilStep("correct score displayed", () => ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score!.Equals(getImport())); AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Ruleset)); break; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index 866e20d063..5671cbebd7 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -418,7 +418,7 @@ namespace osu.Game.Tests.Visual.Ranking public UnrankedSoloResultsScreen(ScoreInfo score) : base(score, true) { - Score.BeatmapInfo!.OnlineID = 0; + Score!.BeatmapInfo!.OnlineID = 0; Score.BeatmapInfo.Status = BeatmapOnlineStatus.Pending; } From ef94eff5745e577cec54615d6c69522100b20b87 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 16:56:28 +0900 Subject: [PATCH 155/915] Rename `PollingChatClientConnector` to better describe usage --- osu.Game/Online/API/DummyAPIAccess.cs | 2 +- ...llingChatClientConnector.cs => TestChatClientConnector.cs} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game/Tests/{PollingChatClientConnector.cs => TestChatClientConnector.cs} (89%) diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 2d5852b209..3c60513495 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -148,7 +148,7 @@ namespace osu.Game.Online.API public IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => null; - public IChatClient GetChatClient() => new PollingChatClientConnector(this); + public IChatClient GetChatClient() => new TestChatClientConnector(this); public RegistrationRequest.RegistrationRequestErrors? CreateAccount(string email, string username, string password) { diff --git a/osu.Game/Tests/PollingChatClientConnector.cs b/osu.Game/Tests/TestChatClientConnector.cs similarity index 89% rename from osu.Game/Tests/PollingChatClientConnector.cs rename to osu.Game/Tests/TestChatClientConnector.cs index f1b0d9dd7d..40e15b5ef5 100644 --- a/osu.Game/Tests/PollingChatClientConnector.cs +++ b/osu.Game/Tests/TestChatClientConnector.cs @@ -11,7 +11,7 @@ using osu.Game.Online.Chat; namespace osu.Game.Tests { - public class PollingChatClientConnector : PersistentEndpointClientConnector, IChatClient + public class TestChatClientConnector : PersistentEndpointClientConnector, IChatClient { public event Action? ChannelJoined; @@ -29,7 +29,7 @@ namespace osu.Game.Tests // don't really need to do anything special if we poll every second anyway. } - public PollingChatClientConnector(IAPIProvider api) + public TestChatClientConnector(IAPIProvider api) : base(api) { Start(); From 363fd1d54f76c82e639d9394aaa05e1a0cbfa28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 Jan 2024 09:05:03 +0100 Subject: [PATCH 156/915] Remove no longer relevant changes --- .../DevelopmentEndpointConfiguration.cs | 1 - osu.Game/Online/EndpointConfiguration.cs | 5 - .../ExperimentalEndpointConfiguration.cs | 1 - .../WebSocket/OsuClientWebSocket.cs | 154 ------------------ .../Online/ProductionEndpointConfiguration.cs | 1 - 5 files changed, 162 deletions(-) delete mode 100644 osu.Game/Online/Notifications/WebSocket/OsuClientWebSocket.cs diff --git a/osu.Game/Online/DevelopmentEndpointConfiguration.cs b/osu.Game/Online/DevelopmentEndpointConfiguration.cs index 1c78c3c147..5f3c353f4d 100644 --- a/osu.Game/Online/DevelopmentEndpointConfiguration.cs +++ b/osu.Game/Online/DevelopmentEndpointConfiguration.cs @@ -13,7 +13,6 @@ namespace osu.Game.Online SpectatorEndpointUrl = $@"{APIEndpointUrl}/signalr/spectator"; MultiplayerEndpointUrl = $@"{APIEndpointUrl}/signalr/multiplayer"; MetadataEndpointUrl = $@"{APIEndpointUrl}/signalr/metadata"; - NotificationsWebSocketEndpointUrl = "wss://dev.ppy.sh/home/notifications/feed"; } } } diff --git a/osu.Game/Online/EndpointConfiguration.cs b/osu.Game/Online/EndpointConfiguration.cs index 6187471b65..f3bcced630 100644 --- a/osu.Game/Online/EndpointConfiguration.cs +++ b/osu.Game/Online/EndpointConfiguration.cs @@ -44,10 +44,5 @@ namespace osu.Game.Online /// The endpoint for the SignalR metadata server. /// public string MetadataEndpointUrl { get; set; } - - /// - /// The endpoint for the notifications websocket. - /// - public string NotificationsWebSocketEndpointUrl { get; set; } } } diff --git a/osu.Game/Online/ExperimentalEndpointConfiguration.cs b/osu.Game/Online/ExperimentalEndpointConfiguration.cs index bc65fd63f3..c3d0014c8b 100644 --- a/osu.Game/Online/ExperimentalEndpointConfiguration.cs +++ b/osu.Game/Online/ExperimentalEndpointConfiguration.cs @@ -14,7 +14,6 @@ namespace osu.Game.Online SpectatorEndpointUrl = "https://spectator.ppy.sh/spectator"; MultiplayerEndpointUrl = "https://spectator.ppy.sh/multiplayer"; MetadataEndpointUrl = "https://spectator.ppy.sh/metadata"; - NotificationsWebSocketEndpointUrl = "wss://notify.ppy.sh"; } } } diff --git a/osu.Game/Online/Notifications/WebSocket/OsuClientWebSocket.cs b/osu.Game/Online/Notifications/WebSocket/OsuClientWebSocket.cs deleted file mode 100644 index 965f606bdc..0000000000 --- a/osu.Game/Online/Notifications/WebSocket/OsuClientWebSocket.cs +++ /dev/null @@ -1,154 +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 System.Diagnostics; -using System.Net; -using System.Net.WebSockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Newtonsoft.Json; -using osu.Framework.Extensions.TypeExtensions; -using osu.Framework.Logging; -using osu.Game.Online.API; - -namespace osu.Game.Online.Notifications.WebSocket -{ - public class OsuClientWebSocket : IAsyncDisposable - { - public event Func? MessageReceived; - public event Func? Closed; - - private readonly string endpoint; - private readonly ClientWebSocket socket; - - private CancellationTokenSource? linkedTokenSource = null; - - public OsuClientWebSocket(IAPIProvider api, string endpoint) - { - socket = new ClientWebSocket(); - socket.Options.SetRequestHeader(@"Authorization", @$"Bearer {api.AccessToken}"); - socket.Options.Proxy = WebRequest.DefaultWebProxy; - if (socket.Options.Proxy != null) - socket.Options.Proxy.Credentials = CredentialCache.DefaultCredentials; - - this.endpoint = endpoint; - } - - public async Task ConnectAsync(CancellationToken cancellationToken) - { - if (socket.State == WebSocketState.Connecting || socket.State == WebSocketState.Open) - throw new InvalidOperationException("Connection is already opened"); - - Debug.Assert(linkedTokenSource == null); - linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - - await socket.ConnectAsync(new Uri(endpoint), linkedTokenSource.Token).ConfigureAwait(false); - runReadLoop(linkedTokenSource.Token); - } - - private void runReadLoop(CancellationToken cancellationToken) => Task.Factory.StartNew(async () => - { - byte[] buffer = new byte[1024]; - StringBuilder messageResult = new StringBuilder(); - - while (!cancellationToken.IsCancellationRequested) - { - try - { - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false); - - switch (result.MessageType) - { - case WebSocketMessageType.Text: - messageResult.Append(Encoding.UTF8.GetString(buffer[..result.Count])); - - if (result.EndOfMessage) - { - SocketMessage? message = JsonConvert.DeserializeObject(messageResult.ToString()); - messageResult.Clear(); - - Debug.Assert(message != null); - - if (message.Error != null) - { - Logger.Log($"{GetType().ReadableName()} error: {message.Error}", LoggingTarget.Network); - break; - } - - await invokeMessageReceived(message).ConfigureAwait(false); - } - - break; - - case WebSocketMessageType.Binary: - throw new NotImplementedException("Binary message type not supported."); - - case WebSocketMessageType.Close: - throw new WebException("Connection closed by remote host."); - } - } - catch (Exception ex) - { - await invokeClosed(ex).ConfigureAwait(false); - return; - } - } - }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default); - - private async Task invokeMessageReceived(SocketMessage message) - { - if (MessageReceived == null) - return; - - var invocationList = MessageReceived.GetInvocationList(); - - // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop - foreach (Func handler in invocationList) - await handler.Invoke(message).ConfigureAwait(false); - } - - private async Task invokeClosed(Exception ex) - { - if (Closed == null) - return; - - var invocationList = Closed.GetInvocationList(); - - // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop - foreach (Func handler in invocationList) - await handler.Invoke(ex).ConfigureAwait(false); - } - - public Task SendMessage(SocketMessage message, CancellationToken cancellationToken) - { - if (socket.State != WebSocketState.Open) - return Task.CompletedTask; - - return socket.SendAsync(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message)), WebSocketMessageType.Text, true, cancellationToken); - } - - public async Task DisconnectAsync() - { - linkedTokenSource?.Cancel(); - await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, @"Disconnecting", CancellationToken.None).ConfigureAwait(false); - linkedTokenSource?.Dispose(); - linkedTokenSource = null; - } - - public async ValueTask DisposeAsync() - { - try - { - await DisconnectAsync().ConfigureAwait(false); - } - catch - { - // Closure can fail if the connection is aborted. Don't really care since it's disposed anyway. - } - - socket.Dispose(); - } - } -} diff --git a/osu.Game/Online/ProductionEndpointConfiguration.cs b/osu.Game/Online/ProductionEndpointConfiguration.cs index a26a25bce5..0244761b65 100644 --- a/osu.Game/Online/ProductionEndpointConfiguration.cs +++ b/osu.Game/Online/ProductionEndpointConfiguration.cs @@ -13,7 +13,6 @@ namespace osu.Game.Online SpectatorEndpointUrl = "https://spectator.ppy.sh/spectator"; MultiplayerEndpointUrl = "https://spectator.ppy.sh/multiplayer"; MetadataEndpointUrl = "https://spectator.ppy.sh/metadata"; - NotificationsWebSocketEndpointUrl = "wss://notify.ppy.sh"; } } } From 96811a88749b7cc763f721ecebca20006ed08289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 Jan 2024 09:13:44 +0100 Subject: [PATCH 157/915] Fix `APIAccess` spamming requests while waiting for second factor --- osu.Game/Online/API/APIAccess.cs | 60 +++++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 8b369d0f3f..52506e4b12 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -269,42 +269,44 @@ namespace osu.Game.Online.API } } - var userReq = new GetMeRequest(); - userReq.Failure += ex => + if (state.Value != APIState.RequiresSecondFactorAuth) { - if (ex is APIException) + var userReq = new GetMeRequest(); + userReq.Failure += ex => { - LastLoginError = ex; - log.Add($@"Login failed for username {ProvidedUsername} on user retrieval ({LastLoginError.Message})!"); - Logout(); - } - else if (ex is WebException webException && webException.Message == @"Unauthorized") + if (ex is APIException) + { + LastLoginError = ex; + log.Add($@"Login failed for username {ProvidedUsername} on user retrieval ({LastLoginError.Message})!"); + Logout(); + } + else if (ex is WebException webException && webException.Message == @"Unauthorized") + { + log.Add(@"Login no longer valid"); + Logout(); + } + else + { + state.Value = APIState.Failing; + } + }; + userReq.Success += me => { - log.Add(@"Login no longer valid"); - Logout(); - } - else + me.Status.Value = configStatus.Value ?? UserStatus.Online; + + setLocalUser(me); + + state.Value = me.SessionVerified ? APIState.Online : APIState.RequiresSecondFactorAuth; + failureCount = 0; + }; + + if (!handleRequest(userReq)) { state.Value = APIState.Failing; + return; } - }; - userReq.Success += me => - { - me.Status.Value = configStatus.Value ?? UserStatus.Online; - - setLocalUser(me); - - state.Value = me.SessionVerified ? APIState.Online : APIState.RequiresSecondFactorAuth; - failureCount = 0; - }; - - if (!handleRequest(userReq)) - { - state.Value = APIState.Failing; - return; } - - if (state.Value == APIState.RequiresSecondFactorAuth) + else { if (string.IsNullOrEmpty(SecondFactorCode)) return; From 6a469f2cb6e45ec46c435682dc99e6e0d09b3a82 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 17:18:17 +0900 Subject: [PATCH 158/915] Use `switch` instead of `if-else` --- osu.Game/Online/API/APIAccess.cs | 114 +++++++++++++++++-------------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 52506e4b12..d3707fe74d 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -269,69 +269,79 @@ namespace osu.Game.Online.API } } - if (state.Value != APIState.RequiresSecondFactorAuth) + switch (state.Value) { - var userReq = new GetMeRequest(); - userReq.Failure += ex => + case APIState.RequiresSecondFactorAuth: { - if (ex is APIException) + if (string.IsNullOrEmpty(SecondFactorCode)) + return; + + state.Value = APIState.Connecting; + LastLoginError = null; + + var verificationRequest = new VerifySessionRequest(SecondFactorCode); + + verificationRequest.Success += () => state.Value = APIState.Online; + verificationRequest.Failure += ex => { + state.Value = APIState.RequiresSecondFactorAuth; LastLoginError = ex; - log.Add($@"Login failed for username {ProvidedUsername} on user retrieval ({LastLoginError.Message})!"); - Logout(); - } - else if (ex is WebException webException && webException.Message == @"Unauthorized") - { - log.Add(@"Login no longer valid"); - Logout(); - } - else + SecondFactorCode = null; + }; + + if (!handleRequest(verificationRequest)) { state.Value = APIState.Failing; + return; } - }; - userReq.Success += me => - { - me.Status.Value = configStatus.Value ?? UserStatus.Online; - setLocalUser(me); + if (state.Value != APIState.Online) + return; - state.Value = me.SessionVerified ? APIState.Online : APIState.RequiresSecondFactorAuth; - failureCount = 0; - }; - - if (!handleRequest(userReq)) - { - state.Value = APIState.Failing; - return; - } - } - else - { - if (string.IsNullOrEmpty(SecondFactorCode)) - return; - - state.Value = APIState.Connecting; - LastLoginError = null; - - var verificationRequest = new VerifySessionRequest(SecondFactorCode); - - verificationRequest.Success += () => state.Value = APIState.Online; - verificationRequest.Failure += ex => - { - state.Value = APIState.RequiresSecondFactorAuth; - LastLoginError = ex; - SecondFactorCode = null; - }; - - if (!handleRequest(verificationRequest)) - { - state.Value = APIState.Failing; - return; + break; } - if (state.Value != APIState.Online) - return; + default: + { + var userReq = new GetMeRequest(); + + userReq.Failure += ex => + { + if (ex is APIException) + { + LastLoginError = ex; + log.Add($@"Login failed for username {ProvidedUsername} on user retrieval ({LastLoginError.Message})!"); + Logout(); + } + else if (ex is WebException webException && webException.Message == @"Unauthorized") + { + log.Add(@"Login no longer valid"); + Logout(); + } + else + { + state.Value = APIState.Failing; + } + }; + + userReq.Success += me => + { + me.Status.Value = configStatus.Value ?? UserStatus.Online; + + setLocalUser(me); + + state.Value = me.SessionVerified ? APIState.Online : APIState.RequiresSecondFactorAuth; + failureCount = 0; + }; + + if (!handleRequest(userReq)) + { + state.Value = APIState.Failing; + return; + } + + break; + } } var friendsReq = new GetFriendsRequest(); From 540ff0da5b1192a9f442952973ddb4ae02bdb80c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 17:54:34 +0900 Subject: [PATCH 159/915] Add loading layer when requesting a code reissue --- .../Overlays/Login/SecondFactorAuthForm.cs | 82 ++++++++++++------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/osu.Game/Overlays/Login/SecondFactorAuthForm.cs b/osu.Game/Overlays/Login/SecondFactorAuthForm.cs index 566587a541..dcd3119f33 100644 --- a/osu.Game/Overlays/Login/SecondFactorAuthForm.cs +++ b/osu.Game/Overlays/Login/SecondFactorAuthForm.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.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,12 +18,14 @@ using osuTK; namespace osu.Game.Overlays.Login { - public partial class SecondFactorAuthForm : FillFlowContainer + public partial class SecondFactorAuthForm : Container { private OsuTextBox codeTextBox = null!; private LinkFlowContainer explainText = null!; private ErrorTextFlowContainer errorText = null!; + private LoadingLayer loading = null!; + [Resolved] private IAPIProvider api { get; set; } = null!; @@ -31,8 +34,6 @@ namespace osu.Game.Overlays.Login { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - Spacing = new Vector2(0, SettingsSection.ITEM_SPACING); Children = new Drawable[] { @@ -40,42 +41,56 @@ namespace osu.Game.Overlays.Login { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, Direction = FillDirection.Vertical, - Spacing = new Vector2(0f, SettingsSection.ITEM_SPACING), + Spacing = new Vector2(0, SettingsSection.ITEM_SPACING), Children = new Drawable[] { - new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Regular)) + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Text = "An email has been sent to you with a verification code. Enter the code.", + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0f, SettingsSection.ITEM_SPACING), + Children = new Drawable[] + { + new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Regular)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = "An email has been sent to you with a verification code. Enter the code.", + }, + codeTextBox = new OsuTextBox + { + PlaceholderText = "Enter code", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + }, + explainText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Regular)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + errorText = new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = 0, + }, + }, }, - codeTextBox = new OsuTextBox - { - PlaceholderText = "Enter code", - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - }, - explainText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Regular)) + new LinkFlowContainer { + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }, - errorText = new ErrorTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Alpha = 0, - }, - }, + } }, - new LinkFlowContainer + loading = new LoadingLayer(true) { - Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, + Padding = new MarginPadding { Vertical = -SettingsSection.ITEM_SPACING }, + } }; explainText.AddParagraph(UserVerificationStrings.BoxInfoCheckSpam); @@ -85,9 +100,20 @@ namespace osu.Game.Overlays.Login explainText.AddText(". You can also "); explainText.AddLink(UserVerificationStrings.BoxInfoReissueLink, () => { + loading.Show(); + var reissueRequest = new ReissueVerificationCodeRequest(); - reissueRequest.Failure += ex => Logger.Error(ex, @"Failed to retrieve new verification code."); - api.Perform(reissueRequest); + reissueRequest.Failure += ex => + { + Logger.Error(ex, @"Failed to retrieve new verification code."); + loading.Hide(); + }; + reissueRequest.Success += () => + { + loading.Hide(); + }; + + Task.Run(() => api.Perform(reissueRequest)); }); explainText.AddText(" or "); explainText.AddLink(UserVerificationStrings.BoxInfoLogoutLink, () => { api.Logout(); }); From dc28a6b873f0af9835f991acb805e647123e8446 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 19:33:07 +0900 Subject: [PATCH 160/915] Update resources --- osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index e46b92795a..a552b22c11 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Backgrounds private Background background; private int currentDisplay; - private const int background_count = 7; + private const int background_count = 8; private IBindable user; private Bindable skin; private Bindable source; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6f71424130..48ba7beb7d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From 8341da7586126de557904f4db124113d33ef9e4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 19:41:03 +0900 Subject: [PATCH 161/915] Revert "Remove dead code" (mostly) This reverts commit 6070eac6eec64852a8aa27a2c283cf9388c6ad5c. --- osu.Game/Skinning/LegacyJudgementPieceNew.cs | 2 +- osu.Game/Skinning/LegacyJudgementPieceOld.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Skinning/LegacyJudgementPieceNew.cs b/osu.Game/Skinning/LegacyJudgementPieceNew.cs index bd1508b4a6..5ff28726c0 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceNew.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceNew.cs @@ -53,7 +53,7 @@ namespace osu.Game.Skinning if (!result.IsMiss()) { //new judgement shows old as a temporary effect - AddInternal(temporaryOldStyle = new LegacyJudgementPieceOld(result, createMainDrawable, 1.05f) + AddInternal(temporaryOldStyle = new LegacyJudgementPieceOld(result, createMainDrawable, 1.05f, true) { Blending = BlendingParameters.Additive, Anchor = Anchor.Centre, diff --git a/osu.Game/Skinning/LegacyJudgementPieceOld.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs index c15ff041d1..edfb5a23ec 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceOld.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -18,14 +18,16 @@ namespace osu.Game.Skinning private readonly HitResult result; private readonly float finalScale; + private readonly bool forceTransforms; [Resolved] private ISkinSource skin { get; set; } = null!; - public LegacyJudgementPieceOld(HitResult result, Func createMainDrawable, float finalScale = 1f) + public LegacyJudgementPieceOld(HitResult result, Func createMainDrawable, float finalScale = 1f, bool forceTransforms = false) { this.result = result; this.finalScale = finalScale; + this.forceTransforms = forceTransforms; AutoSizeAxes = Axes.Both; Origin = Anchor.Centre; @@ -45,6 +47,10 @@ namespace osu.Game.Skinning this.FadeInFromZero(fade_in_length); + // legacy judgements don't play any transforms if they are an animation.... UNLESS they are the temporary displayed judgement from new piece. + if (animation?.FrameCount > 1 && !forceTransforms) + return; + if (result.IsMiss()) { decimal? legacyVersion = skin.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value; @@ -95,12 +101,6 @@ namespace osu.Game.Skinning private bool isMissedTick() => result.IsMiss() && result != HitResult.Miss; - private void applyMissedTickScaling() - { - this.ScaleTo(0.6f); - this.ScaleTo(0.3f, 100, Easing.In); - } - public Drawable GetAboveHitObjectsProxiedContent() => CreateProxy(); } } From 1efdf2ae253a9844dc437c6f26767efb17bfb06a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 19:45:56 +0900 Subject: [PATCH 162/915] Update framework --- 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 969fd52340..da404599ef 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index bbcabc6360..0855c0c6d6 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From 8a11ff122712a15a2f466f01434af76e00ac98f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 Jan 2024 11:46:45 +0100 Subject: [PATCH 163/915] Apply local precision workaround to editor effect section --- osu.Game/Screens/Edit/Timing/EffectSection.cs | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index 7e484433f7..f321f7eeb0 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -52,17 +52,38 @@ namespace osu.Game.Screens.Edit.Timing protected override void OnControlPointChanged(ValueChangedEvent point) { - if (point.NewValue != null) + scrollSpeedSlider.Current.ValueChanged -= updateControlPointFromSlider; + + if (point.NewValue is EffectControlPoint newEffectPoint) { isRebinding = true; - kiai.Current = point.NewValue.KiaiModeBindable; - scrollSpeedSlider.Current = point.NewValue.ScrollSpeedBindable; + kiai.Current = newEffectPoint.KiaiModeBindable; + scrollSpeedSlider.Current = new BindableDouble + { + MinValue = 0.01, + MaxValue = 10, + Precision = 0.01, + Value = newEffectPoint.ScrollSpeedBindable.Value + }; + scrollSpeedSlider.Current.ValueChanged += updateControlPointFromSlider; + // at this point in time the above is enough to keep the slider control in sync with reality, + // since undo/redo causes `OnControlPointChanged()` to fire. + // whenever that stops being the case, or there is a possibility that the scroll speed could be changed + // by something else other than this control, this code should probably be revisited to have a binding in the other direction, too. isRebinding = false; } } + private void updateControlPointFromSlider(ValueChangedEvent scrollSpeed) + { + if (ControlPoint.Value is not EffectControlPoint effectPoint || isRebinding) + return; + + effectPoint.ScrollSpeedBindable.Value = scrollSpeed.NewValue; + } + protected override EffectControlPoint CreatePoint() { var reference = Beatmap.ControlPointInfo.EffectPointAt(SelectedGroup.Value.Time); From 034f8c0388c84333961d5ad6702c044dc83e519f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 20:36:59 +0900 Subject: [PATCH 164/915] Also fix spinner case --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index bf4b07eaab..9a98286738 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -153,7 +153,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { if (tracking.NewValue) { - if (!spinningSample.IsPlaying) + if (!spinningSample.RequestedPlaying) spinningSample.Play(); spinningSample.VolumeTo(1, 300); From f2546d72c2616f4d3d746d27b9fea061998591d7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 Jan 2024 20:45:51 +0900 Subject: [PATCH 165/915] Fix osu! logo being mispositioned in song select on very wide resolutions --- osu.Game/Screens/Select/SongSelect.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index bf1724995a..50467bc089 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -642,7 +642,11 @@ namespace osu.Game.Screens.Select { base.LogoArriving(logo, resuming); - Vector2 position = new Vector2(0.95f, 0.96f); + logo.Anchor = Anchor.BottomRight; + logo.Origin = Anchor.Centre; + logo.RelativePositionAxes = Axes.None; + + Vector2 position = new Vector2(-76, -36); if (logo.Alpha > 0.8f) { From 16c06169ed077bc493e1856094b76528de1665d6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jan 2024 01:06:32 +0900 Subject: [PATCH 166/915] Update framework --- 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 da404599ef..55ef55ab7d 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index 0855c0c6d6..5b99319499 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From 996ae0ecc1f970ebc60f17653b3cf6b698794dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 Jan 2024 19:17:39 +0100 Subject: [PATCH 167/915] Fix incorrect handling of `StartChatRequest` in websocket chat client Fixes this happening on staging: [network] 2024-01-29 17:48:24 [verbose]: WebSocketNotificationsClientConnector connected! [network] 2024-01-29 17:48:24 [verbose]: WebSocketNotificationsClientConnector connect attempt failed: Can't use WaitSafely from inside an async operation. I'm not sure how I ever allowed that `.WaitSafely()` to be there. It did feel rather dangerous but then I must have forgotten and never noticed it failing. Which is weird because you'd think that would be caught by testing that chat isn't working but I'm pretty sure that I tested that chat *was* indeed working. Anyway now that entire flow is replaced by something that should hopefully be somewhat more sane? It has a whole retry flow with logging now which should be more robust than what was there previously (failing to start to listen to chat events killing the entire websocket connection for very little good reason). --- osu.Game/Online/Chat/WebSocketChatClient.cs | 47 +++++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/osu.Game/Online/Chat/WebSocketChatClient.cs b/osu.Game/Online/Chat/WebSocketChatClient.cs index 05d3b7b3ce..b74f8bec4b 100644 --- a/osu.Game/Online/Chat/WebSocketChatClient.cs +++ b/osu.Game/Online/Chat/WebSocketChatClient.cs @@ -5,9 +5,10 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -26,21 +27,49 @@ namespace osu.Game.Online.Chat private readonly INotificationsClient client; private readonly ConcurrentDictionary channelsMap = new ConcurrentDictionary(); + private CancellationTokenSource? chatStartCancellationSource; + public WebSocketChatClient(IAPIProvider api) { this.api = api; client = api.NotificationsClient; - client.IsConnected.BindValueChanged(start, true); + client.IsConnected.BindValueChanged(onConnectedChanged, true); } - private void start(ValueChangedEvent connected) + private void onConnectedChanged(ValueChangedEvent connected) { - if (!connected.NewValue) - return; + if (connected.NewValue) + { + client.MessageReceived += onMessageReceived; + attemptToStartChat(); + RequestPresence(); + } + else + chatStartCancellationSource?.Cancel(); + } - client.MessageReceived += onMessageReceived; - client.SendAsync(new StartChatRequest()).WaitSafely(); - RequestPresence(); + private void attemptToStartChat() + { + chatStartCancellationSource?.Cancel(); + chatStartCancellationSource = new CancellationTokenSource(); + + Task.Factory.StartNew(async () => + { + while (!chatStartCancellationSource.IsCancellationRequested) + { + try + { + await client.SendAsync(new StartChatRequest()).ConfigureAwait(false); + Logger.Log(@"Now listening to websocket chat messages.", LoggingTarget.Network); + chatStartCancellationSource.Cancel(); + } + catch (Exception ex) + { + Logger.Log($@"Could not start listening to websocket chat messages: {ex}", LoggingTarget.Network); + await Task.Delay(5000).ConfigureAwait(false); + } + } + }, chatStartCancellationSource.Token); } public void RequestPresence() @@ -137,7 +166,7 @@ namespace osu.Game.Online.Chat public void Dispose() { - client.IsConnected.ValueChanged -= start; + client.IsConnected.ValueChanged -= onConnectedChanged; client.MessageReceived -= onMessageReceived; } } From 959cc7c7d91fa288bb98777b73286bc30285a21f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 29 Jan 2024 21:26:36 +0300 Subject: [PATCH 168/915] Rewrite time range computation logic to be completely based on stable code --- .../UI/DrawableTaikoRuleset.cs | 20 ++-------- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 40 +++++++++++++++++-- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 49b0ad811d..77b2b06c0e 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -16,7 +16,6 @@ using osu.Game.Replays; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Rulesets.Timing; @@ -36,6 +35,8 @@ namespace osu.Game.Rulesets.Taiko.UI public new TaikoInputManager KeyBindingInputManager => (TaikoInputManager)base.KeyBindingInputManager; + protected new TaikoPlayfieldAdjustmentContainer PlayfieldAdjustmentContainer => (TaikoPlayfieldAdjustmentContainer)base.PlayfieldAdjustmentContainer; + protected override bool UserScrollSpeedAdjustment => false; private SkinnableDrawable scroller; @@ -68,22 +69,7 @@ namespace osu.Game.Rulesets.Taiko.UI TimeRange.Value = ComputeTimeRange(); } - protected virtual double ComputeTimeRange() - { - // Taiko scrolls at a constant 100px per 1000ms. More notes become visible as the playfield is lengthened. - const float scroll_rate = 10; - - // Since the time range will depend on a positional value, it is referenced to the x480 pixel space. - // Width is used because it defines how many notes fit on the playfield. - // We clamp the ratio to the maximum aspect ratio to keep scroll speed consistent on widths lower than the default. - float ratio = Math.Max(DrawSize.X / 768f, TaikoPlayfieldAdjustmentContainer.MAXIMUM_ASPECT); - - // Stable internally increased the slider velocity of objects by a factor of `VELOCITY_MULTIPLIER`. - // To simulate this, we shrink the time range by that factor here. - // This, when combined with the rest of the scrolling ruleset machinery (see `MultiplierControlPoint` et al.), - // has the effect of increasing each multiplier control point's multiplier by `VELOCITY_MULTIPLIER`, ensuring parity with stable. - return (Playfield.HitObjectContainer.DrawWidth / ratio) * scroll_rate / TaikoBeatmapConverter.VELOCITY_MULTIPLIER; - } + protected virtual double ComputeTimeRange() => PlayfieldAdjustmentContainer.ComputeTimeRange(); protected override void UpdateAfterChildren() { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index c10e505f50..c67f61052c 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.UI; using osuTK; @@ -14,6 +15,8 @@ namespace osu.Game.Rulesets.Taiko.UI public const float MAXIMUM_ASPECT = 16f / 9f; public const float MINIMUM_ASPECT = 5f / 4f; + private const float stable_gamefield_height = 480f; + public readonly IBindable LockPlayfieldAspectRange = new BindableBool(true); public TaikoPlayfieldAdjustmentContainer() @@ -21,6 +24,9 @@ namespace osu.Game.Rulesets.Taiko.UI RelativeSizeAxes = Axes.X; RelativePositionAxes = Axes.Y; Height = TaikoPlayfield.BASE_HEIGHT; + + // Matches stable, see https://github.com/peppy/osu-stable-reference/blob/7519cafd1823f1879c0d9c991ba0e5c7fd3bfa02/osu!/GameModes/Play/Rulesets/Taiko/RulesetTaiko.cs#L514 + Y = 135f / stable_gamefield_height; } protected override void Update() @@ -28,8 +34,6 @@ namespace osu.Game.Rulesets.Taiko.UI base.Update(); const float base_relative_height = TaikoPlayfield.BASE_HEIGHT / 768; - // Matches stable, see https://github.com/peppy/osu-stable-reference/blob/7519cafd1823f1879c0d9c991ba0e5c7fd3bfa02/osu!/GameModes/Play/Rulesets/Taiko/RulesetTaiko.cs#L514 - const float base_position = 135f / 480f; float relativeHeight = base_relative_height; @@ -51,10 +55,38 @@ namespace osu.Game.Rulesets.Taiko.UI // Limit the maximum relative height of the playfield to one-third of available area to avoid it masking out on extreme resolutions. relativeHeight = Math.Min(relativeHeight, 1f / 3f); - Y = base_position; - Scale = new Vector2(Math.Max((Parent!.ChildSize.Y / 768f) * (relativeHeight / base_relative_height), 1f)); Width = 1 / Scale.X; } + + public double ComputeTimeRange() + { + float currentAspect = Parent!.ChildSize.X / Parent!.ChildSize.Y; + + if (LockPlayfieldAspectRange.Value) + currentAspect = Math.Clamp(currentAspect, MINIMUM_ASPECT, MAXIMUM_ASPECT); + + // in a game resolution of 1024x768, stable's scrolling system consists of objects being placed 600px (widthScaled - 40) away from their hit location. + // however, the point at which the object renders at the end of the screen is exactly x=640, but stable makes the object start moving from beyond the screen instead of the boundary point. + // therefore, in lazer we have to adjust the "in length" so that it's in a 640px->160px fashion before passing it down as a "time range". + // see stable's "in length": https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManagerTaiko.cs#L168 + const float stable_hit_location = 160f; + float widthScaled = currentAspect * stable_gamefield_height; + float inLength = widthScaled - stable_hit_location; + + // also in a game resolution of 1024x768, stable makes hit objects scroll from 760px->160px at a duration of 6000ms, divided by slider velocity (i.e. at a rate of 0.1px/ms) + // compare: https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManagerTaiko.cs#L218 + // note: the variable "sv", in the linked reference, is equivalent to MultiplierControlPoint.Multiplier * 100, but since time range is agnostic of velocity, we replace "sv" with 100 below. + float inMsLength = inLength / 100 * 1000; + + // stable multiplies the slider velocity by 1.4x for certain reasons, divide the time range by that factor to achieve similar result. + // for references on how the factor is applied to the time range, see: + // 1. https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManagerTaiko.cs#L79 (DifficultySliderMultiplier multiplied by 1.4x) + // 2. https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManager.cs#L468-L470 (DifficultySliderMultiplier used to calculate SliderScoringPointDistance) + // 3. https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/GameplayElements/HitObjectManager.cs#L248-L250 (SliderScoringPointDistance used to calculate slider velocity, i.e. the "sv" variable from above) + inMsLength /= TaikoBeatmapConverter.VELOCITY_MULTIPLIER; + + return inMsLength; + } } } From acc2614090739ce546bead00deef3ddcfbbeadf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 Jan 2024 20:04:18 +0100 Subject: [PATCH 169/915] Apply alternative solution Fixes the logo flying out of the wrong corner when transitioning from song select to gameplay. Co-authored-by: Dean Herbert --- osu.Game/Screens/Menu/OsuLogo.cs | 7 +++++++ osu.Game/Screens/OsuScreen.cs | 5 ++++- osu.Game/Screens/Select/SongSelect.cs | 3 +-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 25101730e7..f2e2e25fa6 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -486,5 +486,12 @@ namespace osu.Game.Screens.Menu defaultProxyTarget.Add(this); defaultProxyTarget.Add(proxy = CreateProxy()); } + + public void ChangeAnchor(Anchor anchor) + { + var previousAnchor = AnchorPosition; + Anchor = anchor; + Position -= AnchorPosition - previousAnchor; + } } } diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index f719ef67c9..2e8f85423d 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -250,9 +250,12 @@ namespace osu.Game.Screens { logo.Action = null; logo.FadeOut(300, Easing.OutQuint); - logo.Anchor = Anchor.TopLeft; + logo.Origin = Anchor.Centre; + + logo.ChangeAnchor(Anchor.TopLeft); logo.RelativePositionAxes = Axes.Both; + logo.Triangles = true; logo.Ripple = true; } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 50467bc089..a603934a9d 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -642,9 +642,8 @@ namespace osu.Game.Screens.Select { base.LogoArriving(logo, resuming); - logo.Anchor = Anchor.BottomRight; - logo.Origin = Anchor.Centre; logo.RelativePositionAxes = Axes.None; + logo.ChangeAnchor(Anchor.BottomRight); Vector2 position = new Vector2(-76, -36); From 6888cda02cd127ff4baf6159d3c6a7e533184970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 Jan 2024 21:42:38 +0100 Subject: [PATCH 170/915] Make `LegacyScoreDecoder.PopulateMaximumStatistics()` public For `osu-tools` consumption. --- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index e51a95798b..65e2c02655 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -180,7 +180,7 @@ namespace osu.Game.Scoring.Legacy /// /// The score to populate the statistics of. /// The corresponding . - internal static void PopulateMaximumStatistics(ScoreInfo score, WorkingBeatmap workingBeatmap) + public static void PopulateMaximumStatistics(ScoreInfo score, WorkingBeatmap workingBeatmap) { Debug.Assert(score.BeatmapInfo != null); From 87f853fcd270c9fce2f3f5a7368bfb506d060a23 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 30 Jan 2024 00:23:32 +0300 Subject: [PATCH 171/915] Reduce overhead in ScrollingHitObjectContainer --- .../Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 129918da14..39ddb5c753 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -184,9 +184,12 @@ namespace osu.Game.Rulesets.UI.Scrolling // We need to calculate hit object positions (including nested hit objects) as soon as possible after lifetimes // to prevent hit objects displayed in a wrong position for one frame. - // Only AliveObjects need to be considered for layout (reduces overhead in the case of scroll speed changes). - foreach (var obj in AliveObjects) + // Only AliveEntries need to be considered for layout (reduces overhead in the case of scroll speed changes). + // We are not using AliveObjects directly to avoid selection/sorting overhead since we don't care about the order at which positions will be updated. + foreach (var entry in AliveEntries) { + var obj = entry.Drawable; + updatePosition(obj, Time.Current); if (layoutComputed.Contains(obj)) From 7dba870518857bb832dbf7b4a034471a3ed45f94 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 30 Jan 2024 03:07:37 +0300 Subject: [PATCH 172/915] Rework Content storage in ColumnFlow --- osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs | 4 ++-- osu.Game.Rulesets.Mania/UI/ColumnFlow.cs | 16 +++++++++------- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 10 +++++----- osu.Game.Rulesets.Mania/UI/Stage.cs | 11 +++++------ 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index fee3ba3e39..db04142915 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Tests { foreach (var stage in stages) { - for (int i = 0; i < stage.Columns.Count; i++) + for (int i = 0; i < stage.Columns.Length; i++) { var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Tests { foreach (var stage in stages) { - for (int i = 0; i < stage.Columns.Count; i++) + for (int i = 0; i < stage.Columns.Length; i++) { var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs b/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs index 8734f8ac8a..1593e8e76f 100644 --- a/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs +++ b/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs @@ -4,8 +4,6 @@ #nullable disable using System; -using System.Collections.Generic; -using System.Linq; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -28,20 +26,21 @@ namespace osu.Game.Rulesets.Mania.UI /// /// All contents added to this . /// - public IReadOnlyList Content => columns.Children.Select(c => c.Count == 0 ? null : (TContent)c.Child).ToList(); + public TContent[] Content { get; } - private readonly FillFlowContainer columns; + private readonly FillFlowContainer> columns; private readonly StageDefinition stageDefinition; public ColumnFlow(StageDefinition stageDefinition) { this.stageDefinition = stageDefinition; + Content = new TContent[stageDefinition.Columns]; AutoSizeAxes = Axes.X; Masking = true; - InternalChild = columns = new FillFlowContainer + InternalChild = columns = new FillFlowContainer> { RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, @@ -49,7 +48,7 @@ namespace osu.Game.Rulesets.Mania.UI }; for (int i = 0; i < stageDefinition.Columns; i++) - columns.Add(new Container { RelativeSizeAxes = Axes.Y }); + columns.Add(new Container { RelativeSizeAxes = Axes.Y }); } private ISkinSource currentSkin; @@ -102,7 +101,10 @@ namespace osu.Game.Rulesets.Mania.UI /// /// The index of the column to set the content of. /// The content. - public void SetContentForColumn(int column, TContent content) => columns[column].Child = content; + public void SetContentForColumn(int column, TContent content) + { + Content[column] = columns[column].Child = content; + } private void updateMobileSizing() { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 314d199944..c8874c8ab3 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.UI stages.Add(newStage); AddNested(newStage); - firstColumnIndex += newStage.Columns.Count; + firstColumnIndex += newStage.Columns.Length; } } @@ -125,9 +125,9 @@ namespace osu.Game.Rulesets.Mania.UI foreach (var stage in stages) { - if (index >= stage.Columns.Count) + if (index >= stage.Columns.Length) { - index -= stage.Columns.Count; + index -= stage.Columns.Length; continue; } @@ -140,7 +140,7 @@ namespace osu.Game.Rulesets.Mania.UI /// /// Retrieves the total amount of columns across all stages in this playfield. /// - public int TotalColumns => stages.Sum(s => s.Columns.Count); + public int TotalColumns => stages.Sum(s => s.Columns.Length); private Stage getStageByColumn(int column) { @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Mania.UI foreach (var stage in stages) { - sum += stage.Columns.Count; + sum += stage.Columns.Length; if (sum > column) return stage; } diff --git a/osu.Game.Rulesets.Mania/UI/Stage.cs b/osu.Game.Rulesets.Mania/UI/Stage.cs index 36286940a8..db06f9dbde 100644 --- a/osu.Game.Rulesets.Mania/UI/Stage.cs +++ b/osu.Game.Rulesets.Mania/UI/Stage.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; @@ -37,7 +36,7 @@ namespace osu.Game.Rulesets.Mania.UI public const float HIT_TARGET_POSITION = 110; - public IReadOnlyList Columns => columnFlow.Content; + public Column[] Columns => columnFlow.Content; private readonly ColumnFlow columnFlow; private readonly JudgementContainer judgements; @@ -184,13 +183,13 @@ namespace osu.Game.Rulesets.Mania.UI NewResult += OnNewResult; } - public override void Add(HitObject hitObject) => Columns.ElementAt(((ManiaHitObject)hitObject).Column - firstColumnIndex).Add(hitObject); + public override void Add(HitObject hitObject) => Columns[((ManiaHitObject)hitObject).Column - firstColumnIndex].Add(hitObject); - public override bool Remove(HitObject hitObject) => Columns.ElementAt(((ManiaHitObject)hitObject).Column - firstColumnIndex).Remove(hitObject); + public override bool Remove(HitObject hitObject) => Columns[((ManiaHitObject)hitObject).Column - firstColumnIndex].Remove(hitObject); - public override void Add(DrawableHitObject h) => Columns.ElementAt(((ManiaHitObject)h.HitObject).Column - firstColumnIndex).Add(h); + public override void Add(DrawableHitObject h) => Columns[((ManiaHitObject)h.HitObject).Column - firstColumnIndex].Add(h); - public override bool Remove(DrawableHitObject h) => Columns.ElementAt(((ManiaHitObject)h.HitObject).Column - firstColumnIndex).Remove(h); + public override bool Remove(DrawableHitObject h) => Columns[((ManiaHitObject)h.HitObject).Column - firstColumnIndex].Remove(h); public void Add(BarLine barLine) => base.Add(barLine); From 8e20eed4ef2783234e54101fd0fa8bd92d5e11fe Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 30 Jan 2024 03:19:27 +0300 Subject: [PATCH 173/915] Don't use LINQ in ReceivePositionalInputAt --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 11 ++++++++++- osu.Game.Rulesets.Mania/UI/Stage.cs | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index c8874c8ab3..0d36f51943 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -42,7 +42,16 @@ namespace osu.Game.Rulesets.Mania.UI } } - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos)); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + { + foreach (var s in stages) + { + if (s.ReceivePositionalInputAt(screenSpacePos)) + return true; + } + + return false; + } public ManiaPlayfield(List stageDefinitions) { diff --git a/osu.Game.Rulesets.Mania/UI/Stage.cs b/osu.Game.Rulesets.Mania/UI/Stage.cs index db06f9dbde..a4a09c9a82 100644 --- a/osu.Game.Rulesets.Mania/UI/Stage.cs +++ b/osu.Game.Rulesets.Mania/UI/Stage.cs @@ -44,7 +44,16 @@ namespace osu.Game.Rulesets.Mania.UI private readonly Drawable barLineContainer; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Columns.Any(c => c.ReceivePositionalInputAt(screenSpacePos)); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + { + foreach (var c in Columns) + { + if (c.ReceivePositionalInputAt(screenSpacePos)) + return true; + } + + return false; + } private readonly int firstColumnIndex; From d895a91cd535328e327752d98576e5d5db9b20ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 Jan 2024 18:40:17 +0900 Subject: [PATCH 174/915] Update endpoints to final production endpoints --- osu.Game/Online/EndpointConfiguration.cs | 16 +++++++--------- .../ExperimentalEndpointConfiguration.cs | 19 ------------------- osu.Game/OsuGameBase.cs | 2 +- 3 files changed, 8 insertions(+), 29 deletions(-) delete mode 100644 osu.Game/Online/ExperimentalEndpointConfiguration.cs diff --git a/osu.Game/Online/EndpointConfiguration.cs b/osu.Game/Online/EndpointConfiguration.cs index f3bcced630..bd3c945124 100644 --- a/osu.Game/Online/EndpointConfiguration.cs +++ b/osu.Game/Online/EndpointConfiguration.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - namespace osu.Game.Online { /// @@ -13,36 +11,36 @@ namespace osu.Game.Online /// /// The base URL for the website. /// - public string WebsiteRootUrl { get; set; } + public string WebsiteRootUrl { get; set; } = string.Empty; /// /// The endpoint for the main (osu-web) API. /// - public string APIEndpointUrl { get; set; } + public string APIEndpointUrl { get; set; } = string.Empty; /// /// The OAuth client secret. /// - public string APIClientSecret { get; set; } + public string APIClientSecret { get; set; } = string.Empty; /// /// The OAuth client ID. /// - public string APIClientID { get; set; } + public string APIClientID { get; set; } = string.Empty; /// /// The endpoint for the SignalR spectator server. /// - public string SpectatorEndpointUrl { get; set; } + public string SpectatorEndpointUrl { get; set; } = string.Empty; /// /// The endpoint for the SignalR multiplayer server. /// - public string MultiplayerEndpointUrl { get; set; } + public string MultiplayerEndpointUrl { get; set; } = string.Empty; /// /// The endpoint for the SignalR metadata server. /// - public string MetadataEndpointUrl { get; set; } + public string MetadataEndpointUrl { get; set; } = string.Empty; } } diff --git a/osu.Game/Online/ExperimentalEndpointConfiguration.cs b/osu.Game/Online/ExperimentalEndpointConfiguration.cs deleted file mode 100644 index c3d0014c8b..0000000000 --- a/osu.Game/Online/ExperimentalEndpointConfiguration.cs +++ /dev/null @@ -1,19 +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.Online -{ - public class ExperimentalEndpointConfiguration : EndpointConfiguration - { - public ExperimentalEndpointConfiguration() - { - WebsiteRootUrl = @"https://osu.ppy.sh"; - APIEndpointUrl = @"https://lazer.ppy.sh"; - APIClientSecret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk"; - APIClientID = "5"; - SpectatorEndpointUrl = "https://spectator.ppy.sh/spectator"; - MultiplayerEndpointUrl = "https://spectator.ppy.sh/multiplayer"; - MetadataEndpointUrl = "https://spectator.ppy.sh/metadata"; - } - } -} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 2208f7d7ca..a2a6322665 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -102,7 +102,7 @@ namespace osu.Game public virtual bool UseDevelopmentServer => DebugUtils.IsDebugBuild; public virtual EndpointConfiguration CreateEndpoints() => - UseDevelopmentServer ? new DevelopmentEndpointConfiguration() : new ExperimentalEndpointConfiguration(); + UseDevelopmentServer ? new DevelopmentEndpointConfiguration() : new ProductionEndpointConfiguration(); public virtual Version AssemblyVersion => Assembly.GetEntryAssembly()?.GetName().Version ?? new Version(); From 6931af664ed3c9a1550a9e2751cfe436b1dc542d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 30 Jan 2024 12:05:31 +0100 Subject: [PATCH 175/915] Add missing `icon.png` entry to nuspec This is only half of the deployment fix, the other half will be in `osu-deploy` (making sure the icon is actually in the staging directory). --- osu.Desktop/osu.nuspec | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec index 3b7d6cbe79..f85698680e 100644 --- a/osu.Desktop/osu.nuspec +++ b/osu.Desktop/osu.nuspec @@ -20,5 +20,6 @@ + From 000ddc14acadf104af4724731c0aa41e27952ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 30 Jan 2024 20:50:00 +0100 Subject: [PATCH 176/915] Fix broken locking in `OAuth` Closes https://github.com/ppy/osu/issues/26824... I think? Can be reproduced via something like diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index 485274f349..e6e93ab4c7 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -151,6 +151,11 @@ internal string RequestAccessToken() { if (!ensureAccessToken()) return null; + for (int i = 0; i < 10000; ++i) + { + _ = Token.Value.AccessToken; + } + return Token.Value.AccessToken; } The cause is `SecondFactorAuthForm` calling `Logout()`, which calls `OAuth.Clear()`, _while_ the `APIAccess` connect loop is checking if `authentication.HasValidAccessToken` is true, which happens to internally check `Token.Value.AccessToken`, which the clearing of tokens can brutally interrupt. --- osu.Game/Online/API/OAuth.cs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index 485274f349..4829310870 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -128,19 +128,12 @@ namespace osu.Game.Online.API // if we already have a valid access token, let's use it. if (accessTokenValid) return true; - // we want to ensure only a single authentication update is happening at once. - lock (access_token_retrieval_lock) - { - // re-check if valid, in case another request completed and revalidated our access. - if (accessTokenValid) return true; + // if not, let's try using our refresh token to request a new access token. + if (!string.IsNullOrEmpty(Token.Value?.RefreshToken)) + // ReSharper disable once PossibleNullReferenceException + AuthenticateWithRefresh(Token.Value.RefreshToken); - // if not, let's try using our refresh token to request a new access token. - if (!string.IsNullOrEmpty(Token.Value?.RefreshToken)) - // ReSharper disable once PossibleNullReferenceException - AuthenticateWithRefresh(Token.Value.RefreshToken); - - return accessTokenValid; - } + return accessTokenValid; } private bool accessTokenValid => Token.Value?.IsValid ?? false; @@ -149,14 +142,18 @@ namespace osu.Game.Online.API internal string RequestAccessToken() { - if (!ensureAccessToken()) return null; + lock (access_token_retrieval_lock) + { + if (!ensureAccessToken()) return null; - return Token.Value.AccessToken; + return Token.Value.AccessToken; + } } internal void Clear() { - Token.Value = null; + lock (access_token_retrieval_lock) + Token.Value = null; } private class AccessTokenRequestRefresh : AccessTokenRequest From 4126dcbe281c2f6590b999af14e27a09748bbde6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 30 Jan 2024 21:40:23 +0100 Subject: [PATCH 177/915] Fix 2FA verification via link not working correctly Closes https://github.com/ppy/osu/issues/26835. I must have not re-tested this correctly after all the refactors... Basically the issue is that the websocket connection would only come online when the API state changed to full `Online`. In particular the connector would not attempt to connect when the API state was `RequiresSecondFactorAuth`, giving the link-based flow no chance to actually work. The change in `WebSocketNotificationsClientConnector` is relevant in that queueing requests does nothing before the API state changes to full `Online`. It also cleans up things a bit code-wise so... win? And yes, this means that the _other_ `PersistentEndpointClientConnector` implementations (i.e. SignalR connectors) will also come online earlier after this. Based on previous discussions (https://github.com/ppy/osu/pull/25480#discussion_r1395566545) I think this is fine, but if it is _not_ fine, then it can be fixed by exposing a virtual that lets a connector to decide when to come alive, I guess. --- .../WebSocketNotificationsClientConnector.cs | 11 ++++------- osu.Game/Online/PersistentEndpointClientConnector.cs | 3 ++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs index 73fe29d441..596322d377 100644 --- a/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs +++ b/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClientConnector.cs @@ -29,14 +29,11 @@ namespace osu.Game.Online.Notifications.WebSocket protected override async Task BuildConnectionAsync(CancellationToken cancellationToken) { - var tcs = new TaskCompletionSource(); - var req = new GetNotificationsRequest(); - req.Success += bundle => tcs.SetResult(bundle.Endpoint); - req.Failure += ex => tcs.SetException(ex); - api.Queue(req); - - string endpoint = await tcs.Task.ConfigureAwait(false); + // must use `PerformAsync()`, since we may not be fully online yet + // (see `APIState.RequiresSecondFactorAuth` - in this state queued requests will not execute). + await api.PerformAsync(req).ConfigureAwait(false); + string endpoint = req.Response!.Endpoint; ClientWebSocket socket = new ClientWebSocket(); socket.Options.SetRequestHeader(@"Authorization", @$"Bearer {api.AccessToken}"); diff --git a/osu.Game/Online/PersistentEndpointClientConnector.cs b/osu.Game/Online/PersistentEndpointClientConnector.cs index 8c1b58a750..024a0fea73 100644 --- a/osu.Game/Online/PersistentEndpointClientConnector.cs +++ b/osu.Game/Online/PersistentEndpointClientConnector.cs @@ -69,6 +69,7 @@ namespace osu.Game.Online break; case APIState.Online: + case APIState.RequiresSecondFactorAuth: await connect().ConfigureAwait(true); break; } @@ -83,7 +84,7 @@ namespace osu.Game.Online try { - while (apiState.Value == APIState.Online) + while (apiState.Value == APIState.RequiresSecondFactorAuth || apiState.Value == APIState.Online) { // ensure any previous connection was disposed. // this will also create a new cancellation token source. From c5e118bd1011a3a2f9b5f1affa832dc2e0735c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 30 Jan 2024 22:15:35 +0100 Subject: [PATCH 178/915] Revert "Move fade more local to avoid fading twice" This reverts commit d0421fe20667530bf1bca1a5c8e3f387dde0cf6a and fixes https://github.com/ppy/osu/issues/26801. https://github.com/ppy/osu/pull/26703#discussion_r1469409667 was correct in saying that the early fade-out needs to be restored, and that's because of the early-return. Legacy judgements that are the temporary displayed judgement from new piece should also receive the fade-out, and d0421fe20667530bf1bca1a5c8e3f387dde0cf6a broke that. --- osu.Game/Skinning/LegacyJudgementPieceOld.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Skinning/LegacyJudgementPieceOld.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs index edfb5a23ec..068707ba4f 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceOld.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -46,6 +46,7 @@ namespace osu.Game.Skinning const double fade_out_length = 600; this.FadeInFromZero(fade_in_length); + this.Delay(fade_out_delay).FadeOut(fade_out_length); // legacy judgements don't play any transforms if they are an animation.... UNLESS they are the temporary displayed judgement from new piece. if (animation?.FrameCount > 1 && !forceTransforms) @@ -79,8 +80,6 @@ namespace osu.Game.Skinning this.RotateTo(0); this.RotateTo(rotation, fade_in_length) .Then().RotateTo(rotation * 2, fade_out_delay + fade_out_length - fade_in_length, Easing.In); - - this.Delay(fade_out_delay).FadeOut(fade_out_length); } } else @@ -94,8 +93,6 @@ namespace osu.Game.Skinning // so we need to force the current value to be correct at 1.2 (0.95) then complete the // second half of the transform. .ScaleTo(0.95f).ScaleTo(finalScale, fade_in_length * 0.2f); // t = 1.4 - - this.Delay(fade_out_delay).FadeOut(fade_out_length); } } From 3aefc919675a855f6d13385d4d69ed326db2bc4f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 31 Jan 2024 07:54:07 +0300 Subject: [PATCH 179/915] Make AliveDrawableMap public --- .../PooledDrawableWithLifetimeContainer.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs index 1b0176cae5..1ebdf48ae8 100644 --- a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs +++ b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Objects.Pooling /// /// The enumeration order is undefined. /// - public IEnumerable<(TEntry Entry, TDrawable Drawable)> AliveEntries => aliveDrawableMap.Select(x => (x.Key, x.Value)); + public IEnumerable<(TEntry Entry, TDrawable Drawable)> AliveEntries => AliveDrawableMap.Select(x => (x.Key, x.Value)); /// /// Whether to remove an entry when clock goes backward and crossed its . @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Objects.Pooling /// internal double FutureLifetimeExtension { get; set; } - private readonly Dictionary aliveDrawableMap = new Dictionary(); + public readonly Dictionary AliveDrawableMap = new Dictionary(); private readonly HashSet allEntries = new HashSet(); private readonly LifetimeEntryManager lifetimeManager = new LifetimeEntryManager(); @@ -101,10 +101,10 @@ namespace osu.Game.Rulesets.Objects.Pooling private void entryBecameAlive(LifetimeEntry lifetimeEntry) { var entry = (TEntry)lifetimeEntry; - Debug.Assert(!aliveDrawableMap.ContainsKey(entry)); + Debug.Assert(!AliveDrawableMap.ContainsKey(entry)); TDrawable drawable = GetDrawable(entry); - aliveDrawableMap[entry] = drawable; + AliveDrawableMap[entry] = drawable; AddDrawable(entry, drawable); } @@ -119,10 +119,10 @@ namespace osu.Game.Rulesets.Objects.Pooling private void entryBecameDead(LifetimeEntry lifetimeEntry) { var entry = (TEntry)lifetimeEntry; - Debug.Assert(aliveDrawableMap.ContainsKey(entry)); + Debug.Assert(AliveDrawableMap.ContainsKey(entry)); - TDrawable drawable = aliveDrawableMap[entry]; - aliveDrawableMap.Remove(entry); + TDrawable drawable = AliveDrawableMap[entry]; + AliveDrawableMap.Remove(entry); RemoveDrawable(entry, drawable); } @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Objects.Pooling foreach (var entry in Entries.ToArray()) Remove(entry); - Debug.Assert(aliveDrawableMap.Count == 0); + Debug.Assert(AliveDrawableMap.Count == 0); } protected override bool CheckChildrenLife() From 6b1de5446ad5dfd21a481ee8f484b92b42851be5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 31 Jan 2024 07:54:28 +0300 Subject: [PATCH 180/915] Reduce allocaations in ScrollingHitObjectContainer --- osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 39ddb5c753..23ac4378e4 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -186,9 +186,9 @@ namespace osu.Game.Rulesets.UI.Scrolling // to prevent hit objects displayed in a wrong position for one frame. // Only AliveEntries need to be considered for layout (reduces overhead in the case of scroll speed changes). // We are not using AliveObjects directly to avoid selection/sorting overhead since we don't care about the order at which positions will be updated. - foreach (var entry in AliveEntries) + foreach (var entry in AliveDrawableMap) { - var obj = entry.Drawable; + var obj = entry.Value; updatePosition(obj, Time.Current); From 9b1bbe5f48eaaf6854c6055d45d6c4601ff3226e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 31 Jan 2024 15:54:43 +0900 Subject: [PATCH 181/915] Adjust default min result of SliderTailHit, remove override --- osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs | 1 - osu.Game/Rulesets/Judgements/Judgement.cs | 4 +++- osu.Game/Rulesets/Scoring/HitResult.cs | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index ceee513412..ee2490439f 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -30,7 +30,6 @@ namespace osu.Game.Rulesets.Osu.Objects public class TailJudgement : SliderEndJudgement { public override HitResult MaxResult => HitResult.SliderTailHit; - public override HitResult MinResult => HitResult.IgnoreMiss; } } } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 93386de483..d4d06167f1 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -73,9 +73,11 @@ namespace osu.Game.Rulesets.Judgements return HitResult.SmallTickMiss; case HitResult.LargeTickHit: - case HitResult.SliderTailHit: return HitResult.LargeTickMiss; + case HitResult.SliderTailHit: + return HitResult.IgnoreMiss; + default: return HitResult.Miss; } diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 20ec3c4946..b6cfca58db 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -138,7 +138,8 @@ namespace osu.Game.Rulesets.Scoring ComboBreak, /// - /// A special judgement similar to that's used to increase the valuation of the final tick of a slider. + /// A special tick judgement to increase the valuation of the final tick of a slider. + /// The default minimum result is , but may be overridden to . /// [EnumMember(Value = "slider_tail_hit")] [Order(8)] From 3f527081bd663064cf098b5b8af003ba4d41b2ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 31 Jan 2024 16:12:46 +0900 Subject: [PATCH 182/915] Update framework --- 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 55ef55ab7d..d944e2ce8e 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index 5b99319499..bd6891f448 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From a7f9f50ce5c3924733c82934fc0402af41d83802 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 31 Jan 2024 16:52:50 +0900 Subject: [PATCH 183/915] Show a better message when score submission fails due to system clock being set wrong --- osu.Game/Screens/Play/SubmittingPlayer.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index 171ceea84f..c8e84f1961 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -132,7 +132,18 @@ namespace osu.Game.Screens.Play if (string.IsNullOrEmpty(exception.Message)) Logger.Error(exception, "Failed to retrieve a score submission token."); else - Logger.Log($"You are not able to submit a score: {exception.Message}", level: LogLevel.Important); + { + switch (exception.Message) + { + case "expired token": + Logger.Log("Score submission failed because your system clock is set incorrectly. Please check your system time, date and timezone.", level: LogLevel.Important); + break; + + default: + Logger.Log($"You are not able to submit a score: {exception.Message}", level: LogLevel.Important); + break; + } + } Schedule(() => { From ebf637bd3c33f1c886f6bfc81aa9ea2132c9e0d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 31 Jan 2024 17:41:26 +0900 Subject: [PATCH 184/915] Adjust slider tick / end misses to show slightly longer --- .../Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs | 2 +- .../Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs | 2 +- osu.Game/Skinning/LegacyJudgementPieceOld.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs index 878e8dbfc2..bd883d6e4c 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonJudgementPieceSliderTickMiss.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon this.ScaleTo(1.4f); this.ScaleTo(1f, 150, Easing.Out); - this.FadeOutFromOne(400); + this.FadeOutFromOne(600); } public Drawable? GetAboveHitObjectsProxiedContent() => piece.CreateProxy(); diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs index 9fc71852ba..04c15a1433 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultJudgementPieceSliderTickMiss.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default this.ScaleTo(1.4f); this.ScaleTo(1f, 150, Easing.Out); - this.FadeOutFromOne(400); + this.FadeOutFromOne(600); } public Drawable? GetAboveHitObjectsProxiedContent() => piece.CreateProxy(); diff --git a/osu.Game/Skinning/LegacyJudgementPieceOld.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs index 068707ba4f..c8630b54a6 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceOld.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -62,7 +62,7 @@ namespace osu.Game.Skinning this.ScaleTo(1.2f); this.ScaleTo(1f, 100, Easing.In); - this.FadeOutFromOne(400); + this.Delay(fade_out_delay / 2).FadeOut(fade_out_length); } else { From fbc923b47ed5e00ac94b5fa20b7310208e650e8c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 31 Jan 2024 17:51:38 +0900 Subject: [PATCH 185/915] Revert "Merge pull request #26870 from smoogipoo/adjust-default-minresult" This reverts commit 1acff746ee65020689b873c279aefb9c6c3d8124, reversing changes made to 696ecda398b22da06066bb4d5fc32861758829a8. --- osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs | 1 + osu.Game/Rulesets/Judgements/Judgement.cs | 4 +--- osu.Game/Rulesets/Scoring/HitResult.cs | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index ee2490439f..ceee513412 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -30,6 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects public class TailJudgement : SliderEndJudgement { public override HitResult MaxResult => HitResult.SliderTailHit; + public override HitResult MinResult => HitResult.IgnoreMiss; } } } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index d4d06167f1..93386de483 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -73,10 +73,8 @@ namespace osu.Game.Rulesets.Judgements return HitResult.SmallTickMiss; case HitResult.LargeTickHit: - return HitResult.LargeTickMiss; - case HitResult.SliderTailHit: - return HitResult.IgnoreMiss; + return HitResult.LargeTickMiss; default: return HitResult.Miss; diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index b6cfca58db..20ec3c4946 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -138,8 +138,7 @@ namespace osu.Game.Rulesets.Scoring ComboBreak, /// - /// A special tick judgement to increase the valuation of the final tick of a slider. - /// The default minimum result is , but may be overridden to . + /// A special judgement similar to that's used to increase the valuation of the final tick of a slider. /// [EnumMember(Value = "slider_tail_hit")] [Order(8)] From 0642a0ee11f492345d373cd488479449df01bb28 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 31 Jan 2024 15:54:43 +0900 Subject: [PATCH 186/915] Adjust default min result of SliderTailHit, remove override --- osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs | 1 - osu.Game/Rulesets/Judgements/Judgement.cs | 4 +++- osu.Game/Rulesets/Scoring/HitResult.cs | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index ceee513412..ee2490439f 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -30,7 +30,6 @@ namespace osu.Game.Rulesets.Osu.Objects public class TailJudgement : SliderEndJudgement { public override HitResult MaxResult => HitResult.SliderTailHit; - public override HitResult MinResult => HitResult.IgnoreMiss; } } } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 93386de483..d4d06167f1 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -73,9 +73,11 @@ namespace osu.Game.Rulesets.Judgements return HitResult.SmallTickMiss; case HitResult.LargeTickHit: - case HitResult.SliderTailHit: return HitResult.LargeTickMiss; + case HitResult.SliderTailHit: + return HitResult.IgnoreMiss; + default: return HitResult.Miss; } diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 20ec3c4946..b6cfca58db 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -138,7 +138,8 @@ namespace osu.Game.Rulesets.Scoring ComboBreak, /// - /// A special judgement similar to that's used to increase the valuation of the final tick of a slider. + /// A special tick judgement to increase the valuation of the final tick of a slider. + /// The default minimum result is , but may be overridden to . /// [EnumMember(Value = "slider_tail_hit")] [Order(8)] From 66aa41e00162bcc2c32b48407a9d8dd999831f7c Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 31 Jan 2024 18:04:32 +0900 Subject: [PATCH 187/915] Fix tests --- .../Rulesets/Scoring/ScoreProcessorTest.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs index 73465fae08..a3f91fffba 100644 --- a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs +++ b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -31,8 +29,8 @@ namespace osu.Game.Tests.Rulesets.Scoring { public partial class ScoreProcessorTest { - private ScoreProcessor scoreProcessor; - private IBeatmap beatmap; + private ScoreProcessor scoreProcessor = null!; + private IBeatmap beatmap = null!; [SetUp] public void SetUp() @@ -86,7 +84,7 @@ namespace osu.Game.Tests.Rulesets.Scoring [TestCase(ScoringMode.Standardised, HitResult.SmallTickHit, HitResult.SmallTickHit, 493_652)] [TestCase(ScoringMode.Standardised, HitResult.LargeTickMiss, HitResult.LargeTickHit, 0)] [TestCase(ScoringMode.Standardised, HitResult.LargeTickHit, HitResult.LargeTickHit, 326_963)] - [TestCase(ScoringMode.Standardised, HitResult.SliderTailHit, HitResult.SliderTailHit, 326_963)] + [TestCase(ScoringMode.Standardised, HitResult.SliderTailHit, HitResult.SliderTailHit, 371_627)] [TestCase(ScoringMode.Standardised, HitResult.SmallBonus, HitResult.SmallBonus, 1_000_030)] [TestCase(ScoringMode.Standardised, HitResult.LargeBonus, HitResult.LargeBonus, 1_000_150)] [TestCase(ScoringMode.Classic, HitResult.Miss, HitResult.Great, 0)] @@ -99,7 +97,7 @@ namespace osu.Game.Tests.Rulesets.Scoring [TestCase(ScoringMode.Classic, HitResult.SmallTickHit, HitResult.SmallTickHit, 49_365)] [TestCase(ScoringMode.Classic, HitResult.LargeTickMiss, HitResult.LargeTickHit, 0)] [TestCase(ScoringMode.Classic, HitResult.LargeTickHit, HitResult.LargeTickHit, 32_696)] - [TestCase(ScoringMode.Classic, HitResult.SliderTailHit, HitResult.SliderTailHit, 32_696)] + [TestCase(ScoringMode.Classic, HitResult.SliderTailHit, HitResult.SliderTailHit, 37_163)] [TestCase(ScoringMode.Classic, HitResult.SmallBonus, HitResult.SmallBonus, 100_003)] [TestCase(ScoringMode.Classic, HitResult.LargeBonus, HitResult.LargeBonus, 100_015)] public void TestFourVariousResultsOneMiss(ScoringMode scoringMode, HitResult hitResult, HitResult maxResult, int expectedScore) @@ -171,7 +169,7 @@ namespace osu.Game.Tests.Rulesets.Scoring [TestCase(HitResult.Perfect, HitResult.Miss)] [TestCase(HitResult.SmallTickHit, HitResult.SmallTickMiss)] [TestCase(HitResult.LargeTickHit, HitResult.LargeTickMiss)] - [TestCase(HitResult.SliderTailHit, HitResult.LargeTickMiss)] + [TestCase(HitResult.SliderTailHit, HitResult.IgnoreMiss)] [TestCase(HitResult.SmallBonus, HitResult.IgnoreMiss)] [TestCase(HitResult.LargeBonus, HitResult.IgnoreMiss)] public void TestMinResults(HitResult hitResult, HitResult expectedMinResult) @@ -476,7 +474,7 @@ namespace osu.Game.Tests.Rulesets.Scoring public override IEnumerable GetModsFor(ModType type) => throw new NotImplementedException(); - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => throw new NotImplementedException(); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => throw new NotImplementedException(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException(); From f927cb59285ff730f7c8ad7426775f992c0f1352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 31 Jan 2024 12:29:18 +0100 Subject: [PATCH 188/915] Increase repeat count for better coverage of flip operations --- .../OsuHitObjectGenerationUtilsTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs index d78c32aa6a..ffb9ad1784 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Tests new PathControlPoint(new Vector2(-128, 0), PathType.LINEAR) // absolute position: (0, 128) } }, - RepeatCount = 1 + RepeatCount = 2 }; slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return slider; @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Tests OsuHitObjectGenerationUtils.ReflectHorizontallyAlongPlayfield(slider); Assert.That(slider.Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X - 128, 128))); - Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X - 0, 128))); + Assert.That(slider.NestedHitObjects.OfType().First().Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X - 0, 128))); Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] { new Vector2(), @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Osu.Tests OsuHitObjectGenerationUtils.ReflectVerticallyAlongPlayfield(slider); Assert.That(slider.Position, Is.EqualTo(new Vector2(128, OsuPlayfield.BASE_SIZE.Y - 128))); - Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(0, OsuPlayfield.BASE_SIZE.Y - 128))); + Assert.That(slider.NestedHitObjects.OfType().First().Position, Is.EqualTo(new Vector2(0, OsuPlayfield.BASE_SIZE.Y - 128))); Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] { new Vector2(), @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Tests OsuHitObjectGenerationUtils.FlipSliderInPlaceHorizontally(slider); Assert.That(slider.Position, Is.EqualTo(new Vector2(128, 128))); - Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(256, 128))); + Assert.That(slider.NestedHitObjects.OfType().First().Position, Is.EqualTo(new Vector2(256, 128))); Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] { new Vector2(), From a934556bb8e4d266b67c35bbc8c328d540ee35cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 31 Jan 2024 12:34:38 +0100 Subject: [PATCH 189/915] Add failing assertions for head/tail positions after flip --- .../OsuHitObjectGenerationUtilsTest.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs index ffb9ad1784..77ef4627cb 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuHitObjectGenerationUtilsTest.cs @@ -45,7 +45,9 @@ namespace osu.Game.Rulesets.Osu.Tests OsuHitObjectGenerationUtils.ReflectHorizontallyAlongPlayfield(slider); Assert.That(slider.Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X - 128, 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X - 128, 128))); Assert.That(slider.NestedHitObjects.OfType().First().Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X - 0, 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(OsuPlayfield.BASE_SIZE.X, 128))); Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] { new Vector2(), @@ -62,7 +64,9 @@ namespace osu.Game.Rulesets.Osu.Tests OsuHitObjectGenerationUtils.ReflectVerticallyAlongPlayfield(slider); Assert.That(slider.Position, Is.EqualTo(new Vector2(128, OsuPlayfield.BASE_SIZE.Y - 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(128, OsuPlayfield.BASE_SIZE.Y - 128))); Assert.That(slider.NestedHitObjects.OfType().First().Position, Is.EqualTo(new Vector2(0, OsuPlayfield.BASE_SIZE.Y - 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(0, OsuPlayfield.BASE_SIZE.Y - 128))); Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] { new Vector2(), @@ -79,7 +83,9 @@ namespace osu.Game.Rulesets.Osu.Tests OsuHitObjectGenerationUtils.FlipSliderInPlaceHorizontally(slider); Assert.That(slider.Position, Is.EqualTo(new Vector2(128, 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(128, 128))); Assert.That(slider.NestedHitObjects.OfType().First().Position, Is.EqualTo(new Vector2(256, 128))); + Assert.That(slider.NestedHitObjects.OfType().Single().Position, Is.EqualTo(new Vector2(256, 128))); Assert.That(slider.Path.ControlPoints.Select(point => point.Position), Is.EquivalentTo(new[] { new Vector2(), From dfea2ade6d7d1dda0b080fca826cec767a480199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 31 Jan 2024 12:43:24 +0100 Subject: [PATCH 190/915] Revert incorrect end position optimisation Closes https://github.com/ppy/osu/issues/26867. Reverts 882f49039029b7dc3e287ccc302d04de89de10df and ce643aa68f35369be1a975bb1ceb69fb54192cf2. The applied optimisation may have been valid as long as it was constrained to `Slider`. But it is not, as `SliderTailCircle` stores a local copy of the object position. And as the commit message of ce643aa68f35369be1a975bb1ceb69fb54192cf2 states, this could be bypassed by some pretty hacky delegation from `SliderTailCircle.Position` to the slider, but it'd also be pretty hacky because it would make flows like `PositionBindable` break down. Long-term solution is to probably remove bindables from hitobjects. --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 032f105ded..506145568e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Osu.Objects set { repeatCount = value; - endPositionCache.Invalidate(); + updateNestedPositions(); } } @@ -165,7 +165,7 @@ namespace osu.Game.Rulesets.Osu.Objects public Slider() { SamplesBindable.CollectionChanged += (_, _) => UpdateNestedSamples(); - Path.Version.ValueChanged += _ => endPositionCache.Invalidate(); + Path.Version.ValueChanged += _ => updateNestedPositions(); } protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) From 424859328938f86d6520bf784530c3b33d2a1ffb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 31 Jan 2024 22:41:44 +0900 Subject: [PATCH 191/915] Fix menu banner not updating as often as we want it to --- osu.Game/Online/API/Requests/GetSystemTitleRequest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetSystemTitleRequest.cs b/osu.Game/Online/API/Requests/GetSystemTitleRequest.cs index 659e46bb11..52ca0c11eb 100644 --- a/osu.Game/Online/API/Requests/GetSystemTitleRequest.cs +++ b/osu.Game/Online/API/Requests/GetSystemTitleRequest.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; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests @@ -9,7 +8,7 @@ namespace osu.Game.Online.API.Requests public class GetSystemTitleRequest : OsuJsonWebRequest { public GetSystemTitleRequest() - : base($@"https://assets.ppy.sh/lazer-status.json?{DateTimeOffset.UtcNow.ToUnixTimeSeconds() / 1800}") + : base(@"https://assets.ppy.sh/lazer-status.json") { } } From e71c95f1fed41cf194d4c004c0d1b5a9e3620f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 31 Jan 2024 14:48:27 +0100 Subject: [PATCH 192/915] Reintroduce `IMod.Ranked` What goes around, comes around. --- osu.Game/Rulesets/Mods/IMod.cs | 5 +++++ osu.Game/Rulesets/Mods/Mod.cs | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/osu.Game/Rulesets/Mods/IMod.cs b/osu.Game/Rulesets/Mods/IMod.cs index 744d02a4fa..3a33d14835 100644 --- a/osu.Game/Rulesets/Mods/IMod.cs +++ b/osu.Game/Rulesets/Mods/IMod.cs @@ -66,6 +66,11 @@ namespace osu.Game.Rulesets.Mods /// bool AlwaysValidForSubmission { get; } + /// + /// Whether scores with this mod active can give performance points. + /// + bool Ranked { get; } + /// /// Create a fresh instance based on this mod. /// diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 0500b49513..50c867f41b 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -167,6 +167,12 @@ namespace osu.Game.Rulesets.Mods [JsonIgnore] public virtual bool RequiresConfiguration => false; + /// + /// Whether scores with this mod active can give performance points. + /// + [JsonIgnore] + public virtual bool Ranked => false; + /// /// The mods this mod cannot be enabled with. /// From 0642d740149b2daf8876d76b3b55c15709cd6144 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 31 Jan 2024 22:52:57 +0900 Subject: [PATCH 193/915] Expose as ReadOnlyDictionary --- .../PooledDrawableWithLifetimeContainer.cs | 19 +++++++++++-------- .../UI/GameplaySampleTriggerSource.cs | 2 +- osu.Game/Rulesets/UI/HitObjectContainer.cs | 2 +- .../Scrolling/ScrollingHitObjectContainer.cs | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs index 1ebdf48ae8..aed608cf8f 100644 --- a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs +++ b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; @@ -35,7 +36,7 @@ namespace osu.Game.Rulesets.Objects.Pooling /// /// The enumeration order is undefined. /// - public IEnumerable<(TEntry Entry, TDrawable Drawable)> AliveEntries => AliveDrawableMap.Select(x => (x.Key, x.Value)); + public readonly ReadOnlyDictionary AliveEntries; /// /// Whether to remove an entry when clock goes backward and crossed its . @@ -53,7 +54,7 @@ namespace osu.Game.Rulesets.Objects.Pooling /// internal double FutureLifetimeExtension { get; set; } - public readonly Dictionary AliveDrawableMap = new Dictionary(); + private readonly Dictionary aliveDrawableMap = new Dictionary(); private readonly HashSet allEntries = new HashSet(); private readonly LifetimeEntryManager lifetimeManager = new LifetimeEntryManager(); @@ -63,6 +64,8 @@ namespace osu.Game.Rulesets.Objects.Pooling lifetimeManager.EntryBecameAlive += entryBecameAlive; lifetimeManager.EntryBecameDead += entryBecameDead; lifetimeManager.EntryCrossedBoundary += entryCrossedBoundary; + + AliveEntries = new ReadOnlyDictionary(aliveDrawableMap); } /// @@ -101,10 +104,10 @@ namespace osu.Game.Rulesets.Objects.Pooling private void entryBecameAlive(LifetimeEntry lifetimeEntry) { var entry = (TEntry)lifetimeEntry; - Debug.Assert(!AliveDrawableMap.ContainsKey(entry)); + Debug.Assert(!aliveDrawableMap.ContainsKey(entry)); TDrawable drawable = GetDrawable(entry); - AliveDrawableMap[entry] = drawable; + aliveDrawableMap[entry] = drawable; AddDrawable(entry, drawable); } @@ -119,10 +122,10 @@ namespace osu.Game.Rulesets.Objects.Pooling private void entryBecameDead(LifetimeEntry lifetimeEntry) { var entry = (TEntry)lifetimeEntry; - Debug.Assert(AliveDrawableMap.ContainsKey(entry)); + Debug.Assert(aliveDrawableMap.ContainsKey(entry)); - TDrawable drawable = AliveDrawableMap[entry]; - AliveDrawableMap.Remove(entry); + TDrawable drawable = aliveDrawableMap[entry]; + aliveDrawableMap.Remove(entry); RemoveDrawable(entry, drawable); } @@ -148,7 +151,7 @@ namespace osu.Game.Rulesets.Objects.Pooling foreach (var entry in Entries.ToArray()) Remove(entry); - Debug.Assert(AliveDrawableMap.Count == 0); + Debug.Assert(aliveDrawableMap.Count == 0); } protected override bool CheckChildrenLife() diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index b61e8d9674..177520f28f 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.UI // If required, we can make this lookup more efficient by adding support to get next-future-entry in LifetimeEntryManager. var candidate = // Use alive entries first as an optimisation. - hitObjectContainer.AliveEntries.Select(tuple => tuple.Entry).Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime) + hitObjectContainer.AliveEntries.Keys.Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime) ?? hitObjectContainer.Entries.Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime); // In the case there are no non-judged objects, the last hit object should be used instead. diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index 099be486b3..c2879e6d87 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.UI { public IEnumerable Objects => InternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); - public IEnumerable AliveObjects => AliveEntries.Select(pair => pair.Drawable).OrderBy(h => h.HitObject.StartTime); + public IEnumerable AliveObjects => AliveEntries.Values.OrderBy(h => h.HitObject.StartTime); /// /// Invoked when a is judged. diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 23ac4378e4..4e72291b9c 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -186,7 +186,7 @@ namespace osu.Game.Rulesets.UI.Scrolling // to prevent hit objects displayed in a wrong position for one frame. // Only AliveEntries need to be considered for layout (reduces overhead in the case of scroll speed changes). // We are not using AliveObjects directly to avoid selection/sorting overhead since we don't care about the order at which positions will be updated. - foreach (var entry in AliveDrawableMap) + foreach (var entry in AliveEntries) { var obj = entry.Value; From f89923aeaee5785aeb4b91b6aaa3dfdf8b8ad791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 31 Jan 2024 14:59:35 +0100 Subject: [PATCH 194/915] Annotate mods that give pp --- osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs | 1 + osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs | 1 + osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs | 1 + osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs | 1 + osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs | 1 + osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs | 1 + osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs | 1 + osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs | 1 + osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs | 1 + osu.Game/Rulesets/Mods/ModDaycore.cs | 1 + osu.Game/Rulesets/Mods/ModDoubleTime.cs | 1 + osu.Game/Rulesets/Mods/ModEasy.cs | 1 + osu.Game/Rulesets/Mods/ModFlashlight.cs | 1 + osu.Game/Rulesets/Mods/ModHalfTime.cs | 1 + osu.Game/Rulesets/Mods/ModHardRock.cs | 1 + osu.Game/Rulesets/Mods/ModHidden.cs | 1 + osu.Game/Rulesets/Mods/ModMuted.cs | 1 + osu.Game/Rulesets/Mods/ModNightcore.cs | 1 + osu.Game/Rulesets/Mods/ModNoFail.cs | 1 + osu.Game/Rulesets/Mods/ModPerfect.cs | 1 + osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 1 + 21 files changed, 21 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs index 050b302bd8..88d6a19822 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs @@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Mania.Mods public abstract int KeyCount { get; } public override ModType Type => ModType.Conversion; public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier + public override bool Ranked => UsesDefaultConfiguration; public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter) { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs index d9de06a811..189c4b3a5f 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs @@ -8,5 +8,6 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModHardRock : ModHardRock { public override double ScoreMultiplier => 1; + public override bool Ranked => false; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs index 31f52610e9..7dd0c499da 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs @@ -11,5 +11,6 @@ namespace osu.Game.Rulesets.Mania.Mods public override string Name => "One Key"; public override string Acronym => "1K"; public override LocalisableString Description => @"Play with one key."; + public override bool Ranked => false; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs index 67e65b887a..a6c57d4597 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs @@ -11,5 +11,6 @@ namespace osu.Game.Rulesets.Mania.Mods public override string Name => "Ten Keys"; public override string Acronym => "10K"; public override LocalisableString Description => @"Play with ten keys."; + public override bool Ranked => false; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs index 0f8148d252..0d04395a52 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs @@ -11,5 +11,6 @@ namespace osu.Game.Rulesets.Mania.Mods public override string Name => "Two Keys"; public override string Acronym => "2K"; public override LocalisableString Description => @"Play with two keys."; + public override bool Ranked => false; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs index 0f8af7940c..c83b0979ee 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs @@ -11,5 +11,6 @@ namespace osu.Game.Rulesets.Mania.Mods public override string Name => "Three Keys"; public override string Acronym => "3K"; public override LocalisableString Description => @"Play with three keys."; + public override bool Ranked => false; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs index f9690b4298..cc7e270dda 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs @@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModMirror : ModMirror, IApplicableToBeatmap { public override LocalisableString Description => "Notes are flipped horizontally."; + public override bool Ranked => UsesDefaultConfiguration; public void ApplyToBeatmap(IBeatmap beatmap) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs index f691731afe..df9544b71e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs @@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override LocalisableString Description => @"Spinners will be automatically completed."; public override double ScoreMultiplier => 0.9; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot), typeof(OsuModTargetPractice) }; + public override bool Ranked => UsesDefaultConfiguration; public void ApplyToDrawableHitObject(DrawableHitObject hitObject) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs index f1468d414e..917685cdad 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs @@ -10,5 +10,6 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModTouchDevice : ModTouchDevice { public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); + public override bool Ranked => UsesDefaultConfiguration; } } diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 09b35c249e..359f8a950c 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Mods public override IconUsage? Icon => null; public override ModType Type => ModType.DifficultyReduction; public override LocalisableString Description => "Whoaaaaa..."; + public override bool Ranked => UsesDefaultConfiguration; [SettingSource("Speed decrease", "The actual decrease to apply", SettingControlType = typeof(MultiplierSettingsSlider))] public override BindableNumber SpeedChange { get; } = new BindableDouble(0.75) diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index 789291772d..8e430da368 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Mods public override IconUsage? Icon => OsuIcon.ModDoubleTime; public override ModType Type => ModType.DifficultyIncrease; public override LocalisableString Description => "Zoooooooooom..."; + public override bool Ranked => UsesDefaultConfiguration; [SettingSource("Speed increase", "The actual increase to apply", SettingControlType = typeof(MultiplierSettingsSlider))] public override BindableNumber SpeedChange { get; } = new BindableDouble(1.5) diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 0f51e2a6d5..da43a6b294 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyReduction; public override double ScoreMultiplier => 0.5; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock), typeof(ModDifficultyAdjust) }; + public override bool Ranked => UsesDefaultConfiguration; public virtual void ReadFromDifficulty(BeatmapDifficulty difficulty) { diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index dc2ad6f47e..9227af64b8 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -33,6 +33,7 @@ namespace osu.Game.Rulesets.Mods public override IconUsage? Icon => OsuIcon.ModFlashlight; public override ModType Type => ModType.DifficultyIncrease; public override LocalisableString Description => "Restricted view area."; + public override bool Ranked => UsesDefaultConfiguration; [SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")] public abstract BindableFloat SizeMultiplier { get; } diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 8b5dd39584..59e40ee9cc 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Mods public override IconUsage? Icon => OsuIcon.ModHalftime; public override ModType Type => ModType.DifficultyReduction; public override LocalisableString Description => "Less zoom..."; + public override bool Ranked => UsesDefaultConfiguration; [SettingSource("Speed decrease", "The actual decrease to apply", SettingControlType = typeof(MultiplierSettingsSlider))] public override BindableNumber SpeedChange { get; } = new BindableDouble(0.75) diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 4b2d1d050e..1e99891b99 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyIncrease; public override LocalisableString Description => "Everything just got a bit harder..."; public override Type[] IncompatibleMods => new[] { typeof(ModEasy), typeof(ModDifficultyAdjust) }; + public override bool Ranked => UsesDefaultConfiguration; protected const float ADJUST_RATIO = 1.4f; diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 8b25768575..5a1abf115f 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Mods public override string Acronym => "HD"; public override IconUsage? Icon => OsuIcon.ModHidden; public override ModType Type => ModType.DifficultyIncrease; + public override bool Ranked => UsesDefaultConfiguration; public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 131f501630..3ecd9aa6a1 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Mods public override LocalisableString Description => "Can you still feel the rhythm without music?"; public override ModType Type => ModType.Fun; public override double ScoreMultiplier => 1; + public override bool Ranked => UsesDefaultConfiguration; } public abstract class ModMuted : ModMuted, IApplicableToDrawableRuleset, IApplicableToTrack, IApplicableToScoreProcessor diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index b42927256c..bb18940f8c 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -28,6 +28,7 @@ namespace osu.Game.Rulesets.Mods public override IconUsage? Icon => OsuIcon.ModNightcore; public override ModType Type => ModType.DifficultyIncrease; public override LocalisableString Description => "Uguuuuuuuu..."; + public override bool Ranked => UsesDefaultConfiguration; [SettingSource("Speed increase", "The actual increase to apply", SettingControlType = typeof(MultiplierSettingsSlider))] public override BindableNumber SpeedChange { get; } = new BindableDouble(1.5) diff --git a/osu.Game/Rulesets/Mods/ModNoFail.cs b/osu.Game/Rulesets/Mods/ModNoFail.cs index cc451772b2..1aaef8eac4 100644 --- a/osu.Game/Rulesets/Mods/ModNoFail.cs +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Mods public override LocalisableString Description => "You can't fail, no matter what."; public override double ScoreMultiplier => 0.5; public override Type[] IncompatibleMods => new[] { typeof(ModFailCondition), typeof(ModCinema) }; + public override bool Ranked => UsesDefaultConfiguration; private readonly Bindable showHealthBar = new Bindable(); diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 0ba40ba070..f8f498ceb5 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -19,6 +19,7 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyIncrease; public override double ScoreMultiplier => 1; public override LocalisableString Description => "SS or quit."; + public override bool Ranked => UsesDefaultConfiguration; public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(ModSuddenDeath), typeof(ModAccuracyChallenge) }).ToArray(); diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 4e4e8662e8..62579a168c 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -19,6 +19,7 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyIncrease; public override LocalisableString Description => "Miss and fail."; public override double ScoreMultiplier => 1; + public override bool Ranked => UsesDefaultConfiguration; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModPerfect)).ToArray(); From 7165511754ad437f035e87fdd96323d3c75e7a67 Mon Sep 17 00:00:00 2001 From: syscats Date: Wed, 31 Jan 2024 15:49:31 +0100 Subject: [PATCH 195/915] Use ordinal sorting for artist string comparison --- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 6d2e938fb7..857f7efb8e 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Select.Carousel { default: case SortMode.Artist: - comparison = string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.OrdinalIgnoreCase); + comparison = string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.Ordinal); break; case SortMode.Title: From 563f4a26b139be4b4c9354af20b5275527ee85d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Feb 2024 21:10:37 +0900 Subject: [PATCH 196/915] Show "failing" icon on user panel when 2FA prompt is present This gives the user a chance to know it's required. --- osu.Game/Overlays/Toolbar/ToolbarUserButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 28521e3331..1e812d7238 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -95,7 +95,7 @@ namespace osu.Game.Overlays.Toolbar private void onlineStateChanged(ValueChangedEvent state) => Schedule(() => { - failingIcon.FadeTo(state.NewValue == APIState.Failing ? 1 : 0, 200, Easing.OutQuint); + failingIcon.FadeTo(state.NewValue == APIState.Failing || state.NewValue == APIState.RequiresSecondFactorAuth ? 1 : 0, 200, Easing.OutQuint); switch (state.NewValue) { From bf3746daa8e8117a23978b3982185af7145d37fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Feb 2024 21:10:53 +0900 Subject: [PATCH 197/915] Show login overlay at main menu when 2FA is required --- osu.Game/Screens/Menu/MainMenu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index a75edd1cff..decb901c32 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -280,7 +280,7 @@ namespace osu.Game.Screens.Menu sideFlashes.Delay(FADE_IN_DURATION).FadeIn(64, Easing.InQuint); } - else if (!api.IsLoggedIn) + else if (!api.IsLoggedIn || api.State.Value == APIState.RequiresSecondFactorAuth) { // copy out old action to avoid accidentally capturing logo.Action in closure, causing a self-reference loop. var previousAction = logo.Action; From 0407b5d84ac0bc2d872ffc3bb173f622900ffd45 Mon Sep 17 00:00:00 2001 From: syscats Date: Thu, 1 Feb 2024 14:03:59 +0100 Subject: [PATCH 198/915] use ordinal sorting on each method --- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 857f7efb8e..f7b715862a 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -71,15 +71,15 @@ namespace osu.Game.Screens.Select.Carousel break; case SortMode.Title: - comparison = string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.OrdinalIgnoreCase); + comparison = string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.Ordinal); break; case SortMode.Author: - comparison = string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.OrdinalIgnoreCase); + comparison = string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.Ordinal); break; case SortMode.Source: - comparison = string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.OrdinalIgnoreCase); + comparison = string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.Ordinal); break; case SortMode.DateAdded: From 5bbaeb6836cd9280f7e09d946192ba9e3ad69ddf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 1 Feb 2024 16:08:33 +0300 Subject: [PATCH 199/915] Play legacy applause sound only when rank is B or higher --- .../Expanded/Accuracy/AccuracyCircle.cs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 60c35e6203..5de5ceb2a8 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -10,7 +10,6 @@ using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -86,6 +85,9 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// public static readonly Easing ACCURACY_TRANSFORM_EASING = Easing.OutPow10; + [Resolved] + private SkinManager skins { get; set; } + private readonly ScoreInfo score; private CircularProgress accuracyCircle; @@ -99,7 +101,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy private PoolableSkinnableSample swooshUpSound; private PoolableSkinnableSample rankImpactSound; private PoolableSkinnableSample rankApplauseSound; - private DrawableSample rankFailSound; + private PoolableSkinnableSample rankLegacyApplauseSound; private readonly Bindable tickPlaybackRate = new Bindable(); @@ -264,12 +266,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy AddRangeInternal(new Drawable[] { rankImpactSound = new PoolableSkinnableSample(new SampleInfo(impactSampleName)), - rankApplauseSound = new PoolableSkinnableSample(new SampleInfo(@"applause", applauseSampleName)), + rankApplauseSound = new PoolableSkinnableSample(new SampleInfo(applauseSampleName)), + rankLegacyApplauseSound = new PoolableSkinnableSample(new SampleInfo("applause")), scoreTickSound = new PoolableSkinnableSample(new SampleInfo(@"Results/score-tick")), badgeTickSound = new PoolableSkinnableSample(new SampleInfo(@"Results/badge-dink")), badgeMaxSound = new PoolableSkinnableSample(new SampleInfo(@"Results/badge-dink-max")), swooshUpSound = new PoolableSkinnableSample(new SampleInfo(@"Results/swoosh-up")), - rankFailSound = new DrawableSample(audio.Samples.Get(results_applause_d_sound)), }); } } @@ -399,15 +401,19 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { Schedule(() => { - if (score.Rank != ScoreRank.F) + if (skins.CurrentSkin.Value is LegacySkin) { - rankApplauseSound.VolumeTo(applause_volume); - rankApplauseSound.Play(); + // only play legacy "applause" sound if score rank is B or higher. + if (score.Rank >= ScoreRank.B) + { + rankLegacyApplauseSound.VolumeTo(applause_volume); + rankLegacyApplauseSound.Play(); + } } else { - rankFailSound.VolumeTo(applause_volume); - rankFailSound.Play(); + rankApplauseSound.VolumeTo(applause_volume); + rankApplauseSound.Play(); } }); } @@ -451,8 +457,6 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy } } - private const string results_applause_d_sound = @"Results/applause-d"; - private string applauseSampleName { get @@ -461,7 +465,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { default: case ScoreRank.D: - return results_applause_d_sound; + return @"Results/applause-d"; case ScoreRank.C: return @"Results/applause-c"; From 6ab8960fdc630d4110734d206bd15c417b76d0f5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 1 Feb 2024 16:08:48 +0300 Subject: [PATCH 200/915] Add step for toggling skins in results screen test scene --- osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index 122149be44..2bda242de2 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -62,6 +62,12 @@ namespace osu.Game.Tests.Visual.Ranking if (beatmapInfo != null) Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); }); + + AddToggleStep("toggle skin", v => + { + if (skins != null) + skins.CurrentSkinInfo.Value = v ? skins.DefaultClassicSkin.SkinInfo : skins.CurrentSkinInfo.Default; + }); } [SetUp] From b0f6a87a2b6119f82c6219f73363e6c6578d0d2d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Feb 2024 15:35:23 +0300 Subject: [PATCH 201/915] Add stress test in TestSceneDashboardOverlay --- .../Online/TestSceneDashboardOverlay.cs | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs index 9407941da6..b6a300322f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs @@ -2,14 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { public partial class TestSceneDashboardOverlay : OsuTestScene { - protected override bool UseOnlineAPI => true; - private readonly DashboardOverlay overlay; public TestSceneDashboardOverlay() @@ -17,6 +18,30 @@ namespace osu.Game.Tests.Visual.Online Add(overlay = new DashboardOverlay()); } + [BackgroundDependencyLoader] + private void load() + { + int supportLevel = 0; + + for (int i = 0; i < 1000; i++) + { + supportLevel++; + + if (supportLevel > 3) + supportLevel = 0; + + ((DummyAPIAccess)API).Friends.Add(new APIUser + { + Username = @"peppy", + Id = 2, + Colour = "99EB47", + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", + IsSupporter = supportLevel > 0, + SupportLevel = supportLevel + }); + } + } + [Test] public void TestShow() { From 2bd9dcf646127261c62e1a8c913768a9a59d0221 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Feb 2024 16:13:36 +0300 Subject: [PATCH 202/915] Rework UserGridPanel to reduce containers nesting --- osu.Game/Users/UserGridPanel.cs | 138 ++++++++++++++------------------ 1 file changed, 62 insertions(+), 76 deletions(-) diff --git a/osu.Game/Users/UserGridPanel.cs b/osu.Game/Users/UserGridPanel.cs index fe3435c248..fce543415d 100644 --- a/osu.Game/Users/UserGridPanel.cs +++ b/osu.Game/Users/UserGridPanel.cs @@ -35,98 +35,84 @@ namespace osu.Game.Users { FillFlowContainer details; - var layout = new Container + var layout = new GridContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(margin), - Child = new GridContainer + ColumnDimensions = new[] { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[] { - new Dimension(GridSizeMode.AutoSize), - new Dimension() - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Absolute, margin), - new Dimension() - }, - Content = new[] - { - new Drawable[] + CreateAvatar().With(avatar => { - CreateAvatar().With(avatar => + avatar.Size = new Vector2(60); + avatar.Masking = true; + avatar.CornerRadius = 6; + avatar.Margin = new MarginPadding { Bottom = margin }; + }), + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = margin, Bottom = margin }, + ColumnDimensions = new[] { - avatar.Size = new Vector2(60); - avatar.Masking = true; - avatar.CornerRadius = 6; - }), - new Container + new Dimension() + }, + RowDimensions = new[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = margin }, - Child = new GridContainer + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + details = new FillFlowContainer { - new Dimension() - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension() - }, - Content = new[] - { - new Drawable[] + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(6), + Children = new Drawable[] { - details = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(6), - Children = new Drawable[] - { - CreateFlag(), - // supporter icon is being added later - } - } - }, - new Drawable[] - { - CreateUsername().With(username => - { - username.Anchor = Anchor.CentreLeft; - username.Origin = Anchor.CentreLeft; - }) + CreateFlag(), + // supporter icon is being added later } } + }, + new Drawable[] + { + CreateUsername().With(username => + { + username.Anchor = Anchor.CentreLeft; + username.Origin = Anchor.CentreLeft; + }) } } - }, - new[] - { - // padding - Empty(), - Empty() - }, - new Drawable[] - { - CreateStatusIcon().With(icon => - { - icon.Anchor = Anchor.Centre; - icon.Origin = Anchor.Centre; - }), - CreateStatusMessage(false).With(message => - { - message.Anchor = Anchor.CentreLeft; - message.Origin = Anchor.CentreLeft; - message.Margin = new MarginPadding { Left = margin }; - }) } + }, + new Drawable[] + { + CreateStatusIcon().With(icon => + { + icon.Anchor = Anchor.Centre; + icon.Origin = Anchor.Centre; + }), + CreateStatusMessage(false).With(message => + { + message.Anchor = Anchor.CentreLeft; + message.Origin = Anchor.CentreLeft; + message.Margin = new MarginPadding { Left = margin }; + }) } } }; From 66350fd148f7189535b1c070af9d3321cc9704d3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Feb 2024 16:33:54 +0300 Subject: [PATCH 203/915] Refactor UserRankPanel layout --- osu.Game/Users/UserRankPanel.cs | 116 +++++++++++++------------------- 1 file changed, 47 insertions(+), 69 deletions(-) diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index a38962dfc7..84ff3114fc 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -81,117 +81,95 @@ namespace osu.Game.Users }, new GridContainer { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(padding), ColumnDimensions = new[] { - new Dimension(GridSizeMode.Absolute, padding), new Dimension(GridSizeMode.AutoSize), new Dimension(), - new Dimension(GridSizeMode.Absolute, padding), }, RowDimensions = new[] { - new Dimension(GridSizeMode.Absolute, padding), - new Dimension(GridSizeMode.AutoSize), + new Dimension() }, Content = new[] { - new[] + new Drawable[] { - // padding - Empty(), - Empty(), - Empty(), - Empty() - }, - new[] - { - Empty(), // padding CreateAvatar().With(avatar => { avatar.Size = new Vector2(60); avatar.Masking = true; avatar.CornerRadius = 6; }), - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = padding }, - Child = new GridContainer + ColumnDimensions = new[] { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + new Dimension() + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[] { - new Dimension() - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension() - }, - Content = new[] - { - new Drawable[] + details = new FillFlowContainer { - details = new FillFlowContainer + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(6), + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(6), - Children = new Drawable[] - { - CreateFlag(), - // supporter icon is being added later - } + CreateFlag(), + // supporter icon is being added later } - }, - new Drawable[] - { - CreateUsername().With(username => - { - username.Anchor = Anchor.CentreLeft; - username.Origin = Anchor.CentreLeft; - }) } + }, + new Drawable[] + { + CreateUsername().With(username => + { + username.Anchor = Anchor.CentreLeft; + username.Origin = Anchor.CentreLeft; + }) } } - }, - Empty() // padding + } } } } } }, - new Container + new GridContainer { Name = "Bottom content", Margin = new MarginPadding { Top = main_content_height }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Left = 80, Vertical = padding }, - Child = new GridContainer + ColumnDimensions = new[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - ColumnDimensions = new[] + new Dimension(), + new Dimension() + }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + Content = new[] + { + new Drawable[] { - new Dimension(), - new Dimension() - }, - RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, - Content = new[] - { - new Drawable[] + globalRankDisplay = new ProfileValueDisplay(true) { - globalRankDisplay = new ProfileValueDisplay(true) - { - Title = UsersStrings.ShowRankGlobalSimple, - }, - countryRankDisplay = new ProfileValueDisplay(true) - { - Title = UsersStrings.ShowRankCountrySimple, - } + Title = UsersStrings.ShowRankGlobalSimple, + }, + countryRankDisplay = new ProfileValueDisplay(true) + { + Title = UsersStrings.ShowRankCountrySimple, } } } From b0095ee54832dc8e00ab4b7491bf482bdfd7225b Mon Sep 17 00:00:00 2001 From: Susko3 Date: Thu, 1 Feb 2024 18:38:18 +0100 Subject: [PATCH 204/915] Apply NRT --- osu.Game/Updater/SimpleUpdateManager.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index bc1b0919b8..77de68d63e 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using System.Runtime.InteropServices; @@ -22,10 +20,10 @@ namespace osu.Game.Updater /// public partial class SimpleUpdateManager : UpdateManager { - private string version; + private string version = null!; [Resolved] - private GameHost host { get; set; } + private GameHost host { get; set; } = null!; [BackgroundDependencyLoader] private void load(OsuGameBase game) @@ -76,7 +74,7 @@ namespace osu.Game.Updater private string getBestUrl(GitHubRelease release) { - GitHubAsset bestAsset = null; + GitHubAsset? bestAsset = null; switch (RuntimeInfo.OS) { From b9d750cfee9c18a6226c74b0ca5d452279234f5f Mon Sep 17 00:00:00 2001 From: Susko3 Date: Thu, 1 Feb 2024 18:55:34 +0100 Subject: [PATCH 205/915] Convert to try-get and don't fall back to release URL --- osu.Game/Updater/SimpleUpdateManager.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index 77de68d63e..a7671551ef 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; @@ -46,7 +47,7 @@ namespace osu.Game.Updater version = version.Split('-').First(); string latestTagName = latest.TagName.Split('-').First(); - if (latestTagName != version) + if (latestTagName != version && tryGetBestUrl(latest, out string? url)) { Notifications.Post(new SimpleNotification { @@ -55,7 +56,7 @@ namespace osu.Game.Updater Icon = FontAwesome.Solid.Download, Activated = () => { - host.OpenUrlExternally(getBestUrl(latest)); + host.OpenUrlExternally(url); return true; } }); @@ -72,8 +73,9 @@ namespace osu.Game.Updater return false; } - private string getBestUrl(GitHubRelease release) + private bool tryGetBestUrl(GitHubRelease release, [NotNullWhen(true)] out string? url) { + url = null; GitHubAsset? bestAsset = null; switch (RuntimeInfo.OS) @@ -94,15 +96,18 @@ namespace osu.Game.Updater case RuntimeInfo.Platform.iOS: // iOS releases are available via testflight. this link seems to work well enough for now. // see https://stackoverflow.com/a/32960501 - return "itms-beta://beta.itunes.apple.com/v1/app/1447765923"; + url = "itms-beta://beta.itunes.apple.com/v1/app/1447765923"; + break; case RuntimeInfo.Platform.Android: - // on our testing device this causes the download to magically disappear. + // on our testing device using the .apk URL causes the download to magically disappear. //bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".apk")); + url = release.HtmlUrl; break; } - return bestAsset?.BrowserDownloadUrl ?? release.HtmlUrl; + url ??= bestAsset?.BrowserDownloadUrl; + return url != null; } } } From f92751a7d29baf4bdc81d60725e00b8b7bb7db02 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Thu, 1 Feb 2024 18:56:38 +0100 Subject: [PATCH 206/915] Don't suggest an update on mobile if it isn't available --- osu.Game/Updater/SimpleUpdateManager.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index a7671551ef..0f9d5b929f 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -94,15 +94,18 @@ namespace osu.Game.Updater break; case RuntimeInfo.Platform.iOS: - // iOS releases are available via testflight. this link seems to work well enough for now. - // see https://stackoverflow.com/a/32960501 - url = "itms-beta://beta.itunes.apple.com/v1/app/1447765923"; + if (release.Assets?.Exists(f => f.Name.EndsWith(".ipa", StringComparison.Ordinal)) == true) + // iOS releases are available via testflight. this link seems to work well enough for now. + // see https://stackoverflow.com/a/32960501 + url = "itms-beta://beta.itunes.apple.com/v1/app/1447765923"; + break; case RuntimeInfo.Platform.Android: - // on our testing device using the .apk URL causes the download to magically disappear. - //bestAsset = release.Assets?.Find(f => f.Name.EndsWith(".apk")); - url = release.HtmlUrl; + if (release.Assets?.Exists(f => f.Name.EndsWith(".apk", StringComparison.Ordinal)) == true) + // on our testing device using the .apk URL causes the download to magically disappear. + url = release.HtmlUrl; + break; } From 966093f7cea7097e9095d5595cc8401e317b3fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 31 Jan 2024 15:50:43 +0100 Subject: [PATCH 207/915] Transform score multiplier display to also show ranked state --- .../TestSceneModSelectOverlay.cs | 8 +- ... => TestSceneRankingInformationDisplay.cs} | 18 ++-- .../Localisation/ModSelectOverlayStrings.cs | 20 ++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 19 ++-- ...isplay.cs => RankingInformationDisplay.cs} | 95 ++++++++++++------- 5 files changed, 105 insertions(+), 55 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestSceneScoreMultiplierDisplay.cs => TestSceneRankingInformationDisplay.cs} (50%) rename osu.Game/Overlays/Mods/{ScoreMultiplierDisplay.cs => RankingInformationDisplay.cs} (60%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 046954db47..99a5897dff 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("mod multiplier correct", () => { double multiplier = SelectedMods.Value.Aggregate(1d, (m, mod) => m * mod.ScoreMultiplier); - return Precision.AlmostEquals(multiplier, modSelectOverlay.ChildrenOfType().Single().Current.Value); + return Precision.AlmostEquals(multiplier, modSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value); }); assertCustomisationToggleState(disabled: false, active: false); AddAssert("setting items created", () => modSelectOverlay.ChildrenOfType().Any()); @@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("mod multiplier correct", () => { double multiplier = SelectedMods.Value.Aggregate(1d, (m, mod) => m * mod.ScoreMultiplier); - return Precision.AlmostEquals(multiplier, modSelectOverlay.ChildrenOfType().Single().Current.Value); + return Precision.AlmostEquals(multiplier, modSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value); }); assertCustomisationToggleState(disabled: false, active: false); AddAssert("setting items created", () => modSelectOverlay.ChildrenOfType().Any()); @@ -846,7 +846,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); AddAssert("difficulty multiplier display shows correct value", - () => modSelectOverlay.ChildrenOfType().Single().Current.Value, () => Is.EqualTo(0.1).Within(Precision.DOUBLE_EPSILON)); + () => modSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value, () => Is.EqualTo(0.1).Within(Precision.DOUBLE_EPSILON)); // this is highly unorthodox in a test, but because the `ModSettingChangeTracker` machinery heavily leans on events and object disposal and re-creation, // it is instrumental in the reproduction of the failure scenario that this test is supposed to cover. @@ -856,7 +856,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("reset half time speed to default", () => modSelectOverlay.ChildrenOfType().Single() .ChildrenOfType>().Single().TriggerClick()); AddUntilStep("difficulty multiplier display shows correct value", - () => modSelectOverlay.ChildrenOfType().Single().Current.Value, () => Is.EqualTo(0.3).Within(Precision.DOUBLE_EPSILON)); + () => modSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value, () => Is.EqualTo(0.3).Within(Precision.DOUBLE_EPSILON)); } private void waitForColumnLoad() => AddUntilStep("all column content loaded", () => diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScoreMultiplierDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRankingInformationDisplay.cs similarity index 50% rename from osu.Game.Tests/Visual/UserInterface/TestSceneScoreMultiplierDisplay.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneRankingInformationDisplay.cs index c2ddd814b7..42f243cc21 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScoreMultiplierDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRankingInformationDisplay.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Mods; namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public partial class TestSceneScoreMultiplierDisplay : OsuTestScene + public partial class TestSceneRankingInformationDisplay : OsuTestScene { [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); @@ -19,22 +19,24 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestBasic() { - ScoreMultiplierDisplay multiplierDisplay = null!; + RankingInformationDisplay onlinePropertiesDisplay = null!; - AddStep("create content", () => Child = multiplierDisplay = new ScoreMultiplierDisplay + AddStep("create content", () => Child = onlinePropertiesDisplay = new RankingInformationDisplay { Anchor = Anchor.Centre, Origin = Anchor.Centre }); - AddStep("set multiplier below 1", () => multiplierDisplay.Current.Value = 0.5); - AddStep("set multiplier to 1", () => multiplierDisplay.Current.Value = 1); - AddStep("set multiplier above 1", () => multiplierDisplay.Current.Value = 1.5); + AddToggleStep("toggle ranked", ranked => onlinePropertiesDisplay.Ranked.Value = ranked); + + AddStep("set multiplier below 1", () => onlinePropertiesDisplay.ModMultiplier.Value = 0.5); + AddStep("set multiplier to 1", () => onlinePropertiesDisplay.ModMultiplier.Value = 1); + AddStep("set multiplier above 1", () => onlinePropertiesDisplay.ModMultiplier.Value = 1.5); AddSliderStep("set multiplier", 0, 2, 1d, multiplier => { - if (multiplierDisplay.IsNotNull()) - multiplierDisplay.Current.Value = multiplier; + if (onlinePropertiesDisplay.IsNotNull()) + onlinePropertiesDisplay.ModMultiplier.Value = multiplier; }); } } diff --git a/osu.Game/Localisation/ModSelectOverlayStrings.cs b/osu.Game/Localisation/ModSelectOverlayStrings.cs index 86ebebd293..9513eacf02 100644 --- a/osu.Game/Localisation/ModSelectOverlayStrings.cs +++ b/osu.Game/Localisation/ModSelectOverlayStrings.cs @@ -49,6 +49,26 @@ namespace osu.Game.Localisation /// public static LocalisableString ScoreMultiplier => new TranslatableString(getKey(@"score_multiplier"), @"Score Multiplier"); + /// + /// "Ranked" + /// + public static LocalisableString Ranked => new TranslatableString(getKey(@"ranked"), @"Ranked"); + + /// + /// "Performance points can be granted for the active mods." + /// + public static LocalisableString RankedExplanation => new TranslatableString(getKey(@"ranked_explanation"), @"Performance points can be granted for the active mods."); + + /// + /// "Unranked" + /// + public static LocalisableString Unranked => new TranslatableString(getKey(@"unranked"), @"Unranked"); + + /// + /// "Performance points will not be granted due to active mods." + /// + public static LocalisableString UnrankedExplanation => new TranslatableString(getKey(@"ranked_explanation"), @"Performance points will not be granted due to active mods."); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 7271c53e7a..ddf96c1cb3 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.Mods private DeselectAllModsButton deselectAllModsButton = null!; private Container aboveColumnsContent = null!; - private ScoreMultiplierDisplay? multiplierDisplay; + private RankingInformationDisplay? rankingInformationDisplay; private BeatmapAttributesDisplay? beatmapAttributesDisplay; protected ShearedButton BackButton { get; private set; } = null!; @@ -185,7 +185,7 @@ namespace osu.Game.Overlays.Mods aboveColumnsContent = new Container { RelativeSizeAxes = Axes.X, - Height = ScoreMultiplierDisplay.HEIGHT, + Height = RankingInformationDisplay.HEIGHT, Padding = new MarginPadding { Horizontal = 100 }, Child = SearchTextBox = new ShearedSearchTextBox { @@ -200,7 +200,7 @@ namespace osu.Game.Overlays.Mods { Padding = new MarginPadding { - Top = ScoreMultiplierDisplay.HEIGHT + PADDING, + Top = RankingInformationDisplay.HEIGHT + PADDING, Bottom = PADDING }, RelativeSizeAxes = Axes.Both, @@ -269,7 +269,7 @@ namespace osu.Game.Overlays.Mods }, Children = new Drawable[] { - multiplierDisplay = new ScoreMultiplierDisplay + rankingInformationDisplay = new RankingInformationDisplay { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight @@ -315,7 +315,7 @@ namespace osu.Game.Overlays.Mods SelectedMods.BindValueChanged(_ => { - updateMultiplier(); + updateRankingInformation(); updateFromExternalSelection(); updateCustomisation(); @@ -328,7 +328,7 @@ namespace osu.Game.Overlays.Mods // // See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988 modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); - modSettingChangeTracker.SettingChanged += _ => updateMultiplier(); + modSettingChangeTracker.SettingChanged += _ => updateRankingInformation(); } }, true); @@ -450,9 +450,9 @@ namespace osu.Game.Overlays.Mods modState.ValidForSelection.Value = modState.Mod.Type != ModType.System && modState.Mod.HasImplementation && IsValidMod.Invoke(modState.Mod); } - private void updateMultiplier() + private void updateRankingInformation() { - if (multiplierDisplay == null) + if (rankingInformationDisplay == null) return; double multiplier = 1.0; @@ -460,7 +460,8 @@ namespace osu.Game.Overlays.Mods foreach (var mod in SelectedMods.Value) multiplier *= mod.ScoreMultiplier; - multiplierDisplay.Current.Value = multiplier; + rankingInformationDisplay.ModMultiplier.Value = multiplier; + rankingInformationDisplay.Ranked.Value = SelectedMods.Value.All(m => m.Ranked); } private void updateCustomisation() diff --git a/osu.Game/Overlays/Mods/ScoreMultiplierDisplay.cs b/osu.Game/Overlays/Mods/RankingInformationDisplay.cs similarity index 60% rename from osu.Game/Overlays/Mods/ScoreMultiplierDisplay.cs rename to osu.Game/Overlays/Mods/RankingInformationDisplay.cs index a86eba81e4..494f8a377f 100644 --- a/osu.Game/Overlays/Mods/ScoreMultiplierDisplay.cs +++ b/osu.Game/Overlays/Mods/RankingInformationDisplay.cs @@ -6,8 +6,8 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -22,15 +22,13 @@ namespace osu.Game.Overlays.Mods /// /// On the mod select overlay, this provides a local updating view of the aggregate score multiplier coming from mods. /// - public partial class ScoreMultiplierDisplay : ModFooterInformationDisplay, IHasCurrentValue + public partial class RankingInformationDisplay : ModFooterInformationDisplay { public const float HEIGHT = 42; - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } + public Bindable ModMultiplier = new BindableDouble(1); + + public Bindable Ranked { get; } = new BindableBool(true); private readonly BindableWithCurrent current = new BindableWithCurrent(); @@ -39,16 +37,11 @@ namespace osu.Game.Overlays.Mods private RollingCounter counter = null!; private Box flashLayer = null!; + private TextWithTooltip rankedText = null!; [Resolved] private OsuColour colours { get; set; } = null!; - public ScoreMultiplierDisplay() - { - Current.Default = 1d; - Current.Value = 1d; - } - [BackgroundDependencyLoader] private void load() { @@ -75,13 +68,20 @@ namespace osu.Game.Overlays.Mods LeftContent.AddRange(new Drawable[] { - new OsuSpriteText + new Container { + Width = 50, + RelativeSizeAxes = Axes.Y, + Margin = new MarginPadding(10), Anchor = Anchor.Centre, Origin = Anchor.Centre, - Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), - Text = ModSelectOverlayStrings.ScoreMultiplier, - Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold) + Child = rankedText = new TextWithTooltip + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), + Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold) + } } }); @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Mods Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), Anchor = Anchor.Centre, Origin = Anchor.Centre, - Current = { BindTarget = Current } + Current = { BindTarget = ModMultiplier } } }); } @@ -106,30 +106,22 @@ namespace osu.Game.Overlays.Mods { base.LoadComplete(); - Current.BindValueChanged(e => + ModMultiplier.BindValueChanged(e => { - if (e.NewValue > Current.Default) + if (e.NewValue > ModMultiplier.Default) { - MainBackground - .FadeColour(colours.ForModType(ModType.DifficultyIncrease), transition_duration, Easing.OutQuint); - counter.FadeColour(ColourProvider.Background5, transition_duration, Easing.OutQuint); + counter.FadeColour(colours.ForModType(ModType.DifficultyIncrease), transition_duration, Easing.OutQuint); } - else if (e.NewValue < Current.Default) + else if (e.NewValue < ModMultiplier.Default) { - MainBackground - .FadeColour(colours.ForModType(ModType.DifficultyReduction), transition_duration, Easing.OutQuint); - counter.FadeColour(ColourProvider.Background5, transition_duration, Easing.OutQuint); + counter.FadeColour(colours.ForModType(ModType.DifficultyReduction), transition_duration, Easing.OutQuint); } else { - MainBackground.FadeColour(ColourProvider.Background4, transition_duration, Easing.OutQuint); counter.FadeColour(Colour4.White, transition_duration, Easing.OutQuint); } - flashLayer - .FadeOutFromOne() - .FadeTo(0.15f, 60, Easing.OutQuint) - .Then().FadeOut(500, Easing.OutQuint); + flash(); const float move_amount = 4; if (e.NewValue > e.OldValue) @@ -140,10 +132,43 @@ namespace osu.Game.Overlays.Mods // required to prevent the counter initially rolling up from 0 to 1 // due to `Current.Value` having a nonstandard default value of 1. - counter.SetCountWithoutRolling(Current.Value); + counter.SetCountWithoutRolling(ModMultiplier.Value); + + Ranked.BindValueChanged(e => + { + flash(); + + if (e.NewValue) + { + rankedText.Text = ModSelectOverlayStrings.Ranked; + rankedText.TooltipText = ModSelectOverlayStrings.RankedExplanation; + rankedText.FadeColour(Colour4.White, transition_duration, Easing.OutQuint); + FrontBackground.FadeColour(ColourProvider.Background3, transition_duration, Easing.OutQuint); + } + else + { + rankedText.Text = ModSelectOverlayStrings.Unranked; + rankedText.TooltipText = ModSelectOverlayStrings.UnrankedExplanation; + rankedText.FadeColour(ColourProvider.Background5, transition_duration, Easing.OutQuint); + FrontBackground.FadeColour(colours.Orange1, transition_duration, Easing.OutQuint); + } + }, true); } - private partial class EffectCounter : RollingCounter + private void flash() + { + flashLayer + .FadeOutFromOne() + .FadeTo(0.15f, 60, Easing.OutQuint) + .Then().FadeOut(500, Easing.OutQuint); + } + + private partial class TextWithTooltip : OsuSpriteText, IHasTooltip + { + public LocalisableString TooltipText { get; set; } + } + + private partial class EffectCounter : RollingCounter, IHasTooltip { protected override double RollingDuration => 250; @@ -155,6 +180,8 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.Centre, Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold) }; + + public LocalisableString TooltipText => ModSelectOverlayStrings.ScoreMultiplier; } } } From f87ab197318b08e91757b82ea5898de19487b495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 1 Feb 2024 21:22:36 +0100 Subject: [PATCH 208/915] Apply NRT to `FooterButtonMods` --- osu.Game/Screens/Select/FooterButtonMods.cs | 47 ++++++++++----------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 69782c25bb..57784dd6ca 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -1,15 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Screens.Play.HUD; using osu.Game.Rulesets.Mods; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.UserInterface; @@ -31,28 +28,14 @@ namespace osu.Game.Screens.Select set => modDisplay.Current = value; } - protected readonly OsuSpriteText MultiplierText; - private readonly ModDisplay modDisplay; + protected OsuSpriteText MultiplierText { get; private set; } = null!; + private ModDisplay modDisplay = null!; + + private ModSettingChangeTracker? modSettingChangeTracker; + private Color4 lowMultiplierColour; private Color4 highMultiplierColour; - public FooterButtonMods() - { - ButtonContentContainer.Add(modDisplay = new ModDisplay - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(0.8f), - ExpansionMode = ExpansionMode.AlwaysContracted, - }); - ButtonContentContainer.Add(MultiplierText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(weight: FontWeight.Bold), - }); - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -62,10 +45,24 @@ namespace osu.Game.Screens.Select highMultiplierColour = colours.Green; Text = @"mods"; Hotkey = GlobalAction.ToggleModSelection; - } - [CanBeNull] - private ModSettingChangeTracker modSettingChangeTracker; + ButtonContentContainer.AddRange(new Drawable[] + { + modDisplay = new ModDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.8f), + ExpansionMode = ExpansionMode.AlwaysContracted, + }, + MultiplierText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(weight: FontWeight.Bold), + } + }); + } protected override void LoadComplete() { From 865f4d76fff5fe0cff3d7c2d6cf2aae95c99ffac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 1 Feb 2024 21:51:41 +0100 Subject: [PATCH 209/915] Add unranked indicator to song select footer too --- .../TestSceneFooterButtonMods.cs | 11 ++++ osu.Game/Screens/Select/FooterButtonMods.cs | 58 ++++++++++++++++--- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index a95bb2c9e3..b79ce6c75f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; @@ -67,6 +68,15 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert(@"Check empty multiplier", () => assertModsMultiplier(Array.Empty())); } + [Test] + public void TestUnrankedBadge() + { + AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModDeflate() })); + AddAssert("Unranked badge shown", () => footerButtonMods.UnrankedBadge.Alpha == 1); + AddStep(@"Clear selected mod", () => changeMods(Array.Empty())); + AddAssert("Unranked badge not shown", () => footerButtonMods.UnrankedBadge.Alpha == 0); + } + private void changeMods(IReadOnlyList mods) { footerButtonMods.Current.Value = mods; @@ -83,6 +93,7 @@ namespace osu.Game.Tests.Visual.UserInterface private partial class TestFooterButtonMods : FooterButtonMods { public new OsuSpriteText MultiplierText => base.MultiplierText; + public new Drawable UnrankedBadge => base.UnrankedBadge; } } } diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 57784dd6ca..5685910c0a 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -9,6 +9,9 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; using osu.Game.Graphics; @@ -16,6 +19,7 @@ using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; using osu.Game.Input.Bindings; +using osu.Game.Localisation; using osu.Game.Utils; namespace osu.Game.Screens.Select @@ -29,13 +33,27 @@ namespace osu.Game.Screens.Select } protected OsuSpriteText MultiplierText { get; private set; } = null!; - private ModDisplay modDisplay = null!; + protected Container UnrankedBadge { get; private set; } = null!; + + private readonly ModDisplay modDisplay; private ModSettingChangeTracker? modSettingChangeTracker; private Color4 lowMultiplierColour; private Color4 highMultiplierColour; + public FooterButtonMods() + { + // must be created in ctor for correct operation of `Current`. + modDisplay = new ModDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.8f), + ExpansionMode = ExpansionMode.AlwaysContracted, + }; + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -48,19 +66,38 @@ namespace osu.Game.Screens.Select ButtonContentContainer.AddRange(new Drawable[] { - modDisplay = new ModDisplay - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(0.8f), - ExpansionMode = ExpansionMode.AlwaysContracted, - }, + modDisplay, MultiplierText = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold), - } + }, + UnrankedBadge = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = colours.Yellow, + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = colours.Gray2, + Padding = new MarginPadding(5), + UseFullGlyphHeight = false, + Text = ModSelectOverlayStrings.Unranked.ToLower() + } + } + }, }); } @@ -98,6 +135,9 @@ namespace osu.Game.Screens.Select modDisplay.FadeIn(); else modDisplay.FadeOut(); + + bool anyUnrankedMods = Current.Value?.Any(m => !m.Ranked) == true; + UnrankedBadge.FadeTo(anyUnrankedMods ? 1 : 0); }); } } From c114fd8f8963f28b06df951145486689ad0084db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 1 Feb 2024 22:28:49 +0100 Subject: [PATCH 210/915] Allow pp for Sudden Death and Perfect regardless of "restart on fail" setting Closes https://github.com/ppy/osu/issues/26844. --- osu.Game/Rulesets/Mods/ModPerfect.cs | 2 +- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index f8f498ceb5..5bedf443da 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyIncrease; public override double ScoreMultiplier => 1; public override LocalisableString Description => "SS or quit."; - public override bool Ranked => UsesDefaultConfiguration; + public override bool Ranked => true; public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(ModSuddenDeath), typeof(ModAccuracyChallenge) }).ToArray(); diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 62579a168c..d07ff6ce87 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyIncrease; public override LocalisableString Description => "Miss and fail."; public override double ScoreMultiplier => 1; - public override bool Ranked => UsesDefaultConfiguration; + public override bool Ranked => true; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModPerfect)).ToArray(); From 96f66aaa2e4eaa44c167e32af51fde84ad1e6a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 1 Feb 2024 22:30:26 +0100 Subject: [PATCH 211/915] Allow pp for Accuracy Challenge Addresses https://github.com/ppy/osu/discussions/26919. --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 0072c21053..9570cddb0a 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -31,6 +31,8 @@ namespace osu.Game.Rulesets.Mods public override bool RequiresConfiguration => false; + public override bool Ranked => true; + public override string SettingDescription => base.SettingDescription.Replace(MinimumAccuracy.ToString(), MinimumAccuracy.Value.ToString("##%", NumberFormatInfo.InvariantInfo)); [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsPercentageSlider))] From ea76f7a5d88a3060369db0529330c3c28ea35752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 1 Feb 2024 22:33:49 +0100 Subject: [PATCH 212/915] Allow pp for Double/Half Time's "adjust pitch" setting --- osu.Game/Rulesets/Mods/ModDoubleTime.cs | 2 +- osu.Game/Rulesets/Mods/ModHalfTime.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index 8e430da368..fd5120a767 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mods public override IconUsage? Icon => OsuIcon.ModDoubleTime; public override ModType Type => ModType.DifficultyIncrease; public override LocalisableString Description => "Zoooooooooom..."; - public override bool Ranked => UsesDefaultConfiguration; + public override bool Ranked => SpeedChange.IsDefault; [SettingSource("Speed increase", "The actual increase to apply", SettingControlType = typeof(MultiplierSettingsSlider))] public override BindableNumber SpeedChange { get; } = new BindableDouble(1.5) diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 59e40ee9cc..efdf0d6358 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mods public override IconUsage? Icon => OsuIcon.ModHalftime; public override ModType Type => ModType.DifficultyReduction; public override LocalisableString Description => "Less zoom..."; - public override bool Ranked => UsesDefaultConfiguration; + public override bool Ranked => SpeedChange.IsDefault; [SettingSource("Speed decrease", "The actual decrease to apply", SettingControlType = typeof(MultiplierSettingsSlider))] public override BindableNumber SpeedChange { get; } = new BindableDouble(0.75) From 4dbcb41dd1e8d46e2bdee4acc9c6f858f979dd79 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 2 Feb 2024 00:44:51 +0300 Subject: [PATCH 213/915] Remove unused parameter --- osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 5de5ceb2a8..e5ba9500ee 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -137,7 +137,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load() { InternalChildren = new Drawable[] { From 5a1b0004db37148191ccbc349b8bd6fe4ca9e502 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 2 Feb 2024 01:17:28 +0300 Subject: [PATCH 214/915] Add failing test case --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index f97372e9b6..b2e607d9a3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -24,9 +24,11 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens.Menu; using osu.Game.Screens.Play; using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Utils; +using osuTK; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay @@ -53,6 +55,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Cached] private readonly VolumeOverlay volumeOverlay; + [Cached] + private readonly OsuLogo logo; + [Cached(typeof(BatteryInfo))] private readonly LocalBatteryInfo batteryInfo = new LocalBatteryInfo(); @@ -76,7 +81,14 @@ namespace osu.Game.Tests.Visual.Gameplay Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, }, - changelogOverlay = new ChangelogOverlay() + changelogOverlay = new ChangelogOverlay(), + logo = new OsuLogo + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Scale = new Vector2(0.5f), + Position = new Vector2(128f), + }, }); } @@ -204,6 +216,36 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("loads after idle", () => !loader.IsCurrentScreen()); } + [Test] + public void TestLoadNotBlockedOnOsuLogo() + { + AddStep("load dummy beatmap", () => resetPlayer(false)); + AddUntilStep("wait for current", () => loader.IsCurrentScreen()); + + AddUntilStep("wait for load ready", () => + { + moveMouse(); + return player?.LoadState == LoadState.Ready; + }); + + // move mouse in logo while waiting for load to still proceed (it shouldn't be blocked when hovering logo). + AddUntilStep("move mouse in logo", () => + { + moveMouse(); + return !loader.IsCurrentScreen(); + }); + + void moveMouse() + { + notificationOverlay.State.Value = Visibility.Hidden; + + InputManager.MoveMouseTo( + logo.ScreenSpaceDrawQuad.TopLeft + + (logo.ScreenSpaceDrawQuad.BottomRight - logo.ScreenSpaceDrawQuad.TopLeft) + * RNG.NextSingle(0.3f, 0.7f)); + } + } + [Test] public void TestLoadContinuation() { From 0502997ae958e0697fcdbcad2555e80c52b6a22d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 2 Feb 2024 01:02:13 +0300 Subject: [PATCH 215/915] Stop blocking player loader when hovering over osu! logo --- osu.Game/Screens/Play/PlayerLoader.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 232de53ac3..201511529e 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -106,8 +106,8 @@ namespace osu.Game.Screens.Play && ReadyForGameplay; protected virtual bool ReadyForGameplay => - // not ready if the user is hovering one of the panes, unless they are idle. - (IsHovered || idleTracker.IsIdle.Value) + // not ready if the user is hovering one of the panes (logo is excluded), unless they are idle. + (IsHovered || osuLogo?.IsHovered == true || idleTracker.IsIdle.Value) // not ready if the user is dragging a slider or otherwise. && inputManager.DraggedDrawable == null // not ready if a focused overlay is visible, like settings. @@ -306,10 +306,14 @@ namespace osu.Game.Screens.Play return base.OnExiting(e); } + private OsuLogo? osuLogo; + protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); + osuLogo = logo; + const double duration = 300; if (!resuming) logo.MoveTo(new Vector2(0.5f), duration, Easing.OutQuint); @@ -328,6 +332,7 @@ namespace osu.Game.Screens.Play { base.LogoExiting(logo); content.StopTracking(); + osuLogo = null; } protected override void LogoSuspending(OsuLogo logo) @@ -338,6 +343,8 @@ namespace osu.Game.Screens.Play logo .FadeOut(CONTENT_OUT_DURATION / 2, Easing.OutQuint) .ScaleTo(logo.Scale * 0.8f, CONTENT_OUT_DURATION * 2, Easing.OutQuint); + + osuLogo = null; } #endregion From e00e583bb4fbe58c8c26c847d5c2435d86f6a75d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 2 Feb 2024 03:56:38 +0300 Subject: [PATCH 216/915] Fix DrawableManiaRuleset performing skin lookup every frame --- .../UI/DrawableManiaRuleset.cs | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index bea536e4af..070021ef74 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -9,8 +9,10 @@ using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Input; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Handlers; @@ -59,8 +61,7 @@ namespace osu.Game.Rulesets.Mania.UI // Stores the current speed adjustment active in gameplay. private readonly Track speedAdjustmentTrack = new TrackVirtual(0); - [Resolved] - private ISkinSource skin { get; set; } + private ISkinSource currentSkin; public DrawableManiaRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset, beatmap, mods) @@ -72,8 +73,12 @@ namespace osu.Game.Rulesets.Mania.UI } [BackgroundDependencyLoader] - private void load() + private void load(ISkinSource source) { + currentSkin = source; + currentSkin.SourceChanged += onSkinChange; + skinChanged(); + foreach (var mod in Mods.OfType()) mod.ApplyToTrack(speedAdjustmentTrack); @@ -109,12 +114,28 @@ namespace osu.Game.Rulesets.Mania.UI updateTimeRange(); } + private ScheduledDelegate pendingSkinChange; + private float hitPosition; + + private void onSkinChange() + { + // schedule required to avoid calls after disposed. + // note that this has the side-effect of components only performing a skin change when they are alive. + pendingSkinChange?.Cancel(); + pendingSkinChange = Scheduler.Add(skinChanged); + } + + private void skinChanged() + { + hitPosition = currentSkin.GetConfig( + new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.HitPosition))?.Value + ?? Stage.HIT_TARGET_POSITION; + + pendingSkinChange = null; + } + private void updateTimeRange() { - float hitPosition = skin.GetConfig( - new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.HitPosition))?.Value - ?? Stage.HIT_TARGET_POSITION; - const float length_to_default_hit_position = 768 - LegacyManiaSkinConfiguration.DEFAULT_HIT_POSITION; float lengthToHitPosition = 768 - hitPosition; @@ -144,5 +165,13 @@ namespace osu.Game.Rulesets.Mania.UI protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay); protected override ReplayRecorder CreateReplayRecorder(Score score) => new ManiaReplayRecorder(score); + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (currentSkin.IsNotNull()) + currentSkin.SourceChanged -= onSkinChange; + } } } From 7884e5808ad0407449d4895b6b06594755cc7b65 Mon Sep 17 00:00:00 2001 From: Loreos7 Date: Fri, 2 Feb 2024 04:47:13 +0300 Subject: [PATCH 217/915] localise remaining strings --- ...RunOverlayImportFromStableScreenStrings.cs | 30 +++++++++++++++++++ .../FirstRunSetup/ScreenImportFromStable.cs | 21 ++++++++----- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs b/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs index f0620245c3..bbd83d2395 100644 --- a/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs +++ b/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs @@ -51,6 +51,36 @@ namespace osu.Game.Localisation /// public static LocalisableString Items(int arg0) => new TranslatableString(getKey(@"items"), @"{0} item(s)", arg0); + /// + /// "Data migration will use "hard links". No extra disk space will be used, and you can delete either data folder at any point without affecting the other installation." + /// + public static LocalisableString DataMigrationNoExtraSpace => new TranslatableString(getKey(@"data_migration_no_extra_space"), @"Data migration will use ""hard links"". No extra disk space will be used, and you can delete either data folder at any point without affecting the other installation."); + + /// + /// "Learn more about how "hard links" work" + /// + public static LocalisableString LearnAboutHardLinks => new TranslatableString(getKey(@"learn_about_hard_links"), @"Learn more about how ""hard links"" work"); + + /// + /// "Lightweight linking of files is not supported on your operating system yet, so a copy of all files will be made during import." + /// + public static LocalisableString LightweightLinkingNotSupported => new TranslatableString(getKey(@"lightweight_linking_not_supported"), @"Lightweight linking of files is not supported on your operating system yet, so a copy of all files will be made during import."); + + /// + /// "A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install {0}." + /// + public static LocalisableString SecondCopyWillBeMade(LocalisableString extra) => new TranslatableString(getKey(@"second_copy_will_be_made"), @"A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install {0}.", extra); + + /// + /// "(and the file system is NTFS)" + /// + public static LocalisableString ToAvoidEnsureNtfs => new TranslatableString(getKey(@"to_avoid_ensure_ntfs"), @"(and the file system is NTFS)"); + + /// + /// "(and the file system supports hard links)" + /// + public static LocalisableString ToAvoidEnsureHardLinksSupport => new TranslatableString(getKey(@"to_avoid_ensure_hard_links_support"), @"(and the file system supports hard links)"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs index 24ac5e72e8..0b2b750136 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs @@ -127,18 +127,16 @@ namespace osu.Game.Overlays.FirstRunSetup if (available) { - copyInformation.Text = - "Data migration will use \"hard links\". No extra disk space will be used, and you can delete either data folder at any point without affecting the other installation. "; - - copyInformation.AddLink("Learn more about how \"hard links\" work", LinkAction.OpenWiki, @"Client/Release_stream/Lazer/File_storage#via-hard-links"); + copyInformation.Text = FirstRunOverlayImportFromStableScreenStrings.DataMigrationNoExtraSpace; + copyInformation.AddLink(FirstRunOverlayImportFromStableScreenStrings.LearnAboutHardLinks, LinkAction.OpenWiki, @"Client/Release_stream/Lazer/File_storage#via-hard-links"); } else if (!RuntimeInfo.IsDesktop) - copyInformation.Text = "Lightweight linking of files is not supported on your operating system yet, so a copy of all files will be made during import."; + copyInformation.Text = FirstRunOverlayImportFromStableScreenStrings.LightweightLinkingNotSupported; else { copyInformation.Text = RuntimeInfo.OS == RuntimeInfo.Platform.Windows - ? "A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install (and the file system is NTFS). " - : "A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install (and the file system supports hard links). "; + ? FirstRunOverlayImportFromStableScreenStrings.SecondCopyWillBeMade(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureNtfs) + : FirstRunOverlayImportFromStableScreenStrings.SecondCopyWillBeMade(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureHardLinksSupport); copyInformation.AddLink(GeneralSettingsStrings.ChangeFolderLocation, () => { game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen())); @@ -328,4 +326,13 @@ namespace osu.Game.Overlays.FirstRunSetup } } } + + public enum FileSystemAddition + { + [LocalisableDescription(typeof(FirstRunOverlayImportFromStableScreenStrings), nameof(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureNtfs))] + ToAvoidEnsureNtfs, + + [LocalisableDescription(typeof(FirstRunOverlayImportFromStableScreenStrings), nameof(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureHardLinksSupport))] + ToAvoidEnsureHardLinksSupport, + } } From 8dce158a13e05911273c5fb07f77555dc3d0b6ae Mon Sep 17 00:00:00 2001 From: Loreos7 Date: Fri, 2 Feb 2024 04:49:22 +0300 Subject: [PATCH 218/915] localise update-related strings --- osu.Game/Localisation/NotificationsStrings.cs | 22 +++++++++++++++++++ osu.Game/Updater/UpdateManager.cs | 9 ++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/osu.Game/Localisation/NotificationsStrings.cs b/osu.Game/Localisation/NotificationsStrings.cs index fb3dab032d..f4965e4ebe 100644 --- a/osu.Game/Localisation/NotificationsStrings.cs +++ b/osu.Game/Localisation/NotificationsStrings.cs @@ -113,6 +113,28 @@ Please try changing your audio device to a working setting."); /// public static LocalisableString MismatchingBeatmapForReplay => new TranslatableString(getKey(@"mismatching_beatmap_for_replay"), @"Your local copy of the beatmap for this replay appears to be different than expected. You may need to update or re-download it."); + /// + /// "You are now running osu! {version}. + /// Click to see what's new!" + /// + public static LocalisableString GameVersionAfterUpdate(string version) => new TranslatableString(getKey(@"game_version_after_update"), @"You are now running osu! {0}. +Click to see what's new!", version); + + /// + /// "Update ready to install. Click to restart!" + /// + public static LocalisableString UpdateReadyToInstall => new TranslatableString(getKey(@"update_ready_to_install"), @"Update ready to install. Click to restart!"); + + /// + /// "Downloading update..." + /// + public static LocalisableString DownloadingUpdate => new TranslatableString(getKey(@"downloading_update"), @"Downloading update..."); + + /// + /// "Installing update..." + /// + public static LocalisableString InstallingUpdate => new TranslatableString(getKey(@"installing_update"), @"Installing update..."); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs index 190748137a..8f13e0f42a 100644 --- a/osu.Game/Updater/UpdateManager.cs +++ b/osu.Game/Updater/UpdateManager.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Graphics; +using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osuTK; @@ -92,7 +93,7 @@ namespace osu.Game.Updater public UpdateCompleteNotification(string version) { this.version = version; - Text = $"You are now running osu! {version}.\nClick to see what's new!"; + Text = NotificationsStrings.GameVersionAfterUpdate(version); } [BackgroundDependencyLoader] @@ -114,7 +115,7 @@ namespace osu.Game.Updater { public UpdateApplicationCompleteNotification() { - Text = @"Update ready to install. Click to restart!"; + Text = NotificationsStrings.UpdateReadyToInstall; } } @@ -166,13 +167,13 @@ namespace osu.Game.Updater { State = ProgressNotificationState.Active; Progress = 0; - Text = @"Downloading update..."; + Text = NotificationsStrings.DownloadingUpdate; } public void StartInstall() { Progress = 0; - Text = @"Installing update..."; + Text = NotificationsStrings.InstallingUpdate; } public void FailDownload() From 53c5483eba108acb4c8782764ae4840d414428dd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 2 Feb 2024 04:53:48 +0300 Subject: [PATCH 219/915] Reduce allocation in Playfield --- osu.Game/Rulesets/UI/Playfield.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index e9c35555c8..90a2f63faa 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -247,10 +247,14 @@ namespace osu.Game.Rulesets.UI nestedPlayfields.Add(otherPlayfield); } + private Mod[] mods; + protected override void LoadComplete() { base.LoadComplete(); + mods = Mods?.ToArray(); + // in the case a consumer forgets to add the HitObjectContainer, we will add it here. if (HitObjectContainer.Parent == null) AddInternal(HitObjectContainer); @@ -260,9 +264,9 @@ namespace osu.Game.Rulesets.UI { base.Update(); - if (!IsNested && Mods != null) + if (!IsNested && mods != null) { - foreach (var mod in Mods) + foreach (Mod mod in mods) { if (mod is IUpdatableByPlayfield updatable) updatable.Update(this); @@ -403,10 +407,13 @@ namespace osu.Game.Rulesets.UI // If this is the first time this DHO is being used, then apply the DHO mods. // This is done before Apply() so that the state is updated once when the hitobject is applied. - if (Mods != null) + if (mods != null) { - foreach (var m in Mods.OfType()) - m.ApplyToDrawableHitObject(dho); + foreach (Mod mod in mods) + { + if (mod is IApplicableToDrawableHitObject applicable) + applicable.ApplyToDrawableHitObject(dho); + } } } From 2ff46daf5ede3204da4263fa265ee417601b667a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Feb 2024 06:34:47 +0100 Subject: [PATCH 220/915] Also change icon and tooltip text when pending 2FA --- osu.Game/Localisation/ToolbarStrings.cs | 5 +++++ osu.Game/Overlays/Toolbar/ToolbarUserButton.cs | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Localisation/ToolbarStrings.cs b/osu.Game/Localisation/ToolbarStrings.cs index e71a3fff9b..5822f76e02 100644 --- a/osu.Game/Localisation/ToolbarStrings.cs +++ b/osu.Game/Localisation/ToolbarStrings.cs @@ -19,6 +19,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Connecting => new TranslatableString(getKey(@"connecting"), @"Connecting..."); + /// + /// "Verification required" + /// + public static LocalisableString VerificationRequired => new TranslatableString(getKey(@"verification_required"), @"Verification required"); + /// /// "home" /// diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 1e812d7238..2620e850c8 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -99,7 +99,6 @@ namespace osu.Game.Overlays.Toolbar switch (state.NewValue) { - case APIState.RequiresSecondFactorAuth: case APIState.Connecting: TooltipText = ToolbarStrings.Connecting; spinner.Show(); @@ -108,6 +107,13 @@ namespace osu.Game.Overlays.Toolbar case APIState.Failing: TooltipText = ToolbarStrings.AttemptingToReconnect; spinner.Show(); + failingIcon.Icon = FontAwesome.Solid.ExclamationTriangle; + break; + + case APIState.RequiresSecondFactorAuth: + TooltipText = ToolbarStrings.VerificationRequired; + spinner.Show(); + failingIcon.Icon = FontAwesome.Solid.Key; break; case APIState.Offline: From dfd966e039e49a3582b519146440b866ae00705c Mon Sep 17 00:00:00 2001 From: Mike Will Date: Wed, 31 Jan 2024 18:47:47 -0500 Subject: [PATCH 221/915] Improve silence detection in `MutedNotification` Instead of checking the master and music volumes separately to see if they're <= 1%, check the aggregate of the two volumes to see if it's <= -60 dB. When muted notification is activated, restore the aggregate volume level to -30 dB. --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 16 +++++++++---- osu.Game/Screens/Play/PlayerLoader.cs | 23 +++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index f97372e9b6..2798d77373 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -264,15 +264,23 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] - public void TestMutedNotificationMasterVolume() + public void TestMutedNotificationHighMasterVolume() { - addVolumeSteps("master volume", () => audioManager.Volume.Value = 0, () => audioManager.Volume.Value == 0.5); + addVolumeSteps("high master volume", () => + { + audioManager.Volume.Value = 0.1; + audioManager.VolumeTrack.Value = 0.01; + }, () => audioManager.Volume.Value == 0.1 && audioManager.VolumeTrack.Value == 0.32); } [Test] - public void TestMutedNotificationTrackVolume() + public void TestMutedNotificationLowMasterVolume() { - addVolumeSteps("music volume", () => audioManager.VolumeTrack.Value = 0, () => audioManager.VolumeTrack.Value == 0.5); + addVolumeSteps("low master volume", () => + { + audioManager.Volume.Value = 0.01; + audioManager.VolumeTrack.Value = 0.1; + }, () => audioManager.Volume.Value == 0.03 && audioManager.VolumeTrack.Value == 1); } [Test] diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 232de53ac3..6282041f2c 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -544,14 +544,14 @@ namespace osu.Game.Screens.Play private int restartCount; - private const double volume_requirement = 0.01; + private const double volume_requirement = 1e-3; // -60 dB private void showMuteWarningIfNeeded() { if (!muteWarningShownOnce.Value) { // Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value <= volume_requirement || audioManager.VolumeTrack.Value <= volume_requirement) + if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value * audioManager.VolumeTrack.Value <= volume_requirement) { notificationOverlay?.Post(new MutedNotification()); muteWarningShownOnce.Value = true; @@ -581,11 +581,20 @@ namespace osu.Game.Screens.Play volumeOverlay.IsMuted.Value = false; // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. - // Note that we only restore halfway to ensure the user isn't suddenly overloaded by unexpectedly high volume. - if (audioManager.Volume.Value <= volume_requirement) - audioManager.Volume.Value = 0.5f; - if (audioManager.VolumeTrack.Value <= volume_requirement) - audioManager.VolumeTrack.Value = 0.5f; + // Note that we only restore to -30 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. + if (audioManager.Volume.Value * audioManager.VolumeTrack.Value <= volume_requirement) + { + // Prioritize increasing music over master volume as to avoid also increasing effects volume. + const double target = 0.031622776601684; // 10 ^ (-30 / 20) + double result = target / Math.Max(0.01, audioManager.Volume.Value); + if (result > 1) + { + audioManager.Volume.Value = target; + audioManager.VolumeTrack.Value = 1; + } + else + audioManager.VolumeTrack.Value = result; + } return true; }; From bb6387bea01ebac9e5c3e6c2ffa043892824319b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Feb 2024 06:53:00 +0100 Subject: [PATCH 222/915] Enable NRT in `ScreenEntry` --- .../Overlays/AccountCreation/ScreenEntry.cs | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 9ad507d82a..64d0fa94ab 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using System.Threading.Tasks; @@ -28,28 +26,28 @@ namespace osu.Game.Overlays.AccountCreation { public partial class ScreenEntry : AccountCreationScreen { - private ErrorTextFlowContainer usernameDescription; - private ErrorTextFlowContainer emailAddressDescription; - private ErrorTextFlowContainer passwordDescription; + private ErrorTextFlowContainer usernameDescription = null!; + private ErrorTextFlowContainer emailAddressDescription = null!; + private ErrorTextFlowContainer passwordDescription = null!; - private OsuTextBox usernameTextBox; - private OsuTextBox emailTextBox; - private OsuPasswordTextBox passwordTextBox; + private OsuTextBox usernameTextBox = null!; + private OsuTextBox emailTextBox = null!; + private OsuPasswordTextBox passwordTextBox = null!; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; - private ShakeContainer registerShake; - private ITextPart characterCheckText; + private ShakeContainer registerShake = null!; + private ITextPart characterCheckText = null!; - private OsuTextBox[] textboxes; - private LoadingLayer loadingLayer; + private OsuTextBox[] textboxes = null!; + private LoadingLayer loadingLayer = null!; [Resolved] - private GameHost host { get; set; } + private GameHost? host { get; set; } [Resolved] - private OsuGame game { get; set; } + private OsuGame game { get; set; } = null!; [BackgroundDependencyLoader] private void load() @@ -180,7 +178,7 @@ namespace osu.Game.Overlays.AccountCreation Task.Run(() => { bool success; - RegistrationRequest.RegistrationRequestErrors errors = null; + RegistrationRequest.RegistrationRequestErrors? errors = null; try { @@ -241,6 +239,6 @@ namespace osu.Game.Overlays.AccountCreation return false; } - private OsuTextBox nextUnfilledTextBox() => textboxes.FirstOrDefault(t => string.IsNullOrEmpty(t.Text)); + private OsuTextBox? nextUnfilledTextBox() => textboxes.FirstOrDefault(t => string.IsNullOrEmpty(t.Text)); } } From b58ac7950bd69d383cd26e6c3142b4ea568e9a1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Feb 2024 06:53:17 +0100 Subject: [PATCH 223/915] Make game dependency in `ScreenEntry` optional to unbreak tests --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 64d0fa94ab..ab462357c0 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.AccountCreation private GameHost? host { get; set; } [Resolved] - private OsuGame game { get; set; } = null!; + private OsuGame? game { get; set; } [BackgroundDependencyLoader] private void load() @@ -208,7 +208,7 @@ namespace osu.Game.Overlays.AccountCreation if (!string.IsNullOrEmpty(errors.Message)) passwordDescription.AddErrors(new[] { errors.Message }); - game.OpenUrlExternally($"{errors.Redirect}?username={usernameTextBox.Text}&email={emailTextBox.Text}", true); + game?.OpenUrlExternally($"{errors.Redirect}?username={usernameTextBox.Text}&email={emailTextBox.Text}", true); } } else From 93d34e411535f2a47442146f92f62a3cab150821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Feb 2024 06:54:18 +0100 Subject: [PATCH 224/915] Enable NRT in `ScreenWarning` --- osu.Game/Overlays/AccountCreation/ScreenWarning.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index 0fbf6ba59e..c24bd32bb4 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,14 +21,14 @@ namespace osu.Game.Overlays.AccountCreation { public partial class ScreenWarning : AccountCreationScreen { - private OsuTextFlowContainer multiAccountExplanationText; - private LinkFlowContainer furtherAssistance; + private OsuTextFlowContainer multiAccountExplanationText = null!; + private LinkFlowContainer furtherAssistance = null!; - [Resolved(canBeNull: true)] - private IAPIProvider api { get; set; } + [Resolved] + private IAPIProvider? api { get; set; } - [Resolved(canBeNull: true)] - private OsuGame game { get; set; } + [Resolved] + private OsuGame? game { get; set; } private const string help_centre_url = "/help/wiki/Help_Centre#login"; From 45f60b035e549e24a9497bf0f11de2eb3d6a4b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Feb 2024 07:05:27 +0100 Subject: [PATCH 225/915] Enable NRT in `AccountCreationOverlay` --- osu.Game/Overlays/AccountCreationOverlay.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index 576ee92b48..82fc5508f1 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -25,7 +23,9 @@ namespace osu.Game.Overlays { private const float transition_time = 400; - private ScreenWelcome welcomeScreen; + private ScreenWelcome welcomeScreen = null!; + + private ScheduledDelegate? scheduledHide; public AccountCreationOverlay() { @@ -108,8 +108,6 @@ namespace osu.Game.Overlays this.FadeOut(100); } - private ScheduledDelegate scheduledHide; - private void apiStateChanged(ValueChangedEvent state) { switch (state.NewValue) From a00cf87925a06b485d039ba03dcf72fc06127789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Feb 2024 06:50:27 +0100 Subject: [PATCH 226/915] Add 2FA verification screen to registration flow --- .../ScreenEmailVerification.cs | 24 +++++++++++++++++++ .../Overlays/AccountCreation/ScreenEntry.cs | 11 +++++++++ 2 files changed, 35 insertions(+) create mode 100644 osu.Game/Overlays/AccountCreation/ScreenEmailVerification.cs diff --git a/osu.Game/Overlays/AccountCreation/ScreenEmailVerification.cs b/osu.Game/Overlays/AccountCreation/ScreenEmailVerification.cs new file mode 100644 index 0000000000..f3b42117ea --- /dev/null +++ b/osu.Game/Overlays/AccountCreation/ScreenEmailVerification.cs @@ -0,0 +1,24 @@ +// 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.Game.Overlays.Login; + +namespace osu.Game.Overlays.AccountCreation +{ + public partial class ScreenEmailVerification : AccountCreationScreen + { + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new SecondFactorAuthForm + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(20), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + } + } +} diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index ab462357c0..f57c7d22a2 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -37,6 +38,8 @@ namespace osu.Game.Overlays.AccountCreation [Resolved] private IAPIProvider api { get; set; } = null!; + private IBindable apiState = null!; + private ShakeContainer registerShake = null!; private ITextPart characterCheckText = null!; @@ -142,6 +145,8 @@ namespace osu.Game.Overlays.AccountCreation passwordTextBox.Current.BindValueChanged(_ => updateCharacterCheckTextColour(), true); characterCheckText.DrawablePartsRecreated += _ => updateCharacterCheckTextColour(); + + apiState = api.State.GetBoundCopy(); } private void updateCharacterCheckTextColour() @@ -221,6 +226,12 @@ namespace osu.Game.Overlays.AccountCreation return; } + apiState.BindValueChanged(state => + { + if (state.NewValue == APIState.RequiresSecondFactorAuth) + this.Push(new ScreenEmailVerification()); + }); + api.Login(usernameTextBox.Text, passwordTextBox.Text); }); }); From 091618db1a81ec017ef0903f2844b95e048465e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Feb 2024 07:04:31 +0100 Subject: [PATCH 227/915] Add test coverage of full account creation flow --- .../Online/TestSceneAccountCreationOverlay.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index 79fb063ea9..b9d7312233 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; @@ -67,5 +68,34 @@ namespace osu.Game.Tests.Visual.Online }); AddUntilStep("overlay is hidden", () => accountCreation.State.Value == Visibility.Hidden); } + + [Test] + public void TestFullFlow() + { + AddStep("log out", () => API.Logout()); + + AddStep("show manually", () => accountCreation.Show()); + AddUntilStep("overlay is visible", () => accountCreation.State.Value == Visibility.Visible); + + AddStep("click button", () => accountCreation.ChildrenOfType().Single().TriggerClick()); + AddUntilStep("warning screen is present", () => accountCreation.ChildrenOfType().SingleOrDefault()?.IsPresent == true); + + AddStep("proceed", () => accountCreation.ChildrenOfType().Single().TriggerClick()); + AddUntilStep("entry screen is present", () => accountCreation.ChildrenOfType().SingleOrDefault()?.IsPresent == true); + + AddStep("input details", () => + { + var entryScreen = accountCreation.ChildrenOfType().Single(); + entryScreen.ChildrenOfType().ElementAt(0).Text = "new_user"; + entryScreen.ChildrenOfType().ElementAt(1).Text = "new.user@fake.mail"; + entryScreen.ChildrenOfType().ElementAt(2).Text = "password"; + }); + AddStep("click button", () => accountCreation.ChildrenOfType().Single() + .ChildrenOfType().Single().TriggerClick()); + AddUntilStep("verification screen is present", () => accountCreation.ChildrenOfType().SingleOrDefault()?.IsPresent == true); + + AddStep("verify", () => ((DummyAPIAccess)API).AuthenticateSecondFactor("abcdefgh")); + AddUntilStep("overlay is hidden", () => accountCreation.State.Value == Visibility.Hidden); + } } } From 3122211268346b9c57e3ea8b96e77090251f06e5 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 02:12:46 -0500 Subject: [PATCH 228/915] Change silence threshold and target restore volume level --- osu.Game/Screens/Play/PlayerLoader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6282041f2c..9ec7197429 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -544,7 +544,7 @@ namespace osu.Game.Screens.Play private int restartCount; - private const double volume_requirement = 1e-3; // -60 dB + private const double volume_requirement = 0.01; private void showMuteWarningIfNeeded() { @@ -581,11 +581,11 @@ namespace osu.Game.Screens.Play volumeOverlay.IsMuted.Value = false; // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. - // Note that we only restore to -30 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. + // Note that we only restore to -20 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. if (audioManager.Volume.Value * audioManager.VolumeTrack.Value <= volume_requirement) { // Prioritize increasing music over master volume as to avoid also increasing effects volume. - const double target = 0.031622776601684; // 10 ^ (-30 / 20) + const double target = 0.1; double result = target / Math.Max(0.01, audioManager.Volume.Value); if (result > 1) { From f4a2d5f3f489c1332f7e200747dd9b665337db7a Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 02:41:58 -0500 Subject: [PATCH 229/915] Round off inaccuracies in the aggregate volume before evaluating --- osu.Game/Screens/Play/PlayerLoader.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 9ec7197429..50c95ce525 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -551,7 +551,8 @@ namespace osu.Game.Screens.Play if (!muteWarningShownOnce.Value) { // Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value * audioManager.VolumeTrack.Value <= volume_requirement) + double aggregate = Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100; + if (volumeOverlay?.IsMuted.Value == true || aggregate <= volume_requirement) { notificationOverlay?.Post(new MutedNotification()); muteWarningShownOnce.Value = true; @@ -582,7 +583,8 @@ namespace osu.Game.Screens.Play // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. // Note that we only restore to -20 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. - if (audioManager.Volume.Value * audioManager.VolumeTrack.Value <= volume_requirement) + double aggregate = Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100; + if (aggregate <= volume_requirement) { // Prioritize increasing music over master volume as to avoid also increasing effects volume. const double target = 0.1; From 5d9200b4fe02c4ed0f287fe0f43c5f2433b52ec9 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 02:59:02 -0500 Subject: [PATCH 230/915] Update tests to reflect new restore target volume --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 2798d77373..99bb006071 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -268,9 +268,9 @@ namespace osu.Game.Tests.Visual.Gameplay { addVolumeSteps("high master volume", () => { - audioManager.Volume.Value = 0.1; + audioManager.Volume.Value = 0.15; audioManager.VolumeTrack.Value = 0.01; - }, () => audioManager.Volume.Value == 0.1 && audioManager.VolumeTrack.Value == 0.32); + }, () => audioManager.Volume.Value == 0.15 && audioManager.VolumeTrack.Value == 0.67); } [Test] @@ -279,8 +279,8 @@ namespace osu.Game.Tests.Visual.Gameplay addVolumeSteps("low master volume", () => { audioManager.Volume.Value = 0.01; - audioManager.VolumeTrack.Value = 0.1; - }, () => audioManager.Volume.Value == 0.03 && audioManager.VolumeTrack.Value == 1); + audioManager.VolumeTrack.Value = 0.15; + }, () => audioManager.Volume.Value == 0.1 && audioManager.VolumeTrack.Value == 1); } [Test] From c60e110976ca7214c200d90da45bdd165cb0b39c Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 03:09:19 -0500 Subject: [PATCH 231/915] Try to fix code quality issues raised by workflow --- osu.Game/Screens/Play/PlayerLoader.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 50c95ce525..1d0ecfc12d 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -551,8 +551,7 @@ namespace osu.Game.Screens.Play if (!muteWarningShownOnce.Value) { // Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - double aggregate = Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100; - if (volumeOverlay?.IsMuted.Value == true || aggregate <= volume_requirement) + if (volumeOverlay?.IsMuted.Value == true || Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100 <= volume_requirement) { notificationOverlay?.Post(new MutedNotification()); muteWarningShownOnce.Value = true; @@ -583,11 +582,11 @@ namespace osu.Game.Screens.Play // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. // Note that we only restore to -20 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. - double aggregate = Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100; - if (aggregate <= volume_requirement) + if (Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100 <= volume_requirement) { - // Prioritize increasing music over master volume as to avoid also increasing effects volume. const double target = 0.1; + + // Prioritize increasing music over master volume as to avoid also increasing effects volume. double result = target / Math.Max(0.01, audioManager.Volume.Value); if (result > 1) { From 29a28905820bb1242cda326a2e4610e058bef1c2 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 03:46:05 -0500 Subject: [PATCH 232/915] fix code quality error #2 --- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 1d0ecfc12d..40ffa844da 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -584,10 +584,10 @@ namespace osu.Game.Screens.Play // Note that we only restore to -20 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. if (Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100 <= volume_requirement) { - const double target = 0.1; - // Prioritize increasing music over master volume as to avoid also increasing effects volume. + const double target = 0.1; double result = target / Math.Max(0.01, audioManager.Volume.Value); + if (result > 1) { audioManager.Volume.Value = target; From 906560f66d971778ab8ec00866b3aa3d0afb8caa Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 04:06:22 -0500 Subject: [PATCH 233/915] Fix mute button test Lowering the master volume in the previous test meant that the volume levels would end up being modified. --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 99bb006071..04b681989f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -289,9 +289,10 @@ namespace osu.Game.Tests.Visual.Gameplay addVolumeSteps("mute button", () => { // Importantly, in the case the volume is muted but the user has a volume level set, it should be retained. + audioManager.Volume.Value = 0.5f; audioManager.VolumeTrack.Value = 0.5f; volumeOverlay.IsMuted.Value = true; - }, () => !volumeOverlay.IsMuted.Value && audioManager.VolumeTrack.Value == 0.5f); + }, () => !volumeOverlay.IsMuted.Value && audioManager.Volume.Value == 0.5f && audioManager.VolumeTrack.Value == 0.5f); } /// From e4ec8c111b90542c8705e73eaabca6bf9557f63f Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 05:48:57 -0500 Subject: [PATCH 234/915] give better volume names to `addVolumeSteps` --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 04b681989f..67e94a2960 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -266,7 +266,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestMutedNotificationHighMasterVolume() { - addVolumeSteps("high master volume", () => + addVolumeSteps("master and music volumes", () => { audioManager.Volume.Value = 0.15; audioManager.VolumeTrack.Value = 0.01; @@ -276,7 +276,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestMutedNotificationLowMasterVolume() { - addVolumeSteps("low master volume", () => + addVolumeSteps("master and music volumes", () => { audioManager.Volume.Value = 0.01; audioManager.VolumeTrack.Value = 0.15; From b44f77cee1b6adb6568f9b5764382a6cd6ffe2ed Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 19:48:13 +0900 Subject: [PATCH 235/915] Update R# + fix inspections --- .config/dotnet-tools.json | 4 +- .globalconfig | 4 +- .../TestScenePathControlPointVisualiser.cs | 2 +- .../TestSceneFollowPoints.cs | 2 +- .../TestSceneSkinFallbacks.cs | 2 + .../UI/DrumTouchInputArea.cs | 3 +- osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs | 6 ++- osu.Game.Tests/Database/RulesetStoreTests.cs | 6 +-- .../Gameplay/TestSceneStoryboardSamples.cs | 4 +- .../TestSceneBrokenRulesetHandling.cs | 12 +++--- .../Editing/TestSceneEditorTestGameplay.cs | 4 +- .../Gameplay/TestSceneReplayRecorder.cs | 2 +- .../Gameplay/TestSceneSpectatorPlayback.cs | 2 +- .../Visual/Menus/TestSceneToolbar.cs | 2 +- .../TestSceneLoungeRoomsContainer.cs | 2 +- .../TestScenePlaylistsMatchSettingsOverlay.cs | 2 +- .../TestScenePlaylistsRoomCreation.cs | 8 ++-- .../Visual/Ranking/TestSceneResultsScreen.cs | 2 +- .../TestSceneFirstRunSetupOverlay.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 3 +- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 2 +- .../SelectionCycleFillFlowContainer.cs | 4 +- .../UserInterface/BreadcrumbControl.cs | 2 + osu.Game/IO/IStorageResourceProvider.cs | 2 +- osu.Game/Online/Spectator/SpectatorClient.cs | 3 +- osu.Game/Overlays/Comments/VotePill.cs | 2 +- .../Overlays/MedalSplash/DrawableMedal.cs | 2 + osu.Game/Overlays/Volume/VolumeMeter.cs | 2 + .../Objects/Drawables/DrawableHitObject.cs | 3 +- .../Objects/Pooling/HitObjectEntryManager.cs | 5 +-- .../Edit/Compose/Components/DragBox.cs | 2 + osu.Game/Screens/Menu/ButtonArea.cs | 3 ++ .../OnlinePlay/Components/RoomManager.cs | 2 + .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 +- .../Screens/Play/HUD/HoldForMenuButton.cs | 2 +- .../Multiplayer/MultiplayerTestScene.cs | 4 +- .../IOnlinePlayTestSceneDependencies.cs | 12 +++--- .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 42 +++++++++++-------- .../OnlinePlayTestSceneDependencies.cs | 4 +- osu.Game/Tests/Visual/SkinnableTestScene.cs | 4 +- osu.sln.DotSettings | 5 +++ 41 files changed, 102 insertions(+), 81 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index b8dc201559..99906f0895 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,13 +3,13 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2022.2.3", + "version": "2023.3.3", "commands": [ "jb" ] }, "nvika": { - "version": "2.2.0", + "version": "3.0.0", "commands": [ "nvika" ] diff --git a/.globalconfig b/.globalconfig index a7b652c454..a4d4707f9b 100644 --- a/.globalconfig +++ b/.globalconfig @@ -1,5 +1,3 @@ -is_global = true - # .NET Code Style # IDE styles reference: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ @@ -56,4 +54,4 @@ dotnet_diagnostic.RS0030.severity = error # Temporarily disable analysing CanBeNull = true in NRT contexts due to mobile issues. # See: https://github.com/ppy/osu/pull/19677 -dotnet_diagnostic.OSUF001.severity = none \ No newline at end of file +dotnet_diagnostic.OSUF001.severity = none diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs index 8234381283..2b53554ed1 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs @@ -206,7 +206,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor { AddStep($"click context menu item \"{contextMenuText}\"", () => { - MenuItem item = visualiser.ContextMenuItems.FirstOrDefault(menuItem => menuItem.Text.Value == "Curve type")?.Items.FirstOrDefault(menuItem => menuItem.Text.Value == contextMenuText); + MenuItem item = visualiser.ContextMenuItems!.FirstOrDefault(menuItem => menuItem.Text.Value == "Curve type")?.Items.FirstOrDefault(menuItem => menuItem.Text.Value == contextMenuText); item?.Action.Value?.Invoke(); }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index eefaa3cae3..28c9d71139 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -183,7 +183,7 @@ namespace osu.Game.Rulesets.Osu.Tests break; } - hitObjectContainer.Add(drawableObject); + hitObjectContainer.Add(drawableObject!); followPointRenderer.AddFollowPoints(objects[i]); } }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 09b906cb10..c624fbbe73 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -173,6 +174,7 @@ namespace osu.Game.Rulesets.Osu.Tests public IEnumerable AllSources => new[] { this }; + [CanBeNull] public event Action SourceChanged; private bool enabled = true; diff --git a/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs b/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs index 29ccd96675..0b7f6f621a 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumTouchInputArea.cs @@ -179,10 +179,9 @@ namespace osu.Game.Rulesets.Taiko.UI TaikoAction taikoAction = getTaikoActionFromPosition(position); // Not too sure how this can happen, but let's avoid throwing. - if (trackedActions.ContainsKey(source)) + if (!trackedActions.TryAdd(source, taikoAction)) return; - trackedActions.Add(source, taikoAction); keyBindingContainer.TriggerPressed(taikoAction); } diff --git a/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs b/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs index f4b1028c0e..3c26f8e39a 100644 --- a/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Moq; using NUnit.Framework; using osu.Game.Beatmaps; @@ -98,9 +99,10 @@ namespace osu.Game.Tests.Beatmaps Beatmap = beatmap; } +#pragma warning disable CS0067 + [CanBeNull] public event Action> ObjectConverted; - - protected virtual void OnObjectConverted(HitObject arg1, IEnumerable arg2) => ObjectConverted?.Invoke(arg1, arg2); +#pragma warning restore CS0067 public IBeatmap Beatmap { get; } diff --git a/osu.Game.Tests/Database/RulesetStoreTests.cs b/osu.Game.Tests/Database/RulesetStoreTests.cs index 8b4c6e2411..ddf207342a 100644 --- a/osu.Game.Tests/Database/RulesetStoreTests.cs +++ b/osu.Game.Tests/Database/RulesetStoreTests.cs @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Database Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.True); // Availability is updated on construction of a RealmRulesetStore - var _ = new RealmRulesetStore(realm, storage); + _ = new RealmRulesetStore(realm, storage); Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.False); }); @@ -104,13 +104,13 @@ namespace osu.Game.Tests.Database Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.True); // Availability is updated on construction of a RealmRulesetStore - var _ = new RealmRulesetStore(realm, storage); + _ = new RealmRulesetStore(realm, storage); Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.False); // Simulate the ruleset getting updated LoadTestRuleset.Version = Ruleset.CURRENT_RULESET_API_VERSION; - var __ = new RealmRulesetStore(realm, storage); + _ = new RealmRulesetStore(realm, storage); Assert.That(realm.Run(r => r.Find(rulesetShortName)!.Available), Is.True); }); diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index 4fb9db845b..61161f3206 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -203,9 +203,9 @@ namespace osu.Game.Tests.Gameplay public IRenderer Renderer => host.Renderer; public AudioManager AudioManager => Audio; - public IResourceStore Files => null; + public IResourceStore Files => null!; public new IResourceStore Resources => base.Resources; - public RealmAccess RealmAccess => null; + public RealmAccess RealmAccess => null!; public IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore) => null; #endregion diff --git a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs index dac6beea65..b378704e80 100644 --- a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs +++ b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs @@ -56,9 +56,9 @@ namespace osu.Game.Tests.Rulesets public override IEnumerable GetModsFor(ModType type) => new Mod[] { null }; - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; - public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null!; + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null!; + public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null!; } private class TestAPIIncompatibleRuleset : Ruleset @@ -69,9 +69,9 @@ namespace osu.Game.Tests.Rulesets // simulate API incompatibility by throwing similar exceptions. public override IEnumerable GetModsFor(ModType type) => throw new MissingMethodException(); - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; - public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null!; + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null!; + public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null!; } } } diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs index bbd7123f20..ca5e89c8ed 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs @@ -142,7 +142,7 @@ namespace osu.Game.Tests.Visual.Editing AddStep("dismiss prompt", () => { - var button = DialogOverlay.CurrentDialog.Buttons.Last(); + var button = DialogOverlay.CurrentDialog!.Buttons.Last(); InputManager.MoveMouseTo(button); InputManager.Click(MouseButton.Left); }); @@ -167,7 +167,7 @@ namespace osu.Game.Tests.Visual.Editing }); AddUntilStep("save prompt shown", () => DialogOverlay.CurrentDialog is SaveRequiredPopupDialog); - AddStep("save changes", () => DialogOverlay.CurrentDialog.PerformOkAction()); + AddStep("save changes", () => DialogOverlay.CurrentDialog!.PerformOkAction()); EditorPlayer editorPlayer = null; AddUntilStep("player pushed", () => (editorPlayer = Stack.CurrentScreen as EditorPlayer) != null); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index c51883b221..a7ab021884 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void Update() { base.Update(); - playbackManager?.ReplayInputHandler.SetFrameFromTime(Time.Current - 100); + playbackManager?.ReplayInputHandler?.SetFrameFromTime(Time.Current - 100); } [TearDownSteps] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index 3a5b3864af..dd5bbf70b4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay foreach (var legacyFrame in frames.Frames) { var frame = new TestReplayFrame(); - frame.FromLegacy(legacyFrame, null); + frame.FromLegacy(legacyFrame, null!); playbackReplay.Frames.Add(frame); } diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index ce9f80a84f..12d7dde11b 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -250,7 +250,7 @@ namespace osu.Game.Tests.Visual.Menus { } - public virtual IBindable UnreadCount => null; + public virtual IBindable UnreadCount { get; } = new Bindable(); public IEnumerable AllNotifications => Enumerable.Empty(); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index d99d764449..b938e59d63 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.Multiplayer .SkipWhile(r => r.Room.Category.Value == RoomCategory.Spotlight) .All(r => r.Room.Category.Value == RoomCategory.Normal)); - AddStep("remove first room", () => RoomManager.RemoveRoom(RoomManager.Rooms.FirstOrDefault(r => r.RoomID.Value == 0))); + AddStep("remove first room", () => RoomManager.RemoveRoom(RoomManager.Rooms.First(r => r.RoomID.Value == 0))); AddAssert("has 4 rooms", () => container.Rooms.Count == 4); AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0)); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 1053789b27..9f7b20ad43 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -179,7 +179,7 @@ namespace osu.Game.Tests.Visual.Playlists public IBindable InitialRoomsReceived { get; } = new Bindable(true); - public IBindableList Rooms => null; + public IBindableList Rooms => null!; public void AddOrUpdateRoom(Room room) => throw new NotImplementedException(); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index 2f66309f04..1636a3d4b8 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -52,11 +52,11 @@ namespace osu.Game.Tests.Visual.Playlists [SetUpSteps] public void SetupSteps() { - AddStep("set room", () => SelectedRoom.Value = new Room()); + AddStep("set room", () => SelectedRoom!.Value = new Room()); importBeatmap(); - AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom.Value))); + AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom!.Value))); AddUntilStep("wait for load", () => match.IsCurrentScreen()); } @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.Playlists }); }); - AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom.Value.Playlist[0]); + AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom!.Value.Playlist[0]); } [Test] @@ -201,7 +201,7 @@ namespace osu.Game.Tests.Visual.Playlists private void setupAndCreateRoom(Action room) { - AddStep("setup room", () => room(SelectedRoom.Value)); + AddStep("setup room", () => room(SelectedRoom!.Value)); AddStep("click create button", () => { diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index 5671cbebd7..685a685896 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -432,7 +432,7 @@ namespace osu.Game.Tests.Visual.Ranking private class RulesetWithNoPerformanceCalculator : OsuRuleset { - public override PerformanceCalculator CreatePerformanceCalculator() => null; + public override PerformanceCalculator CreatePerformanceCalculator() => null!; } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs index 9275f9755f..51da4d8755 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs @@ -213,7 +213,7 @@ namespace osu.Game.Tests.Visual.UserInterface { } - public virtual IBindable UnreadCount => null; + public virtual IBindable UnreadCount { get; } = new Bindable(); public IEnumerable AllNotifications => Enumerable.Empty(); } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 1ee4670ae2..386dada328 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -567,10 +567,9 @@ namespace osu.Game.Beatmaps.Formats for (int i = pendingControlPoints.Count - 1; i >= 0; i--) { var type = pendingControlPoints[i].GetType(); - if (pendingControlPointTypes.Contains(type)) + if (!pendingControlPointTypes.Add(type)) continue; - pendingControlPointTypes.Add(type); beatmap.ControlPointInfo.Add(pendingControlPointsTime, pendingControlPoints[i]); } diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index 2c500146c5..74a85cde7c 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -116,7 +116,7 @@ namespace osu.Game.Beatmaps ITrackStore IBeatmapResourceProvider.Tracks => trackStore; IRenderer IStorageResourceProvider.Renderer => host?.Renderer ?? new DummyRenderer(); AudioManager IStorageResourceProvider.AudioManager => audioManager; - RealmAccess IStorageResourceProvider.RealmAccess => null; + RealmAccess IStorageResourceProvider.RealmAccess => null!; IResourceStore IStorageResourceProvider.Files => files; IResourceStore IStorageResourceProvider.Resources => resources; IResourceStore IStorageResourceProvider.CreateTextureLoaderStore(IResourceStore underlyingStore) => host?.CreateTextureLoaderStore(underlyingStore); diff --git a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs index 62544c6111..098fd7b1ab 100644 --- a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs @@ -52,10 +52,10 @@ namespace osu.Game.Graphics.Containers public override void Add(T drawable) { - base.Add(drawable); - Debug.Assert(drawable != null); + base.Add(drawable); + drawable.StateChanged += state => selectionChanged(drawable, state); } diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index af4b3849af..4af6ce7498 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface @@ -48,6 +49,7 @@ namespace osu.Game.Graphics.UserInterface { protected virtual float ChevronSize => 10; + [CanBeNull] public event Action StateChanged; public readonly SpriteIcon Chevron; diff --git a/osu.Game/IO/IStorageResourceProvider.cs b/osu.Game/IO/IStorageResourceProvider.cs index 08982a8b5f..91760971e8 100644 --- a/osu.Game/IO/IStorageResourceProvider.cs +++ b/osu.Game/IO/IStorageResourceProvider.cs @@ -41,6 +41,6 @@ namespace osu.Game.IO /// /// The underlying provider of texture data (in arbitrary image formats). /// A texture loader store. - IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore); + IResourceStore? CreateTextureLoaderStore(IResourceStore underlyingStore); } } diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 7911701853..07ee9115d6 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -264,13 +264,12 @@ namespace osu.Game.Online.Spectator { Debug.Assert(ThreadSafety.IsUpdateThread); - if (watchedUsersRefCounts.ContainsKey(userId)) + if (!watchedUsersRefCounts.TryAdd(userId, 1)) { watchedUsersRefCounts[userId]++; return; } - watchedUsersRefCounts.Add(userId, 1); WatchUserInternal(userId); } diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index dd418a9e58..8c5aaa062f 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Comments public Color4 AccentColour { get; set; } - protected override IEnumerable EffectTargets => null; + protected override IEnumerable EffectTargets => Enumerable.Empty(); [Resolved] private IAPIProvider api { get; set; } diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index a25147b69f..f4f6fd2bc1 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using JetBrains.Annotations; using osu.Framework; using osuTK; using osu.Framework.Allocation; @@ -24,6 +25,7 @@ namespace osu.Game.Overlays.MedalSplash private const float scale_when_unlocked = 0.76f; private const float scale_when_full = 0.6f; + [CanBeNull] public event Action StateChanged; private readonly Medal medal; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 9ca4c25ab9..6ec4971f06 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -5,6 +5,7 @@ using System; using System.Globalization; +using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -48,6 +49,7 @@ namespace osu.Game.Overlays.Volume private Sample notchSample; private double sampleLastPlaybackTime; + [CanBeNull] public event Action StateChanged; private SelectionState state; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 5662fb2293..161537200a 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -11,6 +11,7 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; @@ -139,7 +140,7 @@ namespace osu.Game.Rulesets.Objects.Drawables protected override bool RequiresChildrenUpdate => true; - public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart); + public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock.IsNotNull() && Clock.CurrentTime >= LifetimeStart); private readonly Bindable state = new Bindable(); diff --git a/osu.Game/Rulesets/Objects/Pooling/HitObjectEntryManager.cs b/osu.Game/Rulesets/Objects/Pooling/HitObjectEntryManager.cs index fabf4fc444..7977166cb2 100644 --- a/osu.Game/Rulesets/Objects/Pooling/HitObjectEntryManager.cs +++ b/osu.Game/Rulesets/Objects/Pooling/HitObjectEntryManager.cs @@ -47,12 +47,9 @@ namespace osu.Game.Rulesets.Objects.Pooling { HitObject hitObject = entry.HitObject; - if (entryMap.ContainsKey(hitObject)) + if (!entryMap.TryAdd(hitObject, entry)) throw new InvalidOperationException($@"The {nameof(HitObjectLifetimeEntry)} is already added to this {nameof(HitObjectEntryManager)}."); - // Add the entry. - entryMap[hitObject] = entry; - // If the entry has a parent, set it and add the entry to the parent's children. if (parent != null) { diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index 4d1f81228e..b83e565e89 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -69,6 +70,7 @@ namespace osu.Game.Screens.Edit.Compose.Components public override void Show() => State = Visibility.Visible; + [CanBeNull] public event Action StateChanged; public partial class BoxWithBorders : CompositeDrawable diff --git a/osu.Game/Screens/Menu/ButtonArea.cs b/osu.Game/Screens/Menu/ButtonArea.cs index 69ba68442f..4eb91c526f 100644 --- a/osu.Game/Screens/Menu/ButtonArea.cs +++ b/osu.Game/Screens/Menu/ButtonArea.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using JetBrains.Annotations; using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -88,6 +89,7 @@ namespace osu.Game.Screens.Menu public override void Show() => State = Visibility.Visible; + [CanBeNull] public event Action StateChanged; private partial class ButtonAreaBackground : Box, IStateful @@ -146,6 +148,7 @@ namespace osu.Game.Screens.Menu } } + [CanBeNull] public event Action StateChanged; } diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index e892f9280f..cb27d1ee61 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Development; @@ -19,6 +20,7 @@ namespace osu.Game.Screens.OnlinePlay.Components { public partial class RoomManager : Component, IRoomManager { + [CanBeNull] public event Action RoomsUpdated; private readonly BindableList rooms = new BindableList(); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index f35b205bc4..4c0219eff5 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -509,7 +509,7 @@ namespace osu.Game.Screens.OnlinePlay.Match private void cancelTrackLooping() { - var track = Beatmap?.Value?.Track; + var track = Beatmap.Value?.Track; if (track != null) track.Looping = false; diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 1cf3d25dad..a260156595 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Play.HUD protected override bool OnMouseMove(MouseMoveEvent e) { - positionalAdjust = Vector2.Distance(e.MousePosition, button.ToSpaceOfOtherDrawable(button.DrawRectangle.Centre, Parent)) / 100; + positionalAdjust = Vector2.Distance(e.MousePosition, button.ToSpaceOfOtherDrawable(button.DrawRectangle.Centre, Parent!)) / 100; return base.OnMouseMove(e); } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 93c6e72aa2..54c5b578e6 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public TestMultiplayerClient MultiplayerClient => OnlinePlayDependencies.MultiplayerClient; public new TestMultiplayerRoomManager RoomManager => OnlinePlayDependencies.RoomManager; - public TestSpectatorClient SpectatorClient => OnlinePlayDependencies?.SpectatorClient; + public TestSpectatorClient SpectatorClient => OnlinePlayDependencies.SpectatorClient; protected new MultiplayerTestSceneDependencies OnlinePlayDependencies => (MultiplayerTestSceneDependencies)base.OnlinePlayDependencies; @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("join room", () => { - SelectedRoom.Value = CreateRoom(); + SelectedRoom!.Value = CreateRoom(); RoomManager.CreateRoom(SelectedRoom.Value); }); diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs index 3509519113..eb5184353a 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs @@ -16,31 +16,31 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// The cached . /// - Bindable SelectedRoom { get; } + Bindable? SelectedRoom { get; } /// /// The cached /// - IRoomManager RoomManager { get; } + IRoomManager? RoomManager { get; } /// /// The cached . /// - OngoingOperationTracker OngoingOperationTracker { get; } + OngoingOperationTracker? OngoingOperationTracker { get; } /// /// The cached . /// - OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; } + OnlinePlayBeatmapAvailabilityTracker? AvailabilityTracker { get; } /// /// The cached . /// - TestUserLookupCache UserLookupCache { get; } + TestUserLookupCache? UserLookupCache { get; } /// /// The cached . /// - BeatmapLookupCache BeatmapLookupCache { get; } + BeatmapLookupCache? BeatmapLookupCache { get; } } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 87488710a7..0118d60dca 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -22,23 +20,23 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// public abstract partial class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies { - public Bindable SelectedRoom => OnlinePlayDependencies?.SelectedRoom; - public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager; - public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies?.OngoingOperationTracker; - public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies?.AvailabilityTracker; - public TestUserLookupCache UserLookupCache => OnlinePlayDependencies?.UserLookupCache; - public BeatmapLookupCache BeatmapLookupCache => OnlinePlayDependencies?.BeatmapLookupCache; + public Bindable SelectedRoom => OnlinePlayDependencies.SelectedRoom; + public IRoomManager RoomManager => OnlinePlayDependencies.RoomManager; + public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies.OngoingOperationTracker; + public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies.AvailabilityTracker; + public TestUserLookupCache UserLookupCache => OnlinePlayDependencies.UserLookupCache; + public BeatmapLookupCache BeatmapLookupCache => OnlinePlayDependencies.BeatmapLookupCache; /// /// All dependencies required for online play components and screens. /// - protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies; + protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies.OnlinePlayDependencies; protected override Container Content => content; private readonly Container content; private readonly Container drawableDependenciesContainer; - private DelegatedDependencyContainer dependencies; + private DelegatedDependencyContainer dependencies = null!; protected OnlinePlayTestScene() { @@ -51,8 +49,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay protected sealed override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent)); - return dependencies; + return dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent)) + { + OnlinePlayDependencies = initDependencies() + }; } public override void SetUpSteps() @@ -62,9 +62,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay AddStep("setup dependencies", () => { // Reset the room dependencies to a fresh state. - drawableDependenciesContainer.Clear(); - dependencies.OnlinePlayDependencies = CreateOnlinePlayDependencies(); - drawableDependenciesContainer.AddRange(OnlinePlayDependencies.DrawableComponents); + dependencies.OnlinePlayDependencies = initDependencies(); var handler = OnlinePlayDependencies.RequestsHandler; @@ -90,6 +88,14 @@ namespace osu.Game.Tests.Visual.OnlinePlay }); } + private OnlinePlayTestSceneDependencies initDependencies() + { + var newDependencies = CreateOnlinePlayDependencies(); + drawableDependenciesContainer.Clear(); + drawableDependenciesContainer.AddRange(newDependencies.DrawableComponents); + return newDependencies; + } + /// /// Creates the room dependencies. Called every . /// @@ -106,7 +112,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// The online play dependencies. /// - public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; } + public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; } = null!; private readonly IReadOnlyDependencyContainer parent; private readonly DependencyContainer injectableDependencies; @@ -122,10 +128,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay } public object Get(Type type) - => OnlinePlayDependencies?.Get(type) ?? parent.Get(type); + => OnlinePlayDependencies.Get(type) ?? parent.Get(type); public object Get(Type type, CacheInfo info) - => OnlinePlayDependencies?.Get(type, info) ?? parent.Get(type, info); + => OnlinePlayDependencies.Get(type, info) ?? parent.Get(type, info); public void Inject(T instance) where T : class, IDependencyInjectionCandidate diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index 975423d19b..64bd27b871 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -56,10 +56,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay CacheAs(BeatmapLookupCache); } - public object Get(Type type) + public object? Get(Type type) => dependencies.Get(type); - public object Get(Type type, CacheInfo info) + public object? Get(Type type, CacheInfo info) => dependencies.Get(type, info); public void Inject(T instance) diff --git a/osu.Game/Tests/Visual/SkinnableTestScene.cs b/osu.Game/Tests/Visual/SkinnableTestScene.cs index f371cf721f..c9acfa0ee5 100644 --- a/osu.Game/Tests/Visual/SkinnableTestScene.cs +++ b/osu.Game/Tests/Visual/SkinnableTestScene.cs @@ -171,10 +171,10 @@ namespace osu.Game.Tests.Visual public IRenderer Renderer => host.Renderer; public AudioManager AudioManager => Audio; - public IResourceStore Files => null; + public IResourceStore Files => null!; public new IResourceStore Resources => base.Resources; public IResourceStore CreateTextureLoaderStore(IResourceStore underlyingStore) => host.CreateTextureLoaderStore(underlyingStore); - RealmAccess IStorageResourceProvider.RealmAccess => null; + RealmAccess IStorageResourceProvider.RealmAccess => null!; #endregion diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index c8c5d6745c..1bf8aa7b0b 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -66,6 +66,7 @@ HINT WARNING DO_NOT_SHOW + HINT WARNING WARNING WARNING @@ -81,6 +82,7 @@ WARNING WARNING HINT + HINT WARNING HINT DO_NOT_SHOW @@ -165,6 +167,7 @@ WARNING WARNING WARNING + HINT WARNING WARNING WARNING @@ -251,6 +254,7 @@ HINT DO_NOT_SHOW WARNING + HINT WARNING WARNING WARNING @@ -263,6 +267,7 @@ WARNING WARNING WARNING + HINT WARNING HINT HINT From 20ae88b0a0dd9a23dfbb7982d292e475f3a959c7 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 21:05:12 +0900 Subject: [PATCH 236/915] Revert unnecessary changes --- .../Tests/Visual/Multiplayer/MultiplayerTestScene.cs | 2 +- .../OnlinePlay/IOnlinePlayTestSceneDependencies.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 54c5b578e6..80c69db8b1 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("join room", () => { - SelectedRoom!.Value = CreateRoom(); + SelectedRoom.Value = CreateRoom(); RoomManager.CreateRoom(SelectedRoom.Value); }); diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs index eb5184353a..3509519113 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs @@ -16,31 +16,31 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// The cached . /// - Bindable? SelectedRoom { get; } + Bindable SelectedRoom { get; } /// /// The cached /// - IRoomManager? RoomManager { get; } + IRoomManager RoomManager { get; } /// /// The cached . /// - OngoingOperationTracker? OngoingOperationTracker { get; } + OngoingOperationTracker OngoingOperationTracker { get; } /// /// The cached . /// - OnlinePlayBeatmapAvailabilityTracker? AvailabilityTracker { get; } + OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; } /// /// The cached . /// - TestUserLookupCache? UserLookupCache { get; } + TestUserLookupCache UserLookupCache { get; } /// /// The cached . /// - BeatmapLookupCache? BeatmapLookupCache { get; } + BeatmapLookupCache BeatmapLookupCache { get; } } } From 6e4d52863c81e28a6b4389e844081d016a4cdee7 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 00:50:26 +0900 Subject: [PATCH 237/915] Upgrade to .NET 8 SDK --- .../osu.Game.Rulesets.EmptyFreeform.Tests.csproj | 2 +- .../osu.Game.Rulesets.EmptyFreeform.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.csproj | 2 +- .../osu.Game.Rulesets.EmptyScrolling.Tests.csproj | 2 +- .../osu.Game.Rulesets.EmptyScrolling.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.csproj | 2 +- global.json | 8 ++++---- osu.Android/osu.Android.csproj | 2 +- osu.Desktop/osu.Desktop.csproj | 2 +- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.Android.csproj | 4 ++-- .../osu.Game.Rulesets.Catch.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.Android.csproj | 4 ++-- .../osu.Game.Rulesets.Mania.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.Android.csproj | 4 ++-- .../osu.Game.Rulesets.Osu.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.csproj | 2 +- osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.Android.csproj | 4 ++-- .../osu.Game.Rulesets.Taiko.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 2 +- osu.Game.Tests.Android/osu.Game.Tests.Android.csproj | 2 +- osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- .../osu.Game.Tournament.Tests.csproj | 2 +- osu.Game.Tournament/osu.Game.Tournament.csproj | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS/osu.iOS.csproj | 2 +- 35 files changed, 42 insertions(+), 42 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index 5babdb47ff..7d43eb2b05 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -18,7 +18,7 @@ WinExe - net6.0 + net8.0 osu.Game.Rulesets.EmptyFreeform.Tests diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj index d09e7647e0..89abd5665c 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/osu.Game.Rulesets.EmptyFreeform.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 osu.Game.Rulesets.EmptyFreeform Library AnyCPU diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 5d64ca832a..7dc8a1336b 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -18,7 +18,7 @@ WinExe - net6.0 + net8.0 osu.Game.Rulesets.Pippidon.Tests diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj index 9c8867f4ef..165b6b6c6b 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 osu.Game.Rulesets.Pippidon Library AnyCPU diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index 6796a8962b..9c4c8217f0 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -18,7 +18,7 @@ WinExe - net6.0 + net8.0 osu.Game.Rulesets.EmptyScrolling.Tests diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj index 5bf3884f53..6d9565a6f2 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/osu.Game.Rulesets.EmptyScrolling.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 osu.Game.Rulesets.EmptyScrolling Library AnyCPU diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 5d64ca832a..7dc8a1336b 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -18,7 +18,7 @@ WinExe - net6.0 + net8.0 osu.Game.Rulesets.Pippidon.Tests diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj index 9c8867f4ef..165b6b6c6b 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/osu.Game.Rulesets.Pippidon.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 osu.Game.Rulesets.Pippidon Library AnyCPU diff --git a/global.json b/global.json index 5dcd5f425a..da113e4cbd 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "6.0.100", - "rollForward": "latestFeature" + "version": "8.0.0", + "rollForward": "latestFeature", + "allowPrerelease": false } -} - +} \ No newline at end of file diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 1507bfaa29..17e049a569 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -1,7 +1,7 @@  - net6.0-android + net8.0-android Exe osu.Android osu.Android diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index d6a11fa924..cf2ec6e681 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 WinExe true A free-to-win rhythm game. Rhythm is just a *click* away! diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 47c93fbd02..64da5412a8 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 Exe false diff --git a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj index 4ee3219442..4b2e54be67 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj +++ b/osu.Game.Rulesets.Catch.Tests.Android/osu.Game.Rulesets.Catch.Tests.Android.csproj @@ -1,7 +1,7 @@  - net6.0-android + net8.0-android Exe osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.Android @@ -21,4 +21,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj index acf12bb0ac..9c262a752a 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj @@ -1,7 +1,7 @@  Exe - net6.0-ios + net8.0-ios 13.4 osu.Game.Rulesets.Catch.Tests osu.Game.Rulesets.Catch.Tests.iOS diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 0a77845343..619081c754 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -7,7 +7,7 @@ WinExe - net6.0 + net8.0 diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index ecce7c1b3f..a5138ffb39 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 Library true catch the fruit. to the beat. diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj index 25335754d2..2866508a02 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj +++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj @@ -1,7 +1,7 @@  - net6.0-android + net8.0-android Exe osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.Android @@ -21,4 +21,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj index 51e07dd6c1..d51e541e95 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj @@ -1,7 +1,7 @@  Exe - net6.0-ios + net8.0-ios 13.4 osu.Game.Rulesets.Mania.Tests osu.Game.Rulesets.Mania.Tests.iOS diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 877b9c3ea4..eee06acdb8 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -7,7 +7,7 @@ WinExe - net6.0 + net8.0 diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 72f172188e..3bca938450 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 Library true smash the keys. to the beat. diff --git a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj index e8a46a9828..b79de6d40b 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj +++ b/osu.Game.Rulesets.Osu.Tests.Android/osu.Game.Rulesets.Osu.Tests.Android.csproj @@ -1,7 +1,7 @@  - net6.0-android + net8.0-android Exe osu.Game.Rulesets.Osu.Tests osu.Game.Rulesets.Osu.Tests.Android @@ -24,4 +24,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj index 7d50deb8ba..cc0233d7fd 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -1,7 +1,7 @@  Exe - net6.0-ios + net8.0-ios 13.4 Exe osu.Game.Rulesets.Osu.Tests diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 9c248abd66..ea54c8d313 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -8,7 +8,7 @@ WinExe - net6.0 + net8.0 diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 75656e2976..518ab362ca 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 Library true click the circles. to the beat. diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj index a639326ebd..ee973e8544 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.Android/osu.Game.Rulesets.Taiko.Tests.Android.csproj @@ -1,7 +1,7 @@  - net6.0-android + net8.0-android Exe osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.Android @@ -21,4 +21,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj index e648a11299..ee2d4d703e 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj @@ -1,7 +1,7 @@  Exe - net6.0-ios + net8.0-ios 13.4 osu.Game.Rulesets.Taiko.Tests osu.Game.Rulesets.Taiko.Tests.iOS diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 4eb6b0ab3d..26afd42445 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -7,7 +7,7 @@ WinExe - net6.0 + net8.0 diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index f0e1cb8e8f..cacba55c2a 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 Library true bash the drum. to the beat. diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index b745d91980..889f0a3583 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -1,7 +1,7 @@  - net6.0-android + net8.0-android Exe osu.Game.Tests osu.Game.Tests.Android diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj index 79771fcd50..e4b9d2ba94 100644 --- a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj +++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj @@ -1,7 +1,7 @@  Exe - net6.0-ios + net8.0-ios 13.4 osu.Game.Tests osu.Game.Tests.iOS diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 7b08524240..c0bbdfb4ed 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -10,7 +10,7 @@ WinExe - net6.0 + net8.0 tests.ruleset diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 3b00f103c4..8f1d7114b1 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -10,7 +10,7 @@ WinExe - net6.0 + net8.0 diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index ab67e490cd..c8578ac464 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 Library true tools for tournaments. diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a5d212bffe..caffebd063 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,6 +1,6 @@  - net6.0 + net8.0 Library true 10 diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 2d61b73125..6e9449de95 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -1,6 +1,6 @@  - net6.0-ios + net8.0-ios 13.4 Exe true From f06642c315eb7b35298fd4f1f8e3ff9e9d075766 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 00:51:43 +0900 Subject: [PATCH 238/915] Upgrade to C# 12 --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index b08283f071..2d289d0f22 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@  - 10.0 + 12.0 true enable From c8b4ff2b47d53f0a1397f05f481f3d47d70aca0e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 00:51:55 +0900 Subject: [PATCH 239/915] Fix compile error (reserved name) --- osu.Game/IO/HardLinkHelper.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/IO/HardLinkHelper.cs b/osu.Game/IO/HardLinkHelper.cs index 619bfdad6e..ad57f87d10 100644 --- a/osu.Game/IO/HardLinkHelper.cs +++ b/osu.Game/IO/HardLinkHelper.cs @@ -153,12 +153,12 @@ namespace osu.Game.IO public static extern int link(string oldpath, string newpath); [DllImport("libc", SetLastError = true)] - private static extern int stat(string pathname, out struct_stat statbuf); + private static extern int stat(string pathname, out Stat statbuf); // ReSharper disable once InconsistentNaming // Struct layout is likely non-portable across unices. Tread with caution. [StructLayout(LayoutKind.Sequential)] - private struct struct_stat + private struct Stat { public readonly long st_dev; public readonly long st_ino; @@ -170,14 +170,14 @@ namespace osu.Game.IO public readonly long st_size; public readonly long st_blksize; public readonly long st_blocks; - public readonly timespec st_atim; - public readonly timespec st_mtim; - public readonly timespec st_ctim; + public readonly Timespec st_atim; + public readonly Timespec st_mtim; + public readonly Timespec st_ctim; } // ReSharper disable once InconsistentNaming [StructLayout(LayoutKind.Sequential)] - private struct timespec + private struct Timespec { public readonly long tv_sec; public readonly long tv_nsec; From 630278f6e727ce1b7d3cc727e60087db4fd61316 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 01:08:15 +0900 Subject: [PATCH 240/915] Replace UseMauiEssentials with PackageReference --- osu.Android/osu.Android.csproj | 4 +++- osu.iOS/osu.iOS.csproj | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 17e049a569..0e79e0ab3e 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -5,7 +5,6 @@ Exe osu.Android osu.Android - true false 0.0.0 @@ -19,4 +18,7 @@ + + + diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 6e9449de95..19c0c610b5 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -3,7 +3,6 @@ net8.0-ios 13.4 Exe - true 0.1.0 $(Version) $(Version) @@ -16,4 +15,7 @@ + + + From a217a7f8cf74de72a416cda75deb18fdcb6d0712 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 01:11:58 +0900 Subject: [PATCH 241/915] Adjust CI workflows --- .github/workflows/ci.yml | 23 +++++++------------ .../workflows/update-web-mod-definitions.yml | 4 ++-- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 103e4dbc30..722e8910d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,17 +15,10 @@ jobs: - name: Checkout uses: actions/checkout@v3 - # FIXME: Tools won't run in .NET 6.0 unless you install 3.1.x LTS side by side. - # https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e - - name: Install .NET 3.1.x LTS + - name: Install .NET 8.0.x uses: actions/setup-dotnet@v3 with: - dotnet-version: "3.1.x" - - - name: Install .NET 6.0.x - uses: actions/setup-dotnet@v3 - with: - dotnet-version: "6.0.x" + dotnet-version: "8.0.x" - name: Restore Tools run: dotnet tool restore @@ -79,10 +72,10 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Install .NET 6.0.x + - name: Install .NET 8.0.x uses: actions/setup-dotnet@v3 with: - dotnet-version: "6.0.x" + dotnet-version: "8.0.x" - name: Compile run: dotnet build -c Debug -warnaserror osu.Desktop.slnf @@ -114,10 +107,10 @@ jobs: distribution: microsoft java-version: 11 - - name: Install .NET 6.0.x + - name: Install .NET 8.0.x uses: actions/setup-dotnet@v3 with: - dotnet-version: "6.0.x" + dotnet-version: "8.0.x" - name: Install .NET workloads run: dotnet workload install maui-android @@ -135,10 +128,10 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Install .NET 6.0.x + - name: Install .NET 8.0.x uses: actions/setup-dotnet@v3 with: - dotnet-version: "6.0.x" + dotnet-version: "8.0.x" - name: Install .NET Workloads run: dotnet workload install maui-ios diff --git a/.github/workflows/update-web-mod-definitions.yml b/.github/workflows/update-web-mod-definitions.yml index 32d3d37ffe..5827a6cdbf 100644 --- a/.github/workflows/update-web-mod-definitions.yml +++ b/.github/workflows/update-web-mod-definitions.yml @@ -12,10 +12,10 @@ jobs: name: Update osu-web mod definitions runs-on: ubuntu-latest steps: - - name: Install .NET 6.0.x + - name: Install .NET 8.0.x uses: actions/setup-dotnet@v3 with: - dotnet-version: "6.0.x" + dotnet-version: "8.0.x" - name: Checkout ppy/osu uses: actions/checkout@v3 From dda691b8c219f104a938d5a8c0bc29a88acfc19e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 01:14:55 +0900 Subject: [PATCH 242/915] Fix NVAPI compile error --- osu.Desktop/NVAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/NVAPI.cs b/osu.Desktop/NVAPI.cs index bb3a59cc7f..a34b762738 100644 --- a/osu.Desktop/NVAPI.cs +++ b/osu.Desktop/NVAPI.cs @@ -456,7 +456,7 @@ namespace osu.Desktop [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.UNICODE_STRING_MAX)] public string ProfileName; - [MarshalAs(UnmanagedType.ByValArray)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public uint[] GPUSupport; public uint IsPredefined; From 38ed426f8fa90c2bfcd816317349767f1502082d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 02:03:37 +0900 Subject: [PATCH 243/915] Fix more compiler warnings/errors --- .../ruleset-empty/Directory.Build.props | 10 ++++ Templates/Rulesets/ruleset-empty/app.manifest | 46 +++++++++++++++++++ .../ruleset-example/Directory.Build.props | 10 ++++ .../Rulesets/ruleset-example/app.manifest | 46 +++++++++++++++++++ .../Directory.Build.props | 10 ++++ .../ruleset-scrolling-empty/app.manifest | 46 +++++++++++++++++++ .../Directory.Build.props | 10 ++++ .../ruleset-scrolling-example/app.manifest | 46 +++++++++++++++++++ 8 files changed, 224 insertions(+) create mode 100644 Templates/Rulesets/ruleset-empty/Directory.Build.props create mode 100644 Templates/Rulesets/ruleset-empty/app.manifest create mode 100644 Templates/Rulesets/ruleset-example/Directory.Build.props create mode 100644 Templates/Rulesets/ruleset-example/app.manifest create mode 100644 Templates/Rulesets/ruleset-scrolling-empty/Directory.Build.props create mode 100644 Templates/Rulesets/ruleset-scrolling-empty/app.manifest create mode 100644 Templates/Rulesets/ruleset-scrolling-example/Directory.Build.props create mode 100644 Templates/Rulesets/ruleset-scrolling-example/app.manifest diff --git a/Templates/Rulesets/ruleset-empty/Directory.Build.props b/Templates/Rulesets/ruleset-empty/Directory.Build.props new file mode 100644 index 0000000000..74d05ff690 --- /dev/null +++ b/Templates/Rulesets/ruleset-empty/Directory.Build.props @@ -0,0 +1,10 @@ + + + + $(MSBuildThisFileDirectory)app.manifest + + + true + $(NoWarn);CS1591 + + diff --git a/Templates/Rulesets/ruleset-empty/app.manifest b/Templates/Rulesets/ruleset-empty/app.manifest new file mode 100644 index 0000000000..1c1e5f540c --- /dev/null +++ b/Templates/Rulesets/ruleset-empty/app.manifest @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + diff --git a/Templates/Rulesets/ruleset-example/Directory.Build.props b/Templates/Rulesets/ruleset-example/Directory.Build.props new file mode 100644 index 0000000000..74d05ff690 --- /dev/null +++ b/Templates/Rulesets/ruleset-example/Directory.Build.props @@ -0,0 +1,10 @@ + + + + $(MSBuildThisFileDirectory)app.manifest + + + true + $(NoWarn);CS1591 + + diff --git a/Templates/Rulesets/ruleset-example/app.manifest b/Templates/Rulesets/ruleset-example/app.manifest new file mode 100644 index 0000000000..1c1e5f540c --- /dev/null +++ b/Templates/Rulesets/ruleset-example/app.manifest @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/Directory.Build.props b/Templates/Rulesets/ruleset-scrolling-empty/Directory.Build.props new file mode 100644 index 0000000000..74d05ff690 --- /dev/null +++ b/Templates/Rulesets/ruleset-scrolling-empty/Directory.Build.props @@ -0,0 +1,10 @@ + + + + $(MSBuildThisFileDirectory)app.manifest + + + true + $(NoWarn);CS1591 + + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/app.manifest b/Templates/Rulesets/ruleset-scrolling-empty/app.manifest new file mode 100644 index 0000000000..1c1e5f540c --- /dev/null +++ b/Templates/Rulesets/ruleset-scrolling-empty/app.manifest @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + diff --git a/Templates/Rulesets/ruleset-scrolling-example/Directory.Build.props b/Templates/Rulesets/ruleset-scrolling-example/Directory.Build.props new file mode 100644 index 0000000000..74d05ff690 --- /dev/null +++ b/Templates/Rulesets/ruleset-scrolling-example/Directory.Build.props @@ -0,0 +1,10 @@ + + + + $(MSBuildThisFileDirectory)app.manifest + + + true + $(NoWarn);CS1591 + + diff --git a/Templates/Rulesets/ruleset-scrolling-example/app.manifest b/Templates/Rulesets/ruleset-scrolling-example/app.manifest new file mode 100644 index 0000000000..1c1e5f540c --- /dev/null +++ b/Templates/Rulesets/ruleset-scrolling-example/app.manifest @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + From ec4f3577c0659709a26383af1c3818593aef1ebc Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 02:09:00 +0900 Subject: [PATCH 244/915] Use Xcode 15.2 --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 722e8910d5..de902df93f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -136,5 +136,8 @@ jobs: - name: Install .NET Workloads run: dotnet workload install maui-ios + - name: Select Xcode 15.2 + run: sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer + - name: Build run: dotnet build -c Debug osu.iOS From 19ea4842400f45cb78cf55b00cee69669c5b1369 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 02:18:22 +0900 Subject: [PATCH 245/915] Adjust pragma disable to fix Android compile --- osu.Android/OsuGameActivity.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index 33ffed432e..bbee491d90 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -72,9 +72,9 @@ namespace osu.Android Debug.Assert(Resources?.DisplayMetrics != null); Point displaySize = new Point(); -#pragma warning disable 618 // GetSize is deprecated +#pragma warning disable CA1422 // GetSize is deprecated WindowManager.DefaultDisplay.GetSize(displaySize); -#pragma warning restore 618 +#pragma warning restore CA1422 float smallestWidthDp = Math.Min(displaySize.X, displaySize.Y) / Resources.DisplayMetrics.Density; bool isTablet = smallestWidthDp >= 600f; From 497213d529f57e1f057f69720d8fe7e3e22c806d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 02:25:52 +0900 Subject: [PATCH 246/915] Re-enable LLVM for now --- osu.Android/osu.Android.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 0e79e0ab3e..be2e669728 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -5,8 +5,6 @@ Exe osu.Android osu.Android - - false 0.0.0 1 $(Version) From 20504c55ef02b83ea9c575d3b435148a4eff8931 Mon Sep 17 00:00:00 2001 From: Loreos7 Date: Fri, 2 Feb 2024 15:32:55 +0300 Subject: [PATCH 247/915] localise storage error popup dialog --- .../Localisation/StorageErrorDialogStrings.cs | 49 +++++++++++++++++++ osu.Game/Screens/Menu/StorageErrorDialog.cs | 17 ++++--- 2 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Localisation/StorageErrorDialogStrings.cs diff --git a/osu.Game/Localisation/StorageErrorDialogStrings.cs b/osu.Game/Localisation/StorageErrorDialogStrings.cs new file mode 100644 index 0000000000..6ad388dd1f --- /dev/null +++ b/osu.Game/Localisation/StorageErrorDialogStrings.cs @@ -0,0 +1,49 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class StorageErrorDialogStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.StorageErrorDialog"; + + /// + /// "osu! storage error" + /// + public static LocalisableString StorageError => new TranslatableString(getKey(@"storage_error"), @"osu! storage error"); + + /// + /// "The specified osu! data location ("{0}") is not accessible. If it is on external storage, please reconnect the device and try again." + /// + public static LocalisableString LocationIsNotAccessible(string? loc) => new TranslatableString(getKey(@"location_is_not_accessible"), @"The specified osu! data location (""{0}"") is not accessible. If it is on external storage, please reconnect the device and try again.", loc); + + /// + /// "The specified osu! data location ("{0}") is empty. If you have moved the files, please close osu! and move them back." + /// + public static LocalisableString LocationIsEmpty(string? loc2) => new TranslatableString(getKey(@"location_is_empty"), @"The specified osu! data location (""{0}"") is empty. If you have moved the files, please close osu! and move them back.", loc2); + + /// + /// "Try again" + /// + public static LocalisableString TryAgain => new TranslatableString(getKey(@"try_again"), @"Try again"); + + /// + /// "Use default location until restart" + /// + public static LocalisableString UseDefaultLocation => new TranslatableString(getKey(@"use_default_location"), @"Use default location until restart"); + + /// + /// "Reset to default location" + /// + public static LocalisableString ResetToDefaultLocation => new TranslatableString(getKey(@"reset_to_default_location"), @"Reset to default location"); + + /// + /// "Start fresh at specified location" + /// + public static LocalisableString StartFresh => new TranslatableString(getKey(@"start_fresh"), @"Start fresh at specified location"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Screens/Menu/StorageErrorDialog.cs b/osu.Game/Screens/Menu/StorageErrorDialog.cs index dd43289873..b48046d190 100644 --- a/osu.Game/Screens/Menu/StorageErrorDialog.cs +++ b/osu.Game/Screens/Menu/StorageErrorDialog.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Game.IO; +using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Overlays.Dialog; @@ -17,7 +18,7 @@ namespace osu.Game.Screens.Menu public StorageErrorDialog(OsuStorage storage, OsuStorageError error) { - HeaderText = "osu! storage error"; + HeaderText = StorageErrorDialogStrings.StorageError; Icon = FontAwesome.Solid.ExclamationTriangle; var buttons = new List(); @@ -25,13 +26,13 @@ namespace osu.Game.Screens.Menu switch (error) { case OsuStorageError.NotAccessible: - BodyText = $"The specified osu! data location (\"{storage.CustomStoragePath}\") is not accessible. If it is on external storage, please reconnect the device and try again."; + BodyText = StorageErrorDialogStrings.LocationIsNotAccessible(storage.CustomStoragePath); buttons.AddRange(new PopupDialogButton[] { new PopupDialogCancelButton { - Text = "Try again", + Text = StorageErrorDialogStrings.TryAgain, Action = () => { if (!storage.TryChangeToCustomStorage(out var nextError)) @@ -40,29 +41,29 @@ namespace osu.Game.Screens.Menu }, new PopupDialogCancelButton { - Text = "Use default location until restart", + Text = StorageErrorDialogStrings.UseDefaultLocation, }, new PopupDialogOkButton { - Text = "Reset to default location", + Text = StorageErrorDialogStrings.ResetToDefaultLocation, Action = storage.ResetCustomStoragePath }, }); break; case OsuStorageError.AccessibleButEmpty: - BodyText = $"The specified osu! data location (\"{storage.CustomStoragePath}\") is empty. If you have moved the files, please close osu! and move them back."; + BodyText = StorageErrorDialogStrings.LocationIsEmpty(storage.CustomStoragePath); // Todo: Provide the option to search for the files similar to migration. buttons.AddRange(new PopupDialogButton[] { new PopupDialogCancelButton { - Text = "Start fresh at specified location" + Text = StorageErrorDialogStrings.StartFresh }, new PopupDialogOkButton { - Text = "Reset to default location", + Text = StorageErrorDialogStrings.ResetToDefaultLocation, Action = storage.ResetCustomStoragePath }, }); From 8e8ba9e77f94a33f06a05190b86c76da90b3c3a6 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 21:36:41 +0900 Subject: [PATCH 248/915] Fix more CI inspections --- osu.Desktop/NVAPI.cs | 2 +- osu.Game.Tests/NonVisual/TaskChainTest.cs | 2 +- osu.Game/Online/Chat/WebSocketChatClient.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Desktop/NVAPI.cs b/osu.Desktop/NVAPI.cs index a34b762738..78a814c585 100644 --- a/osu.Desktop/NVAPI.cs +++ b/osu.Desktop/NVAPI.cs @@ -138,7 +138,7 @@ namespace osu.Desktop return false; // Make sure that this is a laptop. - var gpus = new IntPtr[64]; + IntPtr[] gpus = new IntPtr[64]; if (checkError(EnumPhysicalGPUs(gpus, out int gpuCount))) return false; diff --git a/osu.Game.Tests/NonVisual/TaskChainTest.cs b/osu.Game.Tests/NonVisual/TaskChainTest.cs index ad1a3fd63f..2ac89efb69 100644 --- a/osu.Game.Tests/NonVisual/TaskChainTest.cs +++ b/osu.Game.Tests/NonVisual/TaskChainTest.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.NonVisual var task3 = addTask(); // Cancel task2, allow task3 to complete. - task2.cancellation.Cancel(); + await task2.cancellation.CancelAsync(); task2.mutex.Set(); task3.mutex.Set(); diff --git a/osu.Game/Online/Chat/WebSocketChatClient.cs b/osu.Game/Online/Chat/WebSocketChatClient.cs index b74f8bec4b..8e1b501b25 100644 --- a/osu.Game/Online/Chat/WebSocketChatClient.cs +++ b/osu.Game/Online/Chat/WebSocketChatClient.cs @@ -61,7 +61,7 @@ namespace osu.Game.Online.Chat { await client.SendAsync(new StartChatRequest()).ConfigureAwait(false); Logger.Log(@"Now listening to websocket chat messages.", LoggingTarget.Network); - chatStartCancellationSource.Cancel(); + await chatStartCancellationSource.CancelAsync().ConfigureAwait(false); } catch (Exception ex) { From 50f9c6102975a6fac1c2ddba4bdd1f2d203e4862 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Feb 2024 22:34:48 +0900 Subject: [PATCH 249/915] Fix multiplayer tests --- .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 0118d60dca..eebc3503bc 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// All dependencies required for online play components and screens. /// - protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies.OnlinePlayDependencies; + protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies.OnlinePlayDependencies!; protected override Container Content => content; @@ -48,12 +48,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay } protected sealed override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - return dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent)) - { - OnlinePlayDependencies = initDependencies() - }; - } + => dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent)); public override void SetUpSteps() { @@ -62,7 +57,9 @@ namespace osu.Game.Tests.Visual.OnlinePlay AddStep("setup dependencies", () => { // Reset the room dependencies to a fresh state. - dependencies.OnlinePlayDependencies = initDependencies(); + dependencies.OnlinePlayDependencies = CreateOnlinePlayDependencies(); + drawableDependenciesContainer.Clear(); + drawableDependenciesContainer.AddRange(dependencies.OnlinePlayDependencies.DrawableComponents); var handler = OnlinePlayDependencies.RequestsHandler; @@ -88,14 +85,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay }); } - private OnlinePlayTestSceneDependencies initDependencies() - { - var newDependencies = CreateOnlinePlayDependencies(); - drawableDependenciesContainer.Clear(); - drawableDependenciesContainer.AddRange(newDependencies.DrawableComponents); - return newDependencies; - } - /// /// Creates the room dependencies. Called every . /// @@ -112,7 +101,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// The online play dependencies. /// - public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; } = null!; + public OnlinePlayTestSceneDependencies? OnlinePlayDependencies { get; set; } private readonly IReadOnlyDependencyContainer parent; private readonly DependencyContainer injectableDependencies; @@ -128,10 +117,10 @@ namespace osu.Game.Tests.Visual.OnlinePlay } public object Get(Type type) - => OnlinePlayDependencies.Get(type) ?? parent.Get(type); + => OnlinePlayDependencies?.Get(type) ?? parent.Get(type); public object Get(Type type, CacheInfo info) - => OnlinePlayDependencies.Get(type, info) ?? parent.Get(type, info); + => OnlinePlayDependencies?.Get(type, info) ?? parent.Get(type, info); public void Inject(T instance) where T : class, IDependencyInjectionCandidate From 2ab967f783fd25d95e9142bffb79eb78e03e7cbc Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 13:27:26 -0500 Subject: [PATCH 250/915] Increase precision of aggregate volume rounding It should be large enough to account for true accuracy but small enough to disregard any hair-thin inaccuracy found at the very end of the float value. --- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 40ffa844da..aafa93c122 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -551,7 +551,7 @@ namespace osu.Game.Screens.Play if (!muteWarningShownOnce.Value) { // Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - if (volumeOverlay?.IsMuted.Value == true || Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100 <= volume_requirement) + if (volumeOverlay?.IsMuted.Value == true || Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 1e6) / 1e6 <= volume_requirement) { notificationOverlay?.Post(new MutedNotification()); muteWarningShownOnce.Value = true; @@ -582,7 +582,7 @@ namespace osu.Game.Screens.Play // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. // Note that we only restore to -20 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. - if (Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 100) / 100 <= volume_requirement) + if (Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 1e6) / 1e6 <= volume_requirement) { // Prioritize increasing music over master volume as to avoid also increasing effects volume. const double target = 0.1; From 9a5348598af58008e0c22897964f81bf27d34ee0 Mon Sep 17 00:00:00 2001 From: Mike Will Date: Fri, 2 Feb 2024 14:22:24 -0500 Subject: [PATCH 251/915] Replace aggregate rounding method with a float cast --- osu.Game/Screens/Play/PlayerLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index aafa93c122..6154e443ef 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -551,7 +551,7 @@ namespace osu.Game.Screens.Play if (!muteWarningShownOnce.Value) { // Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - if (volumeOverlay?.IsMuted.Value == true || Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 1e6) / 1e6 <= volume_requirement) + if (volumeOverlay?.IsMuted.Value == true || (float)(audioManager.Volume.Value * audioManager.VolumeTrack.Value) <= volume_requirement) { notificationOverlay?.Post(new MutedNotification()); muteWarningShownOnce.Value = true; @@ -582,7 +582,7 @@ namespace osu.Game.Screens.Play // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. // Note that we only restore to -20 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. - if (Math.Floor(audioManager.Volume.Value * audioManager.VolumeTrack.Value * 1e6) / 1e6 <= volume_requirement) + if ((float)(audioManager.Volume.Value * audioManager.VolumeTrack.Value) <= volume_requirement) { // Prioritize increasing music over master volume as to avoid also increasing effects volume. const double target = 0.1; From dde7e068a4ae490ade2c49650996da50c60e939b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 2 Feb 2024 22:28:47 +0300 Subject: [PATCH 252/915] Incorporate new unstable rate algo --- .../Rulesets/Scoring/HitEventExtensions.cs | 39 ++++++++++++------- osu.sln.DotSettings | 1 + 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs index 9fb61c6cd9..c3ad8980fe 100644 --- a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs +++ b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Scoring public static class HitEventExtensions { /// - /// Calculates the "unstable rate" for a sequence of s. + /// Calculates the "unstable rate" for a sequence of s using Welford's online algorithm. /// /// /// A non-null value if unstable rate could be calculated, @@ -21,9 +21,30 @@ namespace osu.Game.Rulesets.Scoring { Debug.Assert(hitEvents.All(ev => ev.GameplayRate != null)); - // Division by gameplay rate is to account for TimeOffset scaling with gameplay rate. - double[] timeOffsets = hitEvents.Where(affectsUnstableRate).Select(ev => ev.TimeOffset / ev.GameplayRate!.Value).ToArray(); - return 10 * standardDeviation(timeOffsets); + double currentValue; + int k = 0; + double m = 0; + double s = 0; + double mNext; + + foreach (var e in hitEvents) + { + if (!affectsUnstableRate(e)) + continue; + + // Division by gameplay rate is to account for TimeOffset scaling with gameplay rate. + currentValue = e.TimeOffset / e.GameplayRate!.Value; + + k++; + mNext = m + (currentValue - m) / k; + s += (currentValue - m) * (currentValue - mNext); + m = mNext; + } + + if (k == 0) + return null; + + return 10.0 * Math.Sqrt(s / k); } /// @@ -44,15 +65,5 @@ namespace osu.Game.Rulesets.Scoring } private static bool affectsUnstableRate(HitEvent e) => !(e.HitObject.HitWindows is HitWindows.EmptyHitWindows) && e.Result.IsHit(); - - private static double? standardDeviation(double[] timeOffsets) - { - if (timeOffsets.Length == 0) - return null; - - 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.sln.DotSettings b/osu.sln.DotSettings index 1bf8aa7b0b..ef557cbbfc 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -1041,4 +1041,5 @@ private void load() True True True + True True From 4d324a30573f9cd6c4dcff2e0c336e26e66a574a Mon Sep 17 00:00:00 2001 From: Loreos7 Date: Sat, 3 Feb 2024 00:08:36 +0300 Subject: [PATCH 253/915] localise remaining parts of the game settings --- .../TaikoSettingsSubsection.cs | 5 +++-- osu.Game/Localisation/AudioSettingsStrings.cs | 15 +++++++++++++++ osu.Game/Localisation/DebugSettingsStrings.cs | 5 +++++ osu.Game/Localisation/GraphicsSettingsStrings.cs | 5 +++++ osu.Game/Localisation/RulesetSettingsStrings.cs | 5 +++++ .../Sections/Audio/AudioOffsetAdjustControl.cs | 6 +++--- .../Sections/DebugSettings/GeneralSettings.cs | 2 +- .../Settings/Sections/Graphics/LayoutSettings.cs | 2 +- 8 files changed, 38 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs b/osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs index 9fe861c08c..84dea474c5 100644 --- a/osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs +++ b/osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs @@ -1,9 +1,10 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// 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.Localisation; +using osu.Game.Localisation; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Taiko.Configuration; @@ -27,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko { new SettingsEnumDropdown { - LabelText = "Touch control scheme", + LabelText = RulesetSettingsStrings.TouchControlScheme, Current = config.GetBindable(TaikoRulesetSetting.TouchControlScheme) } }; diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs index 0f0f560df9..d93de59cd2 100644 --- a/osu.Game/Localisation/AudioSettingsStrings.cs +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -64,6 +64,21 @@ namespace osu.Game.Localisation /// public static LocalisableString AudioOffset => new TranslatableString(getKey(@"audio_offset"), @"Audio offset"); + /// + /// "Play a few beatmaps to receive a suggested offset!" + /// + public static LocalisableString SuggestedOffsetNote => new TranslatableString(getKey(@"suggested_offset_note"), @"Play a few beatmaps to receive a suggested offset!"); + + /// + /// "Based on the last {0} play(s), the suggested offset is {1} ms" + /// + public static LocalisableString SuggestedOffsetValueReceived(int plays, double? value) => new TranslatableString(getKey(@"suggested_offset_value_received"), @"Based on the last {0} play(s), the suggested offset is {1} ms", plays, value); + + /// + /// "Apply suggested offset" + /// + public static LocalisableString ApplySuggestedOffset => new TranslatableString(getKey(@"apply_suggested_offset"), @"Apply suggested offset"); + /// /// "Offset wizard" /// diff --git a/osu.Game/Localisation/DebugSettingsStrings.cs b/osu.Game/Localisation/DebugSettingsStrings.cs index 18fd3e83da..066c07858c 100644 --- a/osu.Game/Localisation/DebugSettingsStrings.cs +++ b/osu.Game/Localisation/DebugSettingsStrings.cs @@ -29,6 +29,11 @@ namespace osu.Game.Localisation /// public static LocalisableString ImportFiles => new TranslatableString(getKey(@"import_files"), @"Import files"); + /// + /// "Run latency certifier" + /// + public static LocalisableString RunLatencyCertifier => new TranslatableString(getKey(@"run_latency_certifier"), @"Run latency certifier"); + /// /// "Memory" /// diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index 1d14b0a596..d3952d0b4c 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -159,6 +159,11 @@ namespace osu.Game.Localisation /// public static LocalisableString MinimiseOnFocusLoss => new TranslatableString(getKey(@"minimise_on_focus_loss"), @"Minimise osu! when switching to another app"); + /// + /// "Shrink game to avoid cameras and notches" + /// + public static LocalisableString ShrinkGameOnMobile => new TranslatableString(getKey(@"shrink_game_on_mobile"), @"Shrink game to avoid cameras and notches"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Localisation/RulesetSettingsStrings.cs b/osu.Game/Localisation/RulesetSettingsStrings.cs index 3fa7656cbb..e3d51f1124 100644 --- a/osu.Game/Localisation/RulesetSettingsStrings.cs +++ b/osu.Game/Localisation/RulesetSettingsStrings.cs @@ -84,6 +84,11 @@ namespace osu.Game.Localisation /// public static LocalisableString ScrollSpeedTooltip(int scrollTime, int scrollSpeed) => new TranslatableString(getKey(@"ruleset"), @"{0}ms (speed {1})", scrollTime, scrollSpeed); + /// + /// "Touch control scheme" + /// + public static LocalisableString TouchControlScheme => new TranslatableString(getKey(@"touch_control_scheme"), @"Touch control scheme"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs index ef1691534f..71c357c065 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs @@ -91,7 +91,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio applySuggestion = new RoundedButton { RelativeSizeAxes = Axes.X, - Text = "Apply suggested offset", + Text = AudioSettingsStrings.ApplySuggestedOffset, Action = () => { if (SuggestedOffset.Value.HasValue) @@ -155,8 +155,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio private void updateHintText() { hintText.Text = SuggestedOffset.Value == null - ? @"Play a few beatmaps to receive a suggested offset!" - : $@"Based on the last {averageHitErrorHistory.Count} play(s), the suggested offset is {SuggestedOffset.Value:N0} ms."; + ? AudioSettingsStrings.SuggestedOffsetNote + : AudioSettingsStrings.SuggestedOffsetValueReceived(averageHitErrorHistory.Count, SuggestedOffset.Value); applySuggestion.Enabled.Value = SuggestedOffset.Value != null; } diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs index 049ccedf37..df46e38491 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings }, new SettingsButton { - Text = @"Run latency certifier", + Text = DebugSettingsStrings.RunLatencyCertifier, Action = () => performer?.PerformFromScreen(menu => menu.Push(new LatencyCertifierScreen())) } }; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 71afec88d4..4eb3e54708 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -115,7 +115,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, safeAreaConsiderationsCheckbox = new SettingsCheckbox { - LabelText = "Shrink game to avoid cameras and notches", + LabelText = GraphicsSettingsStrings.ShrinkGameOnMobile, Current = osuConfig.GetBindable(OsuSetting.SafeAreaConsiderations), }, new SettingsSlider From 9706836778a8fb3e83c663dc9a957f2265001a64 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 3 Feb 2024 06:16:24 +0900 Subject: [PATCH 254/915] Update system requirements --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d7e710f392..dc5809d46b 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ If you are just looking to give the game a whirl, you can grab the latest releas ### Latest release: -| [Windows 8.1+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 10.15+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) | -| ------------- | ------------- | ------------- | ------------- | ------------- | +| [Windows 10+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 12+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) | +|--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------- | ------------- | ------------- | You can also generally download a version for your current device from the [osu! site](https://osu.ppy.sh/home/download). From 57bc5ee04fd68fc317dea18c51d6d473f1eb80dd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 3 Feb 2024 00:19:04 +0300 Subject: [PATCH 255/915] Improve readability --- osu.Game/Rulesets/Scoring/HitEventExtensions.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs index c3ad8980fe..ab36a54d3d 100644 --- a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs +++ b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs @@ -21,30 +21,28 @@ namespace osu.Game.Rulesets.Scoring { Debug.Assert(hitEvents.All(ev => ev.GameplayRate != null)); - double currentValue; - int k = 0; + int count = 0; double m = 0; double s = 0; - double mNext; foreach (var e in hitEvents) { if (!affectsUnstableRate(e)) continue; - // Division by gameplay rate is to account for TimeOffset scaling with gameplay rate. - currentValue = e.TimeOffset / e.GameplayRate!.Value; + count++; - k++; - mNext = m + (currentValue - m) / k; + // Division by gameplay rate is to account for TimeOffset scaling with gameplay rate. + double currentValue = e.TimeOffset / e.GameplayRate!.Value; + double mNext = m + (currentValue - m) / count; s += (currentValue - m) * (currentValue - mNext); m = mNext; } - if (k == 0) + if (count == 0) return null; - return 10.0 * Math.Sqrt(s / k); + return 10.0 * Math.Sqrt(s / count); } /// From 24e5c7ed42a58f7a787a965a84488a02e00e8e3f Mon Sep 17 00:00:00 2001 From: Loreos7 Date: Sat, 3 Feb 2024 02:02:21 +0300 Subject: [PATCH 256/915] fix formatting --- osu.Game/Localisation/AudioSettingsStrings.cs | 2 +- .../Settings/Sections/Audio/AudioOffsetAdjustControl.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs index d93de59cd2..f4537a4c1c 100644 --- a/osu.Game/Localisation/AudioSettingsStrings.cs +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -72,7 +72,7 @@ namespace osu.Game.Localisation /// /// "Based on the last {0} play(s), the suggested offset is {1} ms" /// - public static LocalisableString SuggestedOffsetValueReceived(int plays, double? value) => new TranslatableString(getKey(@"suggested_offset_value_received"), @"Based on the last {0} play(s), the suggested offset is {1} ms", plays, value); + public static LocalisableString SuggestedOffsetValueReceived(int plays, string value) => new TranslatableString(getKey(@"suggested_offset_value_received"), @"Based on the last {0} play(s), the suggested offset is {1} ms", plays, value); /// /// "Apply suggested offset" diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs index 71c357c065..ad33434848 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs @@ -156,7 +156,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { hintText.Text = SuggestedOffset.Value == null ? AudioSettingsStrings.SuggestedOffsetNote - : AudioSettingsStrings.SuggestedOffsetValueReceived(averageHitErrorHistory.Count, SuggestedOffset.Value); + : AudioSettingsStrings.SuggestedOffsetValueReceived(averageHitErrorHistory.Count, $"{SuggestedOffset.Value:N0}"); applySuggestion.Enabled.Value = SuggestedOffset.Value != null; } From 498d93be614cfd9057ca9c3af0ff63f4c581b3f2 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Sat, 3 Feb 2024 16:59:48 +0100 Subject: [PATCH 257/915] Add way to associate with files and URIs on Windows --- .../TestSceneWindowsAssociationManager.cs | 106 +++++++ .../WindowsAssociationManagerStrings.cs | 39 +++ osu.Game/Updater/WindowsAssociationManager.cs | 268 ++++++++++++++++++ osu.sln.DotSettings | 1 + 4 files changed, 414 insertions(+) create mode 100644 osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs create mode 100644 osu.Game/Localisation/WindowsAssociationManagerStrings.cs create mode 100644 osu.Game/Updater/WindowsAssociationManager.cs diff --git a/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs b/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs new file mode 100644 index 0000000000..72256860fd --- /dev/null +++ b/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs @@ -0,0 +1,106 @@ +// 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.Diagnostics; +using System.IO; +using System.Runtime.Versioning; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Platform; +using osu.Game.Graphics.Sprites; +using osu.Game.Tests.Resources; +using osu.Game.Updater; + +namespace osu.Game.Tests.Visual.Updater +{ + [SupportedOSPlatform("windows")] + [Ignore("These tests modify the windows registry and open programs")] + public partial class TestSceneWindowsAssociationManager : OsuTestScene + { + private static readonly string exe_path = Path.ChangeExtension(typeof(TestSceneWindowsAssociationManager).Assembly.Location, ".exe"); + + [Resolved] + private GameHost host { get; set; } = null!; + + private readonly WindowsAssociationManager associationManager; + + public TestSceneWindowsAssociationManager() + { + Children = new Drawable[] + { + new OsuSpriteText { Text = Environment.CommandLine }, + associationManager = new WindowsAssociationManager(exe_path, "osu.Test"), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (Environment.CommandLine.Contains(".osz", StringComparison.Ordinal)) + ChangeBackgroundColour(ColourInfo.SingleColour(Colour4.DarkOliveGreen)); + + if (Environment.CommandLine.Contains("osu://", StringComparison.Ordinal)) + ChangeBackgroundColour(ColourInfo.SingleColour(Colour4.DarkBlue)); + + if (Environment.CommandLine.Contains("osump://", StringComparison.Ordinal)) + ChangeBackgroundColour(ColourInfo.SingleColour(Colour4.DarkRed)); + } + + [Test] + public void TestInstall() + { + AddStep("install", () => associationManager.InstallAssociations()); + } + + [Test] + public void TestOpenBeatmap() + { + string beatmapPath = null!; + AddStep("create temp beatmap", () => beatmapPath = TestResources.GetTestBeatmapForImport()); + AddAssert("beatmap path ends with .osz", () => beatmapPath, () => Does.EndWith(".osz")); + AddStep("open beatmap", () => host.OpenFileExternally(beatmapPath)); + AddUntilStep("wait for focus", () => host.IsActive.Value); + AddStep("delete temp beatmap", () => File.Delete(beatmapPath)); + } + + /// + /// To check that the icon is correct + /// + [Test] + public void TestPresentBeatmap() + { + string beatmapPath = null!; + AddStep("create temp beatmap", () => beatmapPath = TestResources.GetTestBeatmapForImport()); + AddAssert("beatmap path ends with .osz", () => beatmapPath, () => Does.EndWith(".osz")); + AddStep("show beatmap in explorer", () => host.PresentFileExternally(beatmapPath)); + AddUntilStep("wait for focus", () => host.IsActive.Value); + AddStep("delete temp beatmap", () => File.Delete(beatmapPath)); + } + + [TestCase("osu://s/1")] + [TestCase("osump://123")] + public void TestUrl(string url) + { + AddStep($"open {url}", () => Process.Start(new ProcessStartInfo(url) { UseShellExecute = true })); + } + + [Test] + public void TestUninstall() + { + AddStep("uninstall", () => associationManager.UninstallAssociations()); + } + + /// + /// Useful when testing things out and manually changing the registry. + /// + [Test] + public void TestNotifyShell() + { + AddStep("notify shell of changes", () => associationManager.NotifyShellUpdate()); + } + } +} diff --git a/osu.Game/Localisation/WindowsAssociationManagerStrings.cs b/osu.Game/Localisation/WindowsAssociationManagerStrings.cs new file mode 100644 index 0000000000..95a6decdd6 --- /dev/null +++ b/osu.Game/Localisation/WindowsAssociationManagerStrings.cs @@ -0,0 +1,39 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class WindowsAssociationManagerStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.WindowsAssociationManager"; + + /// + /// "osu! Beatmap" + /// + public static LocalisableString OsuBeatmap => new TranslatableString(getKey(@"osu_beatmap"), @"osu! Beatmap"); + + /// + /// "osu! Replay" + /// + public static LocalisableString OsuReplay => new TranslatableString(getKey(@"osu_replay"), @"osu! Replay"); + + /// + /// "osu! Skin" + /// + public static LocalisableString OsuSkin => new TranslatableString(getKey(@"osu_skin"), @"osu! Skin"); + + /// + /// "osu!" + /// + public static LocalisableString OsuProtocol => new TranslatableString(getKey(@"osu_protocol"), @"osu!"); + + /// + /// "osu! Multiplayer" + /// + public static LocalisableString OsuMultiplayer => new TranslatableString(getKey(@"osu_multiplayer"), @"osu! Multiplayer"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} \ No newline at end of file diff --git a/osu.Game/Updater/WindowsAssociationManager.cs b/osu.Game/Updater/WindowsAssociationManager.cs new file mode 100644 index 0000000000..8949d88362 --- /dev/null +++ b/osu.Game/Updater/WindowsAssociationManager.cs @@ -0,0 +1,268 @@ +// 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.Runtime.InteropServices; +using System.Runtime.Versioning; +using Microsoft.Win32; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Framework.Logging; +using osu.Game.Resources.Icons; +using osu.Game.Localisation; + +namespace osu.Game.Updater +{ + [SupportedOSPlatform("windows")] + public partial class WindowsAssociationManager : Component + { + public const string SOFTWARE_CLASSES = @"Software\Classes"; + + /// + /// Sub key for setting the icon. + /// https://learn.microsoft.com/en-us/windows/win32/com/defaulticon + /// + public const string DEFAULT_ICON = @"DefaultIcon"; + + /// + /// Sub key for setting the command line that the shell invokes. + /// https://learn.microsoft.com/en-us/windows/win32/com/shell + /// + public const string SHELL_OPEN_COMMAND = @"Shell\Open\Command"; + + private static readonly FileAssociation[] file_associations = + { + new FileAssociation(@".osz", WindowsAssociationManagerStrings.OsuBeatmap, Icons.Lazer), + new FileAssociation(@".olz", WindowsAssociationManagerStrings.OsuBeatmap, Icons.Lazer), + new FileAssociation(@".osr", WindowsAssociationManagerStrings.OsuReplay, Icons.Lazer), + new FileAssociation(@".osk", WindowsAssociationManagerStrings.OsuSkin, Icons.Lazer), + }; + + private static readonly UriAssociation[] uri_associations = + { + new UriAssociation(@"osu", WindowsAssociationManagerStrings.OsuProtocol, Icons.Lazer), + new UriAssociation(@"osump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer), + }; + + [Resolved] + private LocalisationManager localisation { get; set; } = null!; + + private IBindable localisationParameters = null!; + + private readonly string exePath; + private readonly string programIdPrefix; + + /// Path to the executable to register. + /// + /// Program ID prefix used for file associations. Should be relatively short since the full program ID has a 39 character limit, + /// see https://learn.microsoft.com/en-us/windows/win32/com/-progid--key. + /// + public WindowsAssociationManager(string exePath, string programIdPrefix) + { + this.exePath = exePath; + this.programIdPrefix = programIdPrefix; + } + + [BackgroundDependencyLoader] + private void load() + { + localisationParameters = localisation.CurrentParameters.GetBoundCopy(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + localisationParameters.ValueChanged += _ => updateDescriptions(); + } + + internal void InstallAssociations() + { + try + { + using (var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, writable: true)) + { + if (classes == null) + return; + + foreach (var association in file_associations) + association.Install(classes, exePath, programIdPrefix); + + foreach (var association in uri_associations) + association.Install(classes, exePath); + } + + updateDescriptions(); + } + catch (Exception e) + { + Logger.Log(@$"Failed to install file and URI associations: {e.Message}"); + } + } + + private void updateDescriptions() + { + try + { + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) + return; + + foreach (var association in file_associations) + { + var b = localisation.GetLocalisedBindableString(association.Description); + association.UpdateDescription(classes, programIdPrefix, b.Value); + b.UnbindAll(); + } + + foreach (var association in uri_associations) + { + var b = localisation.GetLocalisedBindableString(association.Description); + association.UpdateDescription(classes, b.Value); + b.UnbindAll(); + } + + NotifyShellUpdate(); + } + catch (Exception e) + { + Logger.Log($@"Failed to update file and URI associations: {e.Message}"); + } + } + + internal void UninstallAssociations() + { + try + { + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) + return; + + foreach (var association in file_associations) + association.Uninstall(classes, programIdPrefix); + + foreach (var association in uri_associations) + association.Uninstall(classes); + + NotifyShellUpdate(); + } + catch (Exception e) + { + Logger.Log($@"Failed to uninstall file and URI associations: {e.Message}"); + } + } + + internal void NotifyShellUpdate() => SHChangeNotify(EventId.SHCNE_ASSOCCHANGED, Flags.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero); + + #region Native interop + + [DllImport("Shell32.dll")] + private static extern void SHChangeNotify(EventId wEventId, Flags uFlags, IntPtr dwItem1, IntPtr dwItem2); + + private enum EventId + { + /// + /// A file type association has changed. must be specified in the uFlags parameter. + /// dwItem1 and dwItem2 are not used and must be . This event should also be sent for registered protocols. + /// + SHCNE_ASSOCCHANGED = 0x08000000 + } + + private enum Flags : uint + { + SHCNF_IDLIST = 0x0000 + } + + #endregion + + private record FileAssociation(string Extension, LocalisableString Description, Win32Icon Icon) + { + private string getProgramId(string prefix) => $@"{prefix}.File{Extension}"; + + /// + /// Installs a file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key + /// + public void Install(RegistryKey classes, string exePath, string programIdPrefix) + { + string programId = getProgramId(programIdPrefix); + + // register a program id for the given extension + using (var programKey = classes.CreateSubKey(programId)) + { + using (var defaultIconKey = programKey.CreateSubKey(DEFAULT_ICON)) + defaultIconKey.SetValue(null, Icon.RegistryString); + + using (var openCommandKey = programKey.CreateSubKey(SHELL_OPEN_COMMAND)) + openCommandKey.SetValue(null, $@"""{exePath}"" ""%1"""); + } + + using (var extensionKey = classes.CreateSubKey(Extension)) + { + // set ourselves as the default program + extensionKey.SetValue(null, programId); + + // add to the open with dialog + // https://learn.microsoft.com/en-us/windows/win32/shell/how-to-include-an-application-on-the-open-with-dialog-box + using (var openWithKey = extensionKey.CreateSubKey(@"OpenWithProgIds")) + openWithKey.SetValue(programId, string.Empty); + } + } + + public void UpdateDescription(RegistryKey classes, string programIdPrefix, string description) + { + using (var programKey = classes.OpenSubKey(getProgramId(programIdPrefix), true)) + programKey?.SetValue(null, description); + } + + public void Uninstall(RegistryKey classes, string programIdPrefix) + { + string programId = getProgramId(programIdPrefix); + + // importantly, we don't delete the default program entry because some other program could have taken it. + + using (var extensionKey = classes.OpenSubKey($@"{Extension}\OpenWithProgIds", true)) + extensionKey?.DeleteValue(programId, throwOnMissingValue: false); + + classes.DeleteSubKeyTree(programId, throwOnMissingSubKey: false); + } + } + + private record UriAssociation(string Protocol, LocalisableString Description, Win32Icon Icon) + { + /// + /// "The URL Protocol string value indicates that this key declares a custom pluggable protocol handler." + /// See https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85). + /// + public const string URL_PROTOCOL = @"URL Protocol"; + + /// + /// Registers an URI protocol handler in accordance with https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85). + /// + public void Install(RegistryKey classes, string exePath) + { + using (var protocolKey = classes.CreateSubKey(Protocol)) + { + protocolKey.SetValue(URL_PROTOCOL, string.Empty); + + using (var defaultIconKey = protocolKey.CreateSubKey(DEFAULT_ICON)) + defaultIconKey.SetValue(null, Icon.RegistryString); + + using (var openCommandKey = protocolKey.CreateSubKey(SHELL_OPEN_COMMAND)) + openCommandKey.SetValue(null, $@"""{exePath}"" ""%1"""); + } + } + + public void UpdateDescription(RegistryKey classes, string description) + { + using (var protocolKey = classes.OpenSubKey(Protocol, true)) + protocolKey?.SetValue(null, $@"URL:{description}"); + } + + public void Uninstall(RegistryKey classes) + { + classes.DeleteSubKeyTree(Protocol, throwOnMissingSubKey: false); + } + } + } +} diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 1bf8aa7b0b..e2e28c38ec 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -1005,6 +1005,7 @@ private void load() True True True + True True True True From 03578821c0c2c9fc4b4832208e7c10751f8b28af Mon Sep 17 00:00:00 2001 From: Susko3 Date: Sat, 3 Feb 2024 17:04:06 +0100 Subject: [PATCH 258/915] Associate on startup --- osu.Desktop/OsuGameDesktop.cs | 7 ++++++- osu.Game/Updater/WindowsAssociationManager.cs | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index a0db896f46..a048deddb3 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -134,9 +134,14 @@ namespace osu.Desktop LoadComponentAsync(new DiscordRichPresence(), Add); - if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows) + if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows && OperatingSystem.IsWindows()) + { LoadComponentAsync(new GameplayWinKeyBlocker(), Add); + string? executableLocation = Path.GetDirectoryName(typeof(OsuGameDesktop).Assembly.Location); + LoadComponentAsync(new WindowsAssociationManager(Path.Join(executableLocation, @"osu!.exe"), "osu"), Add); + } + LoadComponentAsync(new ElevatedPrivilegesChecker(), Add); osuSchemeLinkIPCChannel = new OsuSchemeLinkIPCChannel(Host, this); diff --git a/osu.Game/Updater/WindowsAssociationManager.cs b/osu.Game/Updater/WindowsAssociationManager.cs index 8949d88362..104406c81b 100644 --- a/osu.Game/Updater/WindowsAssociationManager.cs +++ b/osu.Game/Updater/WindowsAssociationManager.cs @@ -69,6 +69,7 @@ namespace osu.Game.Updater private void load() { localisationParameters = localisation.CurrentParameters.GetBoundCopy(); + InstallAssociations(); } protected override void LoadComplete() From 2bac09ee00d1e809e38aca97350e4853b2ebf09f Mon Sep 17 00:00:00 2001 From: Susko3 Date: Sat, 3 Feb 2024 17:23:59 +0100 Subject: [PATCH 259/915] Only associate on a deployed build Helps to reduce clutter when developing --- osu.Desktop/OsuGameDesktop.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index a048deddb3..c5175fd549 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -134,10 +134,11 @@ namespace osu.Desktop LoadComponentAsync(new DiscordRichPresence(), Add); - if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows && OperatingSystem.IsWindows()) - { + if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows) LoadComponentAsync(new GameplayWinKeyBlocker(), Add); + if (OperatingSystem.IsWindows() && IsDeployedBuild) + { string? executableLocation = Path.GetDirectoryName(typeof(OsuGameDesktop).Assembly.Location); LoadComponentAsync(new WindowsAssociationManager(Path.Join(executableLocation, @"osu!.exe"), "osu"), Add); } From 4aa27482a9b95ce8049d2a6cac1b1ded0945bc8f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 3 Feb 2024 19:52:40 +0300 Subject: [PATCH 260/915] Use SlimReadOnlyDictionaryWrapper for AliveEntries --- .../Objects/Pooling/PooledDrawableWithLifetimeContainer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs index aed608cf8f..efc10f26e1 100644 --- a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs +++ b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs @@ -2,12 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; +using osu.Framework.Extensions.ListExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Performance; +using osu.Framework.Lists; namespace osu.Game.Rulesets.Objects.Pooling { @@ -36,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Pooling /// /// The enumeration order is undefined. /// - public readonly ReadOnlyDictionary AliveEntries; + public readonly SlimReadOnlyDictionaryWrapper AliveEntries; /// /// Whether to remove an entry when clock goes backward and crossed its . @@ -65,7 +66,7 @@ namespace osu.Game.Rulesets.Objects.Pooling lifetimeManager.EntryBecameDead += entryBecameDead; lifetimeManager.EntryCrossedBoundary += entryCrossedBoundary; - AliveEntries = new ReadOnlyDictionary(aliveDrawableMap); + AliveEntries = aliveDrawableMap.AsSlimReadOnly(); } /// From e2e3c61c9c9e1a13434a6db6d919299ee459c78e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 3 Feb 2024 19:54:04 +0300 Subject: [PATCH 261/915] Use AliveEntries where we don't need startTime order --- osu.Game.Rulesets.Osu/Mods/OsuModDepth.cs | 4 +++- osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs | 4 +++- osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs | 4 +++- osu.Game/Screens/Play/FailAnimationContainer.cs | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDepth.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDepth.cs index b70d607ca1..a9111eec1f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDepth.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDepth.cs @@ -75,8 +75,10 @@ namespace osu.Game.Rulesets.Osu.Mods { double time = playfield.Time.Current; - foreach (var drawable in playfield.HitObjectContainer.AliveObjects) + foreach (var entry in playfield.HitObjectContainer.AliveEntries) { + var drawable = entry.Value; + switch (drawable) { case DrawableHitCircle circle: diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs index befee4af5a..b49fb931d1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs @@ -49,8 +49,10 @@ namespace osu.Game.Rulesets.Osu.Mods { var cursorPos = playfield.Cursor.AsNonNull().ActiveCursor.DrawPosition; - foreach (var drawable in playfield.HitObjectContainer.AliveObjects) + foreach (var entry in playfield.HitObjectContainer.AliveEntries) { + var drawable = entry.Value; + switch (drawable) { case DrawableHitCircle circle: diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs index 91feb33931..ced98f0cd5 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs @@ -48,8 +48,10 @@ namespace osu.Game.Rulesets.Osu.Mods { var cursorPos = playfield.Cursor.AsNonNull().ActiveCursor.DrawPosition; - foreach (var drawable in playfield.HitObjectContainer.AliveObjects) + foreach (var entry in playfield.HitObjectContainer.AliveEntries) { + var drawable = entry.Value; + var destination = Vector2.Clamp(2 * drawable.Position - cursorPos, Vector2.Zero, OsuPlayfield.BASE_SIZE); if (drawable.HitObject is Slider thisSlider) diff --git a/osu.Game/Screens/Play/FailAnimationContainer.cs b/osu.Game/Screens/Play/FailAnimationContainer.cs index 821c67e3cb..ebb0d77726 100644 --- a/osu.Game/Screens/Play/FailAnimationContainer.cs +++ b/osu.Game/Screens/Play/FailAnimationContainer.cs @@ -198,8 +198,10 @@ namespace osu.Game.Screens.Play foreach (var nested in playfield.NestedPlayfields) applyToPlayfield(nested); - foreach (DrawableHitObject obj in playfield.HitObjectContainer.AliveObjects) + foreach (var entry in playfield.HitObjectContainer.AliveEntries) { + var obj = entry.Value; + if (appliedObjects.Contains(obj)) continue; From cdcf5bddda5c15c518a810af6b68b06ab214ee52 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Sat, 3 Feb 2024 17:56:14 +0100 Subject: [PATCH 262/915] Uninstall associations when uninstalling from squirrel --- osu.Desktop/Program.cs | 2 ++ .../Visual/Updater/TestSceneWindowsAssociationManager.cs | 2 +- osu.Game/Updater/WindowsAssociationManager.cs | 8 +++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index a7453dc0e0..c9ce5ebf1b 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -12,6 +12,7 @@ using osu.Framework.Platform; using osu.Game; using osu.Game.IPC; using osu.Game.Tournament; +using osu.Game.Updater; using SDL2; using Squirrel; @@ -180,6 +181,7 @@ namespace osu.Desktop { tools.RemoveShortcutForThisExe(); tools.RemoveUninstallerRegistryEntry(); + WindowsAssociationManager.UninstallAssociations(@"osu"); }, onEveryRun: (_, _, _) => { // While setting the `ProcessAppUserModelId` fixes duplicate icons/shortcuts on the taskbar, it currently diff --git a/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs b/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs index 72256860fd..f3eb468334 100644 --- a/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs +++ b/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs @@ -100,7 +100,7 @@ namespace osu.Game.Tests.Visual.Updater [Test] public void TestNotifyShell() { - AddStep("notify shell of changes", () => associationManager.NotifyShellUpdate()); + AddStep("notify shell of changes", WindowsAssociationManager.NotifyShellUpdate); } } } diff --git a/osu.Game/Updater/WindowsAssociationManager.cs b/osu.Game/Updater/WindowsAssociationManager.cs index 104406c81b..bb0e37a2f4 100644 --- a/osu.Game/Updater/WindowsAssociationManager.cs +++ b/osu.Game/Updater/WindowsAssociationManager.cs @@ -78,7 +78,7 @@ namespace osu.Game.Updater localisationParameters.ValueChanged += _ => updateDescriptions(); } - internal void InstallAssociations() + public void InstallAssociations() { try { @@ -132,7 +132,9 @@ namespace osu.Game.Updater } } - internal void UninstallAssociations() + public void UninstallAssociations() => UninstallAssociations(programIdPrefix); + + public static void UninstallAssociations(string programIdPrefix) { try { @@ -154,7 +156,7 @@ namespace osu.Game.Updater } } - internal void NotifyShellUpdate() => SHChangeNotify(EventId.SHCNE_ASSOCCHANGED, Flags.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero); + internal static void NotifyShellUpdate() => SHChangeNotify(EventId.SHCNE_ASSOCCHANGED, Flags.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero); #region Native interop From 397def9ceb543ca7e6d0ada77bfde9558dae286d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 4 Feb 2024 02:58:15 +0300 Subject: [PATCH 263/915] Move layout specification outside the GradedCircles class --- .../Visual/Ranking/TestSceneGradedCircles.cs | 6 ++---- .../Ranking/Expanded/Accuracy/AccuracyCircle.cs | 14 +++++++++++++- .../Ranking/Expanded/Accuracy/GradedCircles.cs | 6 ------ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs b/osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs index 87fbca5c44..116386b4b5 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.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 osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; @@ -25,12 +24,11 @@ namespace osu.Game.Tests.Visual.Ranking double accuracyB = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.B); double accuracyC = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.C); - Add(new Container + Add(ring = new GradedCircles(accuracyC, accuracyB, accuracyA, accuracyS, accuracyX) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(400), - Child = ring = new GradedCircles(accuracyC, accuracyB, accuracyA, accuracyS, accuracyX) + Size = new Vector2(400) }); } diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 8304e7a542..8dc1a48f40 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -20,6 +20,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; +using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.Ranking.Expanded.Accuracy @@ -156,7 +157,18 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#7CF6FF"), Color4Extensions.FromHex("#BAFFA9")), InnerRadius = accuracy_circle_radius, }, - gradedCircles = new GradedCircles(accuracyC, accuracyB, accuracyA, accuracyS, accuracyX), + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.8f), + Padding = new MarginPadding(2.5f), + Child = gradedCircles = new GradedCircles(accuracyC, accuracyB, accuracyA, accuracyS, accuracyX) + { + RelativeSizeAxes = Axes.Both + } + }, badges = new Container { Name = "Rank badges", diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs index efcb848530..e60a24a310 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Scoring; -using osuTK; namespace osu.Game.Screens.Ranking.Expanded.Accuracy { @@ -39,11 +38,6 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy public GradedCircles(double accuracyC, double accuracyB, double accuracyA, double accuracyS, double accuracyX) { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - RelativeSizeAxes = Axes.Both; - Size = new Vector2(0.8f); - Padding = new MarginPadding(2.5f); InternalChildren = new Drawable[] { dProgress = new GradedCircle(0.0, accuracyC) From 4e5c9ddbfe6afad4713e9705cf4b28cd32cfd764 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 4 Feb 2024 03:02:39 +0300 Subject: [PATCH 264/915] Rename notch const to spacing --- .../Ranking/Expanded/Accuracy/AccuracyCircle.cs | 12 ++++++------ .../Ranking/Expanded/Accuracy/GradedCircles.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 8dc1a48f40..7edfc00760 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -76,9 +76,9 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy public const double VIRTUAL_SS_PERCENTAGE = 0.01; /// - /// The width of a solid "notch" in terms of accuracy that appears at the ends of the rank circles to add separation. + /// The width of spacing in terms of accuracy between the grade circles. /// - public const double NOTCH_WIDTH_PERCENTAGE = 2.0 / 360; + public const double GRADE_SPACING_PERCENTAGE = 2.0 / 360; /// /// The easing for the circle filling transforms. @@ -241,10 +241,10 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy // to prevent ambiguity on what grade it's pointing at. foreach (double p in notchPercentages) { - if (Precision.AlmostEquals(p, targetAccuracy, NOTCH_WIDTH_PERCENTAGE / 2)) + if (Precision.AlmostEquals(p, targetAccuracy, GRADE_SPACING_PERCENTAGE / 2)) { int tippingDirection = targetAccuracy - p >= 0 ? 1 : -1; // We "round up" here to match rank criteria - targetAccuracy = p + tippingDirection * (NOTCH_WIDTH_PERCENTAGE / 2); + targetAccuracy = p + tippingDirection * (GRADE_SPACING_PERCENTAGE / 2); break; } } @@ -253,7 +253,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH) targetAccuracy = 1; else - targetAccuracy = Math.Min(accuracyX - VIRTUAL_SS_PERCENTAGE - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy); + targetAccuracy = Math.Min(accuracyX - VIRTUAL_SS_PERCENTAGE - GRADE_SPACING_PERCENTAGE / 2, targetAccuracy); // The accuracy circle gauge visually fills up a bit too much. // This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases. @@ -349,7 +349,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy .FadeOut(800, Easing.Out); accuracyCircle - .FillTo(accuracyS - NOTCH_WIDTH_PERCENTAGE / 2 - visual_alignment_offset, 70, Easing.OutQuint); + .FillTo(accuracyS - GRADE_SPACING_PERCENTAGE / 2 - visual_alignment_offset, 70, Easing.OutQuint); badges.Single(b => b.Rank == getRank(ScoreRank.S)) .FadeOut(70, Easing.OutQuint); diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs index e60a24a310..57b6d8e4ac 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs @@ -79,8 +79,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy public GradedCircle(double startProgress, double endProgress) { - this.startProgress = startProgress + AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5; - this.endProgress = endProgress - AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 0.5; + this.startProgress = startProgress + AccuracyCircle.GRADE_SPACING_PERCENTAGE * 0.5; + this.endProgress = endProgress - AccuracyCircle.GRADE_SPACING_PERCENTAGE * 0.5; Anchor = Anchor.Centre; Origin = Anchor.Centre; From ba291621f0d9a0e074f8597f2f28aa203ee0c187 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sun, 4 Feb 2024 17:27:07 +0900 Subject: [PATCH 265/915] Adjust Android SDK target version --- osu.Android/AndroidManifest.xml | 2 +- osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml | 2 +- osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml | 2 +- osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml | 2 +- osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml | 2 +- osu.Game.Tests.Android/AndroidManifest.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Android/AndroidManifest.xml b/osu.Android/AndroidManifest.xml index a2b55257cb..a85e711cf2 100644 --- a/osu.Android/AndroidManifest.xml +++ b/osu.Android/AndroidManifest.xml @@ -1,6 +1,6 @@  - + - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml index f5a49210ea..df4930419c 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml index ed4725dd94..d0c3484cfd 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml index cc88d3080a..0ae9ee43ad 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Tests.Android/AndroidManifest.xml b/osu.Game.Tests.Android/AndroidManifest.xml index 6f91fb928c..71793af977 100644 --- a/osu.Game.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Tests.Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file From 9923c1b6e6e33fc982c3e61c457aa5210da3ae73 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 4 Feb 2024 17:08:39 +0300 Subject: [PATCH 266/915] Fix multiplayer/playlists lounge screen disposing rooms synchronously --- .../OnlinePlay/Lounge/Components/RoomsContainer.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index ac6403bb34..8a3fbbf792 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -141,9 +141,18 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void removeRooms(IEnumerable rooms) { - foreach (var r in rooms) + foreach (var room in rooms) { - roomFlow.RemoveAll(d => d.Room == r, true); + var drawableRoom = roomFlow.SingleOrDefault(d => d.Room == room); + if (drawableRoom == null) + continue; + + // expire to trigger async disposal. the room still has to exist somewhere so we move it to internal content of RoomsContainer until next frame. + drawableRoom.Hide(); + drawableRoom.Expire(); + + roomFlow.Remove(drawableRoom, false); + AddInternal(drawableRoom); // selection may have a lease due to being in a sub screen. if (!SelectedRoom.Disabled) From 6f9ee3f526745d073c1cf4978a229a796766ad64 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 00:30:48 +0300 Subject: [PATCH 267/915] Fix selected room bindable being set to null regardless of the removed room --- osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index ac6403bb34..bd06890753 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -146,7 +146,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components roomFlow.RemoveAll(d => d.Room == r, true); // selection may have a lease due to being in a sub screen. - if (!SelectedRoom.Disabled) + if (SelectedRoom.Value == r && !SelectedRoom.Disabled) SelectedRoom.Value = null; } } From 44a594ba05325bf28197c3727ef5813b36e4ad61 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 01:03:04 +0300 Subject: [PATCH 268/915] Simplify playback logic --- .../Expanded/Accuracy/AccuracyCircle.cs | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index e5ba9500ee..d209c305fa 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -85,9 +86,6 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// public static readonly Easing ACCURACY_TRANSFORM_EASING = Easing.OutPow10; - [Resolved] - private SkinManager skins { get; set; } - private readonly ScoreInfo score; private CircularProgress accuracyCircle; @@ -101,7 +99,6 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy private PoolableSkinnableSample swooshUpSound; private PoolableSkinnableSample rankImpactSound; private PoolableSkinnableSample rankApplauseSound; - private PoolableSkinnableSample rankLegacyApplauseSound; private readonly Bindable tickPlaybackRate = new Bindable(); @@ -263,11 +260,15 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy if (isFailedSDueToMisses) AddInternal(failedSRankText = new RankText(ScoreRank.S)); + var applauseSamples = new List { applauseSampleName }; + if (score.Rank >= ScoreRank.B) + // when rank is B or higher, play legacy applause sample on legacy skins. + applauseSamples.Insert(0, @"applause"); + AddRangeInternal(new Drawable[] { rankImpactSound = new PoolableSkinnableSample(new SampleInfo(impactSampleName)), - rankApplauseSound = new PoolableSkinnableSample(new SampleInfo(applauseSampleName)), - rankLegacyApplauseSound = new PoolableSkinnableSample(new SampleInfo("applause")), + rankApplauseSound = new PoolableSkinnableSample(new SampleInfo(applauseSamples.ToArray())), scoreTickSound = new PoolableSkinnableSample(new SampleInfo(@"Results/score-tick")), badgeTickSound = new PoolableSkinnableSample(new SampleInfo(@"Results/badge-dink")), badgeMaxSound = new PoolableSkinnableSample(new SampleInfo(@"Results/badge-dink-max")), @@ -401,20 +402,8 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { Schedule(() => { - if (skins.CurrentSkin.Value is LegacySkin) - { - // only play legacy "applause" sound if score rank is B or higher. - if (score.Rank >= ScoreRank.B) - { - rankLegacyApplauseSound.VolumeTo(applause_volume); - rankLegacyApplauseSound.Play(); - } - } - else - { - rankApplauseSound.VolumeTo(applause_volume); - rankApplauseSound.Play(); - } + rankApplauseSound.VolumeTo(applause_volume); + rankApplauseSound.Play(); }); } } From 5f39d4590ba1d69980a76537807a8f86b2476c52 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 5 Feb 2024 18:02:07 +0900 Subject: [PATCH 269/915] Update global.json version --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index da113e4cbd..789bff3bd0 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.0", + "version": "8.0.100", "rollForward": "latestFeature", "allowPrerelease": false } From 989e46c791de8261a970901fc8732b087d254a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 13:05:28 +0100 Subject: [PATCH 270/915] Use better test step name --- osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index 2bda242de2..3f2b71b320 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.Ranking Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); }); - AddToggleStep("toggle skin", v => + AddToggleStep("toggle legacy classic skin", v => { if (skins != null) skins.CurrentSkinInfo.Value = v ? skins.DefaultClassicSkin.SkinInfo : skins.CurrentSkinInfo.Default; From 2f4211249e0b3863d6058252ed55dc0e4f9d6c7f Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 5 Feb 2024 13:12:03 +0100 Subject: [PATCH 271/915] Use cleaner way to specify .exe path --- osu.Desktop/OsuGameDesktop.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index c5175fd549..a6d9ff1653 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -138,10 +138,7 @@ namespace osu.Desktop LoadComponentAsync(new GameplayWinKeyBlocker(), Add); if (OperatingSystem.IsWindows() && IsDeployedBuild) - { - string? executableLocation = Path.GetDirectoryName(typeof(OsuGameDesktop).Assembly.Location); - LoadComponentAsync(new WindowsAssociationManager(Path.Join(executableLocation, @"osu!.exe"), "osu"), Add); - } + LoadComponentAsync(new WindowsAssociationManager(Path.ChangeExtension(typeof(OsuGameDesktop).Assembly.Location, ".exe"), "osu"), Add); LoadComponentAsync(new ElevatedPrivilegesChecker(), Add); From efe6bb25b14db26e7c0b79494aa3eaf038dd99b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 13:21:01 +0100 Subject: [PATCH 272/915] Refactor result application around again to remove requirement for fields Co-authored-by: Dean Herbert --- .../Objects/Drawables/DrawableHoldNote.cs | 2 +- .../Objects/Drawables/DrawableHoldNoteBody.cs | 12 +++----- .../Drawables/DrawableManiaHitObject.cs | 2 +- .../Objects/Drawables/DrawableNote.cs | 3 +- .../TestSceneHitCircle.cs | 2 +- .../TestSceneHitCircleLateFade.cs | 2 +- .../Objects/Drawables/DrawableHitCircle.cs | 29 ++++++++++--------- .../Objects/Drawables/DrawableOsuHitObject.cs | 4 +-- .../Objects/Drawables/DrawableDrumRoll.cs | 2 +- .../Objects/Drawables/DrawableDrumRollTick.cs | 6 ++-- .../Objects/Drawables/DrawableFlyingHit.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 10 +++---- .../Drawables/DrawableStrongNestedHit.cs | 2 +- .../Objects/Drawables/DrawableSwell.cs | 2 +- .../Gameplay/TestSceneDrawableHitObject.cs | 2 +- .../Gameplay/TestScenePoolingRuleset.cs | 8 ++--- .../Rulesets/Judgements/JudgementResult.cs | 2 +- .../Objects/Drawables/DrawableHitObject.cs | 17 +++++++++-- 18 files changed, 59 insertions(+), 50 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 6c70ab3526..2b55e81788 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -265,7 +265,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (Tail.AllJudged) { if (Tail.IsHit) - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); else MissForcefully(); } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs index 731b1b6298..6259033235 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs @@ -11,8 +11,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public override bool DisplayResult => false; - private bool hit; - public DrawableHoldNoteBody() : this(null) { @@ -27,12 +25,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { if (AllJudged) return; - this.hit = hit; - ApplyResult(static (r, hitObject) => - { - var holdNoteBody = (DrawableHoldNoteBody)hitObject; - r.Type = holdNoteBody.hit ? r.Judgement.MaxResult : r.Judgement.MinResult; - }); + if (hit) + ApplyMaxResult(); + else + ApplyMinResult(); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 2d10fa27cd..e98622b8bf 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Causes this to get missed, disregarding all conditions in implementations of . /// - public virtual void MissForcefully() => ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + public virtual void MissForcefully() => ApplyMinResult(); } public abstract partial class DrawableManiaHitObject : DrawableManiaHitObject diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index a70253798a..2246552abe 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -91,12 +91,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); return; } hitResult = HitObject.HitWindows.ResultFor(timeOffset); + if (hitResult == HitResult.None) return; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index 8d4145f2c1..abe950f9bb 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && timeOffset > hitOffset && CheckHittable?.Invoke(this, Time.Current, HitResult.Great) == ClickAction.Hit) { // force success - ApplyResult(static (r, _) => r.Type = HitResult.Great); + ApplyResult(HitResult.Great); } else base.CheckForResult(userTriggered, timeOffset); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs index 2d1e9c1270..838b426cb4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs @@ -208,7 +208,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (shouldHit && !userTriggered && timeOffset >= 0) { // force success - ApplyResult(static (r, _) => r.Type = HitResult.Great); + ApplyResult(HitResult.Great); } else base.CheckForResult(userTriggered, timeOffset); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index ce5422b180..a014ba2e77 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -44,7 +44,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Container scaleContainer; private InputManager inputManager; - private HitResult hitResult; public DrawableHitCircle() : this(null) @@ -156,12 +155,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); return; } - hitResult = ResultFor(timeOffset); + HitResult hitResult = ResultFor(timeOffset); var clickAction = CheckHittable?.Invoke(this, Time.Current, hitResult); if (clickAction == ClickAction.Shake) @@ -170,20 +169,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (hitResult == HitResult.None || clickAction != ClickAction.Hit) return; - ApplyResult(static (r, hitObject) => + Vector2? hitPosition = null; + + // Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss. + if (hitResult.IsHit()) + { + var localMousePosition = ToLocalSpace(inputManager.CurrentState.Mouse.Position); + hitPosition = HitObject.StackedPosition + (localMousePosition - DrawSize / 2); + } + + ApplyResult<(HitResult result, Vector2? position)>((r, state) => { - var hitCircle = (DrawableHitCircle)hitObject; var circleResult = (OsuHitCircleJudgementResult)r; - // Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss. - if (hitCircle.hitResult.IsHit()) - { - var localMousePosition = hitCircle.ToLocalSpace(hitCircle.inputManager.CurrentState.Mouse.Position); - circleResult.CursorPositionAtHit = hitCircle.HitObject.StackedPosition + (localMousePosition - hitCircle.DrawSize / 2); - } - - circleResult.Type = hitCircle.hitResult; - }); + circleResult.Type = state.result; + circleResult.CursorPositionAtHit = state.position; + }, (hitResult, hitPosition)); } /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 6de60a9d51..5271c03e08 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -100,12 +100,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// /// Causes this to get hit, disregarding all conditions in implementations of . /// - public void HitForcefully() => ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + public void HitForcefully() => ApplyMaxResult(); /// /// Causes this to get missed, disregarding all conditions in implementations of . /// - public void MissForcefully() => ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + public void MissForcefully() => ApplyMinResult(); private RectangleF parentScreenSpaceRectangle => ((DrawableOsuHitObject)ParentHitObject)?.parentScreenSpaceRectangle ?? Parent!.ScreenSpaceDrawQuad.AABBFloat; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index e15298f3ca..1af4719b02 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (timeOffset < 0) return; - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index aa678d7043..0333fd71a9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (timeOffset > HitObject.HitWindow) - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); return; } if (Math.Abs(timeOffset) > HitObject.HitWindow) return; - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); } public override void OnKilled() @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables base.OnKilled(); if (Time.Current > HitObject.GetEndTime() && !Judged) - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs index 4349dff9f9..aad9214c5e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void LoadComplete() { base.LoadComplete(); - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); } protected override void LoadSamples() diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index cf8e4050ee..ca49ddb7e1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); return; } @@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return; if (!validActionPressed) - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); else { ApplyResult(static (r, hitObject) => @@ -217,19 +217,19 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!ParentHitObject.Result.IsHit) { - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); return; } if (!userTriggered) { if (timeOffset - ParentHitObject.Result.TimeOffset > SECOND_HIT_WINDOW) - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); return; } if (Math.Abs(timeOffset - ParentHitObject.Result.TimeOffset) <= SECOND_HIT_WINDOW) - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); } public override bool OnPressed(KeyBindingPressEvent e) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index 8f99538448..11759927a9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // it can happen that the hit window of the nested strong hit extends past the lifetime of the parent object. // this is a safety to prevent such cases from causing the nested hit to never be judged and as such prevent gameplay from completing. if (!Judged && Time.Current > ParentHitObject?.HitObject.GetEndTime()) - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 0781ea5e2a..6eb62cce22 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -208,7 +208,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint); if (numHits == HitObject.RequiredHits) - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); } else { diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs index bf1e52aab5..73177e36e1 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs @@ -216,7 +216,7 @@ namespace osu.Game.Tests.Gameplay LifetimeStart = LIFETIME_ON_APPLY; } - public void MissForcefully() => ApplyResult(static (r, _) => r.Type = HitResult.Miss); + public void MissForcefully() => ApplyResult(HitResult.Miss); protected override void UpdateHitStateTransforms(ArmedState state) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs index 00bd58e303..b567e8de8d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs @@ -431,7 +431,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void CheckForResult(bool userTriggered, double timeOffset) { if (timeOffset > HitObject.Duration) - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); } protected override void UpdateHitStateTransforms(ArmedState state) @@ -468,7 +468,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override void OnKilled() { base.OnKilled(); - ApplyResult(static (r, _) => r.Type = r.Judgement.MinResult); + ApplyMinResult(); } } @@ -547,7 +547,7 @@ namespace osu.Game.Tests.Visual.Gameplay { base.CheckForResult(userTriggered, timeOffset); if (timeOffset >= 0) - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); } } @@ -596,7 +596,7 @@ namespace osu.Game.Tests.Visual.Gameplay { base.CheckForResult(userTriggered, timeOffset); if (timeOffset >= 0) - ApplyResult(static (r, _) => r.Type = r.Judgement.MaxResult); + ApplyMaxResult(); } } diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index b781a13929..4b98df50d7 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Judgements /// /// The time at which this occurred. - /// Populated when this is applied via . + /// Populated when this is applied via . /// /// /// This is used instead of to check whether this should be reverted. diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e30ce13f08..07fab72814 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -682,17 +682,28 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateResult(false); } + protected void ApplyMaxResult() => ApplyResult((r, _) => r.Type = r.Judgement.MaxResult); + protected void ApplyMinResult() => ApplyResult((r, _) => r.Type = r.Judgement.MinResult); + + protected void ApplyResult(HitResult type) => ApplyResult(static (result, state) => result.Type = state, type); + + [Obsolete("Use overload with state, preferrably with static delegates to avoid allocation overhead.")] // Can be removed 2024-07-26 + protected void ApplyResult(Action application) => ApplyResult((r, _) => application(r), this); + + protected void ApplyResult(Action application) => ApplyResult(application, this); + /// /// Applies the of this , notifying responders such as /// the of the . /// /// The callback that applies changes to the . Using a `static` delegate is recommended to avoid allocation overhead. - protected void ApplyResult(Action application) + /// The state. + protected void ApplyResult(Action application, T state) { if (Result.HasResult) throw new InvalidOperationException("Cannot apply result on a hitobject that already has a result."); - application?.Invoke(Result, this); + application?.Invoke(Result, state); if (!Result.HasResult) throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}."); @@ -737,7 +748,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Checks if a scoring result has occurred for this . /// /// - /// If a scoring result has occurred, this method must invoke to update the result and notify responders. + /// If a scoring result has occurred, this method must invoke to update the result and notify responders. /// /// Whether the user triggered this check. /// The offset from the end time of the at which this check occurred. From 2976f225e0627ffa8cb4efe2ad6060e02a6fa5ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 13:22:58 +0100 Subject: [PATCH 273/915] Improve xmldoc of `state` param --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 07fab72814..c5f1878d1f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -697,7 +697,10 @@ namespace osu.Game.Rulesets.Objects.Drawables /// the of the . /// /// The callback that applies changes to the . Using a `static` delegate is recommended to avoid allocation overhead. - /// The state. + /// + /// Use this parameter to pass any data that requires + /// to apply a result, so that it can remain a `static` delegate and thus not allocate. + /// protected void ApplyResult(Action application, T state) { if (Result.HasResult) From fb80d76b4a814a8b79ce441833515f450ab8e12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 13:35:41 +0100 Subject: [PATCH 274/915] Apply further changes to remove remaining weirdness --- .../Drawables/DrawableEmptyFreeformHitObject.cs | 2 +- .../Drawables/DrawablePippidonHitObject.cs | 9 ++++----- .../Drawables/DrawableEmptyScrollingHitObject.cs | 3 +-- .../Drawables/DrawablePippidonHitObject.cs | 10 ++++------ .../Objects/Drawables/DrawableCatchHitObject.cs | 9 ++++----- .../Objects/Drawables/DrawableNote.cs | 15 ++++----------- .../Objects/Drawables/DrawableHitCircle.cs | 10 +++++----- .../Objects/Drawables/DrawableSpinnerTick.cs | 12 ++++-------- .../Objects/Drawables/DrawableHit.cs | 14 +++----------- .../Objects/Drawables/DrawableSwell.cs | 15 ++++++--------- .../Objects/Drawables/DrawableSwellTick.cs | 13 +++++-------- 11 files changed, 41 insertions(+), 71 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs index 3ad8f06fb4..e53fe01157 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Objects.Drawables { if (timeOffset >= 0) // todo: implement judgement logic - ApplyResult(static (r, hitObject) => r.Type = HitResult.Perfect); + ApplyResult(HitResult.Perfect); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index 925f2d04bf..b1be25727f 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Audio; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; using osuTK; using osuTK.Graphics; @@ -50,10 +49,10 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables { if (timeOffset >= 0) { - ApplyResult(static (r, hitObject) => - { - r.Type = hitObject.IsHovered ? HitResult.Perfect : HitResult.Miss; - }); + if (IsHovered) + ApplyMaxResult(); + else + ApplyMinResult(); } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs index 408bbea717..adcbd36485 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; using osuTK; using osuTK.Graphics; @@ -24,7 +23,7 @@ namespace osu.Game.Rulesets.EmptyScrolling.Objects.Drawables { if (timeOffset >= 0) // todo: implement judgement logic - ApplyResult(static (r, hitObject) => r.Type = HitResult.Perfect); + ApplyMaxResult(); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index 2c9eac7f65..3ad636a601 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Textures; using osu.Game.Audio; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Pippidon.UI; -using osu.Game.Rulesets.Scoring; using osuTK; using osuTK.Graphics; @@ -50,11 +49,10 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables { if (timeOffset >= 0) { - ApplyResult(static (r, hitObject) => - { - var pippidonHitObject = (DrawablePippidonHitObject)hitObject; - r.Type = pippidonHitObject.currentLane.Value == pippidonHitObject.HitObject.Lane ? HitResult.Perfect : HitResult.Miss; - }); + if (currentLane.Value == HitObject.Lane) + ApplyMaxResult(); + else + ApplyMinResult(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 721c6aaa59..64705f9909 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -64,11 +64,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables if (timeOffset >= 0 && Result != null) { - ApplyResult(static (r, hitObject) => - { - var catchHitObject = (DrawableCatchHitObject)hitObject; - r.Type = catchHitObject.CheckPosition!.Invoke(catchHitObject.HitObject) ? r.Judgement.MaxResult : r.Judgement.MinResult; - }); + if (CheckPosition.Invoke(HitObject)) + ApplyMaxResult(); + else + ApplyMinResult(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 2246552abe..f6b92ab405 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -38,8 +38,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables private Drawable headPiece; - private HitResult hitResult; - public DrawableNote() : this(null) { @@ -96,18 +94,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return; } - hitResult = HitObject.HitWindows.ResultFor(timeOffset); + var result = HitObject.HitWindows.ResultFor(timeOffset); - if (hitResult == HitResult.None) + if (result == HitResult.None) return; - hitResult = GetCappedResult(hitResult); - - ApplyResult(static (r, hitObject) => - { - var note = (DrawableNote)hitObject; - r.Type = note.hitResult; - }); + result = GetCappedResult(result); + ApplyResult(result); } /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index a014ba2e77..b1c9bef6c4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -160,19 +160,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return; } - HitResult hitResult = ResultFor(timeOffset); - var clickAction = CheckHittable?.Invoke(this, Time.Current, hitResult); + var result = ResultFor(timeOffset); + var clickAction = CheckHittable?.Invoke(this, Time.Current, result); if (clickAction == ClickAction.Shake) Shake(); - if (hitResult == HitResult.None || clickAction != ClickAction.Hit) + if (result == HitResult.None || clickAction != ClickAction.Hit) return; Vector2? hitPosition = null; // Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss. - if (hitResult.IsHit()) + if (result.IsHit()) { var localMousePosition = ToLocalSpace(inputManager.CurrentState.Mouse.Position); hitPosition = HitObject.StackedPosition + (localMousePosition - DrawSize / 2); @@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circleResult.Type = state.result; circleResult.CursorPositionAtHit = state.position; - }, (hitResult, hitPosition)); + }, (result, hitPosition)); } /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs index 628f07a281..0a77faf924 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs @@ -11,8 +11,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public override bool DisplayResult => false; - private bool hit; - public DrawableSpinnerTick() : this(null) { @@ -39,12 +37,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// Whether this tick was reached. internal void TriggerResult(bool hit) { - this.hit = hit; - ApplyResult(static (r, hitObject) => - { - var spinnerTick = (DrawableSpinnerTick)hitObject; - r.Type = spinnerTick.hit ? r.Judgement.MaxResult : r.Judgement.MinResult; - }); + if (hit) + ApplyMaxResult(); + else + ApplyMinResult(); } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index ca49ddb7e1..4fb69056da 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private double? lastPressHandleTime; - private HitResult hitResult; - private readonly Bindable type = new Bindable(); public DrawableHit() @@ -105,20 +103,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return; } - hitResult = HitObject.HitWindows.ResultFor(timeOffset); - if (hitResult == HitResult.None) + var result = HitObject.HitWindows.ResultFor(timeOffset); + if (result == HitResult.None) return; if (!validActionPressed) ApplyMinResult(); else - { - ApplyResult(static (r, hitObject) => - { - var drawableHit = (DrawableHit)hitObject; - r.Type = drawableHit.hitResult; - }); - } + ApplyResult(result); } public override bool OnPressed(KeyBindingPressEvent e) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 6eb62cce22..e1fc28fe16 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -41,8 +41,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private double? lastPressHandleTime; - private int numHits; - public override bool DisplayResult => false; public DrawableSwell() @@ -194,7 +192,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables nextTick?.TriggerResult(true); - numHits = ticks.Count(r => r.IsHit); + int numHits = ticks.Count(r => r.IsHit); float completion = (float)numHits / HitObject.RequiredHits; @@ -215,7 +213,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (timeOffset < 0) return; - numHits = 0; + int numHits = 0; foreach (var tick in ticks) { @@ -229,11 +227,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables tick.TriggerResult(false); } - ApplyResult(static (r, hitObject) => - { - var swell = (DrawableSwell)hitObject; - r.Type = swell.numHits == swell.HitObject.RequiredHits ? r.Judgement.MaxResult : r.Judgement.MinResult; - }); + if (numHits == HitObject.RequiredHits) + ApplyMaxResult(); + else + ApplyMinResult(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 557438e5e5..04dd01e066 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -15,8 +15,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public override bool DisplayResult => false; - private bool hit; - public DrawableSwellTick() : this(null) { @@ -31,13 +29,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public void TriggerResult(bool hit) { - this.hit = hit; HitObject.StartTime = Time.Current; - ApplyResult(static (r, hitObject) => - { - var swellTick = (DrawableSwellTick)hitObject; - r.Type = swellTick.hit ? r.Judgement.MaxResult : r.Judgement.MinResult; - }); + + if (hit) + ApplyMaxResult(); + else + ApplyMinResult(); } protected override void CheckForResult(bool userTriggered, double timeOffset) From 01efd1b353f556795f5d30eb4fe6723b7fcd6200 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 5 Feb 2024 13:34:03 +0100 Subject: [PATCH 275/915] Move `WindowsAssociationManager` to `osu.Desktop` --- osu.Desktop/Program.cs | 2 +- .../Windows}/WindowsAssociationManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {osu.Game/Updater => osu.Desktop/Windows}/WindowsAssociationManager.cs (99%) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index c9ce5ebf1b..edbf39a30a 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Runtime.Versioning; using osu.Desktop.LegacyIpc; +using osu.Desktop.Windows; using osu.Framework; using osu.Framework.Development; using osu.Framework.Logging; @@ -12,7 +13,6 @@ using osu.Framework.Platform; using osu.Game; using osu.Game.IPC; using osu.Game.Tournament; -using osu.Game.Updater; using SDL2; using Squirrel; diff --git a/osu.Game/Updater/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs similarity index 99% rename from osu.Game/Updater/WindowsAssociationManager.cs rename to osu.Desktop/Windows/WindowsAssociationManager.cs index bb0e37a2f4..038788f990 100644 --- a/osu.Game/Updater/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -13,7 +13,7 @@ using osu.Framework.Logging; using osu.Game.Resources.Icons; using osu.Game.Localisation; -namespace osu.Game.Updater +namespace osu.Desktop.Windows { [SupportedOSPlatform("windows")] public partial class WindowsAssociationManager : Component From 7789cc01eb31733fa76147adecf73db186c12759 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 5 Feb 2024 14:03:16 +0100 Subject: [PATCH 276/915] Copy .ico files when publishing These icons should appear in end-user installation folder. --- osu.Desktop/Windows/Icons.cs | 10 ++++++++++ osu.Desktop/Windows/Win32Icon.cs | 16 ++++++++++++++++ osu.Desktop/Windows/WindowsAssociationManager.cs | 5 ++--- osu.Desktop/osu.Desktop.csproj | 3 +++ 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 osu.Desktop/Windows/Icons.cs create mode 100644 osu.Desktop/Windows/Win32Icon.cs diff --git a/osu.Desktop/Windows/Icons.cs b/osu.Desktop/Windows/Icons.cs new file mode 100644 index 0000000000..cc60f92810 --- /dev/null +++ b/osu.Desktop/Windows/Icons.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Desktop.Windows +{ + public static class Icons + { + public static Win32Icon Lazer => new Win32Icon(@"lazer.ico"); + } +} diff --git a/osu.Desktop/Windows/Win32Icon.cs b/osu.Desktop/Windows/Win32Icon.cs new file mode 100644 index 0000000000..9544846c55 --- /dev/null +++ b/osu.Desktop/Windows/Win32Icon.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Desktop.Windows +{ + public record Win32Icon + { + public readonly string Path; + + internal Win32Icon(string name) + { + string dir = System.IO.Path.GetDirectoryName(typeof(Win32Icon).Assembly.Location)!; + Path = System.IO.Path.Join(dir, name); + } + } +} diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 038788f990..a5f977d15d 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -10,7 +10,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Logging; -using osu.Game.Resources.Icons; using osu.Game.Localisation; namespace osu.Desktop.Windows @@ -194,7 +193,7 @@ namespace osu.Desktop.Windows using (var programKey = classes.CreateSubKey(programId)) { using (var defaultIconKey = programKey.CreateSubKey(DEFAULT_ICON)) - defaultIconKey.SetValue(null, Icon.RegistryString); + defaultIconKey.SetValue(null, Icon.Path); using (var openCommandKey = programKey.CreateSubKey(SHELL_OPEN_COMMAND)) openCommandKey.SetValue(null, $@"""{exePath}"" ""%1"""); @@ -249,7 +248,7 @@ namespace osu.Desktop.Windows protocolKey.SetValue(URL_PROTOCOL, string.Empty); using (var defaultIconKey = protocolKey.CreateSubKey(DEFAULT_ICON)) - defaultIconKey.SetValue(null, Icon.RegistryString); + defaultIconKey.SetValue(null, Icon.Path); using (var openCommandKey = protocolKey.CreateSubKey(SHELL_OPEN_COMMAND)) openCommandKey.SetValue(null, $@"""{exePath}"" ""%1"""); diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index d6a11fa924..c6a95c1623 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -31,4 +31,7 @@ + + + From 4ec9d26657167bc7310984f093837ef183cef24f Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 5 Feb 2024 14:16:35 +0100 Subject: [PATCH 277/915] Inline constants --- osu.Desktop/OsuGameDesktop.cs | 2 +- .../Windows/WindowsAssociationManager.cs | 31 ++++++++----------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index a6d9ff1653..2e1b34fb38 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -138,7 +138,7 @@ namespace osu.Desktop LoadComponentAsync(new GameplayWinKeyBlocker(), Add); if (OperatingSystem.IsWindows() && IsDeployedBuild) - LoadComponentAsync(new WindowsAssociationManager(Path.ChangeExtension(typeof(OsuGameDesktop).Assembly.Location, ".exe"), "osu"), Add); + LoadComponentAsync(new WindowsAssociationManager(), Add); LoadComponentAsync(new ElevatedPrivilegesChecker(), Add); diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index a5f977d15d..7131067224 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.IO; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Microsoft.Win32; @@ -31,6 +32,14 @@ namespace osu.Desktop.Windows /// public const string SHELL_OPEN_COMMAND = @"Shell\Open\Command"; + public static readonly string EXE_PATH = Path.ChangeExtension(typeof(WindowsAssociationManager).Assembly.Location, ".exe"); + + /// + /// Program ID prefix used for file associations. Should be relatively short since the full program ID has a 39 character limit, + /// see https://learn.microsoft.com/en-us/windows/win32/com/-progid--key. + /// + public const string PROGRAM_ID_PREFIX = "osu"; + private static readonly FileAssociation[] file_associations = { new FileAssociation(@".osz", WindowsAssociationManagerStrings.OsuBeatmap, Icons.Lazer), @@ -50,20 +59,6 @@ namespace osu.Desktop.Windows private IBindable localisationParameters = null!; - private readonly string exePath; - private readonly string programIdPrefix; - - /// Path to the executable to register. - /// - /// Program ID prefix used for file associations. Should be relatively short since the full program ID has a 39 character limit, - /// see https://learn.microsoft.com/en-us/windows/win32/com/-progid--key. - /// - public WindowsAssociationManager(string exePath, string programIdPrefix) - { - this.exePath = exePath; - this.programIdPrefix = programIdPrefix; - } - [BackgroundDependencyLoader] private void load() { @@ -87,10 +82,10 @@ namespace osu.Desktop.Windows return; foreach (var association in file_associations) - association.Install(classes, exePath, programIdPrefix); + association.Install(classes, EXE_PATH, PROGRAM_ID_PREFIX); foreach (var association in uri_associations) - association.Install(classes, exePath); + association.Install(classes, EXE_PATH); } updateDescriptions(); @@ -112,7 +107,7 @@ namespace osu.Desktop.Windows foreach (var association in file_associations) { var b = localisation.GetLocalisedBindableString(association.Description); - association.UpdateDescription(classes, programIdPrefix, b.Value); + association.UpdateDescription(classes, PROGRAM_ID_PREFIX, b.Value); b.UnbindAll(); } @@ -131,7 +126,7 @@ namespace osu.Desktop.Windows } } - public void UninstallAssociations() => UninstallAssociations(programIdPrefix); + public void UninstallAssociations() => UninstallAssociations(PROGRAM_ID_PREFIX); public static void UninstallAssociations(string programIdPrefix) { From 0168ade2e13f200f475081d54363b8b9ee835687 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 5 Feb 2024 14:19:22 +0100 Subject: [PATCH 278/915] Remove tests Can be tested with ``` dotnet publish -f net6.0 -r win-x64 osu.Desktop -o publish -c Debug publish\osu! ``` --- .../TestSceneWindowsAssociationManager.cs | 106 ------------------ 1 file changed, 106 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs diff --git a/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs b/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs deleted file mode 100644 index f3eb468334..0000000000 --- a/osu.Game.Tests/Visual/Updater/TestSceneWindowsAssociationManager.cs +++ /dev/null @@ -1,106 +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 System.Diagnostics; -using System.IO; -using System.Runtime.Versioning; -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Platform; -using osu.Game.Graphics.Sprites; -using osu.Game.Tests.Resources; -using osu.Game.Updater; - -namespace osu.Game.Tests.Visual.Updater -{ - [SupportedOSPlatform("windows")] - [Ignore("These tests modify the windows registry and open programs")] - public partial class TestSceneWindowsAssociationManager : OsuTestScene - { - private static readonly string exe_path = Path.ChangeExtension(typeof(TestSceneWindowsAssociationManager).Assembly.Location, ".exe"); - - [Resolved] - private GameHost host { get; set; } = null!; - - private readonly WindowsAssociationManager associationManager; - - public TestSceneWindowsAssociationManager() - { - Children = new Drawable[] - { - new OsuSpriteText { Text = Environment.CommandLine }, - associationManager = new WindowsAssociationManager(exe_path, "osu.Test"), - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - if (Environment.CommandLine.Contains(".osz", StringComparison.Ordinal)) - ChangeBackgroundColour(ColourInfo.SingleColour(Colour4.DarkOliveGreen)); - - if (Environment.CommandLine.Contains("osu://", StringComparison.Ordinal)) - ChangeBackgroundColour(ColourInfo.SingleColour(Colour4.DarkBlue)); - - if (Environment.CommandLine.Contains("osump://", StringComparison.Ordinal)) - ChangeBackgroundColour(ColourInfo.SingleColour(Colour4.DarkRed)); - } - - [Test] - public void TestInstall() - { - AddStep("install", () => associationManager.InstallAssociations()); - } - - [Test] - public void TestOpenBeatmap() - { - string beatmapPath = null!; - AddStep("create temp beatmap", () => beatmapPath = TestResources.GetTestBeatmapForImport()); - AddAssert("beatmap path ends with .osz", () => beatmapPath, () => Does.EndWith(".osz")); - AddStep("open beatmap", () => host.OpenFileExternally(beatmapPath)); - AddUntilStep("wait for focus", () => host.IsActive.Value); - AddStep("delete temp beatmap", () => File.Delete(beatmapPath)); - } - - /// - /// To check that the icon is correct - /// - [Test] - public void TestPresentBeatmap() - { - string beatmapPath = null!; - AddStep("create temp beatmap", () => beatmapPath = TestResources.GetTestBeatmapForImport()); - AddAssert("beatmap path ends with .osz", () => beatmapPath, () => Does.EndWith(".osz")); - AddStep("show beatmap in explorer", () => host.PresentFileExternally(beatmapPath)); - AddUntilStep("wait for focus", () => host.IsActive.Value); - AddStep("delete temp beatmap", () => File.Delete(beatmapPath)); - } - - [TestCase("osu://s/1")] - [TestCase("osump://123")] - public void TestUrl(string url) - { - AddStep($"open {url}", () => Process.Start(new ProcessStartInfo(url) { UseShellExecute = true })); - } - - [Test] - public void TestUninstall() - { - AddStep("uninstall", () => associationManager.UninstallAssociations()); - } - - /// - /// Useful when testing things out and manually changing the registry. - /// - [Test] - public void TestNotifyShell() - { - AddStep("notify shell of changes", WindowsAssociationManager.NotifyShellUpdate); - } - } -} From 17033e09f679f1f2c7800bdb552545967c42fa18 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 5 Feb 2024 14:29:17 +0100 Subject: [PATCH 279/915] Change to class to satisfy CFS hopefully --- osu.Desktop/Windows/Win32Icon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/Windows/Win32Icon.cs b/osu.Desktop/Windows/Win32Icon.cs index 9544846c55..401e7a2be3 100644 --- a/osu.Desktop/Windows/Win32Icon.cs +++ b/osu.Desktop/Windows/Win32Icon.cs @@ -3,7 +3,7 @@ namespace osu.Desktop.Windows { - public record Win32Icon + public class Win32Icon { public readonly string Path; From 8b9c9f4fedcb8177e5b33061eec320b3832e2d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 14:52:08 +0100 Subject: [PATCH 280/915] Add NRT annotations to `DrawableManiaRuleset` --- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 070021ef74..decf670c5d 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -61,9 +59,9 @@ namespace osu.Game.Rulesets.Mania.UI // Stores the current speed adjustment active in gameplay. private readonly Track speedAdjustmentTrack = new TrackVirtual(0); - private ISkinSource currentSkin; + private ISkinSource currentSkin = null!; - public DrawableManiaRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) + public DrawableManiaRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList? mods = null) : base(ruleset, beatmap, mods) { BarLines = new BarLineGenerator(Beatmap).BarLines; @@ -114,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.UI updateTimeRange(); } - private ScheduledDelegate pendingSkinChange; + private ScheduledDelegate? pendingSkinChange; private float hitPosition; private void onSkinChange() @@ -160,7 +158,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant); - public override DrawableHitObject CreateDrawableRepresentation(ManiaHitObject h) => null; + public override DrawableHitObject? CreateDrawableRepresentation(ManiaHitObject h) => null; protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay); From 9e1a24fdefe24dc3d6d8daa57439ffefe4ddacde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 16:20:50 +0100 Subject: [PATCH 281/915] Remove pointless enum --- .../Overlays/FirstRunSetup/ScreenImportFromStable.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs index 0b2b750136..a56af540e4 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs @@ -326,13 +326,4 @@ namespace osu.Game.Overlays.FirstRunSetup } } } - - public enum FileSystemAddition - { - [LocalisableDescription(typeof(FirstRunOverlayImportFromStableScreenStrings), nameof(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureNtfs))] - ToAvoidEnsureNtfs, - - [LocalisableDescription(typeof(FirstRunOverlayImportFromStableScreenStrings), nameof(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureHardLinksSupport))] - ToAvoidEnsureHardLinksSupport, - } } From fa894bda059e58626639e4a487181f191f207837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 16:25:44 +0100 Subject: [PATCH 282/915] Fix broken spacing --- osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs index a56af540e4..526dffa06f 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs @@ -137,6 +137,7 @@ namespace osu.Game.Overlays.FirstRunSetup copyInformation.Text = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? FirstRunOverlayImportFromStableScreenStrings.SecondCopyWillBeMade(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureNtfs) : FirstRunOverlayImportFromStableScreenStrings.SecondCopyWillBeMade(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureHardLinksSupport); + copyInformation.AddText(@" "); // just to ensure correct spacing copyInformation.AddLink(GeneralSettingsStrings.ChangeFolderLocation, () => { game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen())); From 148e01327b41ebde80f9f1c0a83f844d14a93f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 16:27:56 +0100 Subject: [PATCH 283/915] Split copy info text into two rather than parameterise I have very low hopes translators would be able to correctly navigate this otherwise (especially in languages with different word order). --- .../FirstRunOverlayImportFromStableScreenStrings.cs | 13 ++++--------- .../FirstRunSetup/ScreenImportFromStable.cs | 4 ++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs b/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs index bbd83d2395..04fecab3df 100644 --- a/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs +++ b/osu.Game/Localisation/FirstRunOverlayImportFromStableScreenStrings.cs @@ -67,19 +67,14 @@ namespace osu.Game.Localisation public static LocalisableString LightweightLinkingNotSupported => new TranslatableString(getKey(@"lightweight_linking_not_supported"), @"Lightweight linking of files is not supported on your operating system yet, so a copy of all files will be made during import."); /// - /// "A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install {0}." + /// "A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install (and the file system is NTFS)." /// - public static LocalisableString SecondCopyWillBeMade(LocalisableString extra) => new TranslatableString(getKey(@"second_copy_will_be_made"), @"A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install {0}.", extra); + public static LocalisableString SecondCopyWillBeMadeWindows => new TranslatableString(getKey(@"second_copy_will_be_made_windows"), @"A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install (and the file system is NTFS)."); /// - /// "(and the file system is NTFS)" + /// "A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install (and the file system supports hard links)." /// - public static LocalisableString ToAvoidEnsureNtfs => new TranslatableString(getKey(@"to_avoid_ensure_ntfs"), @"(and the file system is NTFS)"); - - /// - /// "(and the file system supports hard links)" - /// - public static LocalisableString ToAvoidEnsureHardLinksSupport => new TranslatableString(getKey(@"to_avoid_ensure_hard_links_support"), @"(and the file system supports hard links)"); + public static LocalisableString SecondCopyWillBeMadeOtherPlatforms => new TranslatableString(getKey(@"second_copy_will_be_made_other_platforms"), @"A second copy of all files will be made during import. To avoid this, please make sure the lazer data folder is on the same drive as your previous osu! install (and the file system supports hard links)."); private static string getKey(string key) => $@"{prefix}:{key}"; } diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs index 526dffa06f..b19a9c6c99 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs @@ -135,8 +135,8 @@ namespace osu.Game.Overlays.FirstRunSetup else { copyInformation.Text = RuntimeInfo.OS == RuntimeInfo.Platform.Windows - ? FirstRunOverlayImportFromStableScreenStrings.SecondCopyWillBeMade(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureNtfs) - : FirstRunOverlayImportFromStableScreenStrings.SecondCopyWillBeMade(FirstRunOverlayImportFromStableScreenStrings.ToAvoidEnsureHardLinksSupport); + ? FirstRunOverlayImportFromStableScreenStrings.SecondCopyWillBeMadeWindows + : FirstRunOverlayImportFromStableScreenStrings.SecondCopyWillBeMadeOtherPlatforms; copyInformation.AddText(@" "); // just to ensure correct spacing copyInformation.AddLink(GeneralSettingsStrings.ChangeFolderLocation, () => { From 858f2fc7495867a600631e8683cefb193cc255fc Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 18:39:04 +0300 Subject: [PATCH 284/915] Use `Clear` to trigger async disposal --- .../Lounge/Components/RoomsContainer.cs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 8a3fbbf792..fd9aa6cb0e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -126,7 +126,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components case NotifyCollectionChangedAction.Remove: Debug.Assert(args.OldItems != null); - removeRooms(args.OldItems.Cast()); + if (args.OldItems.Count == roomFlow.Count) + clearRooms(); + else + removeRooms(args.OldItems.Cast()); + break; } } @@ -141,18 +145,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void removeRooms(IEnumerable rooms) { - foreach (var room in rooms) + foreach (var r in rooms) { - var drawableRoom = roomFlow.SingleOrDefault(d => d.Room == room); - if (drawableRoom == null) - continue; - - // expire to trigger async disposal. the room still has to exist somewhere so we move it to internal content of RoomsContainer until next frame. - drawableRoom.Hide(); - drawableRoom.Expire(); - - roomFlow.Remove(drawableRoom, false); - AddInternal(drawableRoom); + roomFlow.RemoveAll(d => d.Room == r, true); // selection may have a lease due to being in a sub screen. if (!SelectedRoom.Disabled) @@ -160,6 +155,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components } } + private void clearRooms() + { + roomFlow.Clear(); + + // selection may have a lease due to being in a sub screen. + if (!SelectedRoom.Disabled) + SelectedRoom.Value = null; + } + private void updateSorting() { foreach (var room in roomFlow) From 4449ccd1d395c44b7a183f639bdd24d281b82eed Mon Sep 17 00:00:00 2001 From: Loreos7 Date: Mon, 5 Feb 2024 18:44:18 +0300 Subject: [PATCH 285/915] bring back missing dot --- osu.Game/Localisation/AudioSettingsStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs index f4537a4c1c..405eec985c 100644 --- a/osu.Game/Localisation/AudioSettingsStrings.cs +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -72,7 +72,7 @@ namespace osu.Game.Localisation /// /// "Based on the last {0} play(s), the suggested offset is {1} ms" /// - public static LocalisableString SuggestedOffsetValueReceived(int plays, string value) => new TranslatableString(getKey(@"suggested_offset_value_received"), @"Based on the last {0} play(s), the suggested offset is {1} ms", plays, value); + public static LocalisableString SuggestedOffsetValueReceived(int plays, string value) => new TranslatableString(getKey(@"suggested_offset_value_received"), @"Based on the last {0} play(s), the suggested offset is {1} ms.", plays, value); /// /// "Apply suggested offset" From 8e82327509ad91decc132d56fb065d5fffc0597a Mon Sep 17 00:00:00 2001 From: Loreos7 Date: Mon, 5 Feb 2024 18:45:32 +0300 Subject: [PATCH 286/915] one more dot --- osu.Game/Localisation/AudioSettingsStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs index 405eec985c..24508d6858 100644 --- a/osu.Game/Localisation/AudioSettingsStrings.cs +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -70,7 +70,7 @@ namespace osu.Game.Localisation public static LocalisableString SuggestedOffsetNote => new TranslatableString(getKey(@"suggested_offset_note"), @"Play a few beatmaps to receive a suggested offset!"); /// - /// "Based on the last {0} play(s), the suggested offset is {1} ms" + /// "Based on the last {0} play(s), the suggested offset is {1} ms." /// public static LocalisableString SuggestedOffsetValueReceived(int plays, string value) => new TranslatableString(getKey(@"suggested_offset_value_received"), @"Based on the last {0} play(s), the suggested offset is {1} ms.", plays, value); From 791423651640174323beef88c9607d5cde01690b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 18:49:59 +0300 Subject: [PATCH 287/915] Add explanatory note --- osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index fd9aa6cb0e..bff1a8c64c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -126,6 +126,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components case NotifyCollectionChangedAction.Remove: Debug.Assert(args.OldItems != null); + // clear operations have a separate path that benefits from async disposal, + // since disposing is quite expensive when performed on a high number of drawables synchronously. if (args.OldItems.Count == roomFlow.Count) clearRooms(); else From 48d42ca7d39c66a79cb7d5194c86a4a0fef96afd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 5 Feb 2024 23:58:10 +0800 Subject: [PATCH 288/915] Update framework --- 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 d944e2ce8e..d7f29beeb3 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index bd6891f448..a4cd26a372 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From 2932184d24512eb945c49542bfe005479722688a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 18:05:21 +0100 Subject: [PATCH 289/915] Rename localisable string --- osu.Game/Localisation/GraphicsSettingsStrings.cs | 2 +- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index d3952d0b4c..753444daf1 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -162,7 +162,7 @@ namespace osu.Game.Localisation /// /// "Shrink game to avoid cameras and notches" /// - public static LocalisableString ShrinkGameOnMobile => new TranslatableString(getKey(@"shrink_game_on_mobile"), @"Shrink game to avoid cameras and notches"); + public static LocalisableString ShrinkGameToSafeArea => new TranslatableString(getKey(@"shrink_game_to_safe_area"), @"Shrink game to avoid cameras and notches"); private static string getKey(string key) => $@"{prefix}:{key}"; } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 4eb3e54708..ce087f1807 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -115,7 +115,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, safeAreaConsiderationsCheckbox = new SettingsCheckbox { - LabelText = GraphicsSettingsStrings.ShrinkGameOnMobile, + LabelText = GraphicsSettingsStrings.ShrinkGameToSafeArea, Current = osuConfig.GetBindable(OsuSetting.SafeAreaConsiderations), }, new SettingsSlider From 87381334ffdb12f6b39ad0933cb95da50c676308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 18:06:51 +0100 Subject: [PATCH 290/915] Use more proper method of formatting --- osu.Game/Localisation/AudioSettingsStrings.cs | 2 +- .../Settings/Sections/Audio/AudioOffsetAdjustControl.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/AudioSettingsStrings.cs b/osu.Game/Localisation/AudioSettingsStrings.cs index 24508d6858..89db60d8a6 100644 --- a/osu.Game/Localisation/AudioSettingsStrings.cs +++ b/osu.Game/Localisation/AudioSettingsStrings.cs @@ -72,7 +72,7 @@ namespace osu.Game.Localisation /// /// "Based on the last {0} play(s), the suggested offset is {1} ms." /// - public static LocalisableString SuggestedOffsetValueReceived(int plays, string value) => new TranslatableString(getKey(@"suggested_offset_value_received"), @"Based on the last {0} play(s), the suggested offset is {1} ms.", plays, value); + public static LocalisableString SuggestedOffsetValueReceived(int plays, LocalisableString value) => new TranslatableString(getKey(@"suggested_offset_value_received"), @"Based on the last {0} play(s), the suggested offset is {1} ms.", plays, value); /// /// "Apply suggested offset" diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs index ad33434848..b9f043a233 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs @@ -8,6 +8,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -156,7 +157,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { hintText.Text = SuggestedOffset.Value == null ? AudioSettingsStrings.SuggestedOffsetNote - : AudioSettingsStrings.SuggestedOffsetValueReceived(averageHitErrorHistory.Count, $"{SuggestedOffset.Value:N0}"); + : AudioSettingsStrings.SuggestedOffsetValueReceived(averageHitErrorHistory.Count, SuggestedOffset.Value.ToLocalisableString(@"N0")); applySuggestion.Enabled.Value = SuggestedOffset.Value != null; } From a5aeb2ff9e98f6d0a034548c2bc6664359f8ade2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 18:56:20 +0100 Subject: [PATCH 291/915] Use better variable names It's not the 1970s. We can spare a few extra letters. --- osu.Game/Rulesets/Scoring/HitEventExtensions.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs index ab36a54d3d..f9c6d62608 100644 --- a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs +++ b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs @@ -22,8 +22,8 @@ namespace osu.Game.Rulesets.Scoring Debug.Assert(hitEvents.All(ev => ev.GameplayRate != null)); int count = 0; - double m = 0; - double s = 0; + double mean = 0; + double sumOfSquares = 0; foreach (var e in hitEvents) { @@ -34,15 +34,15 @@ namespace osu.Game.Rulesets.Scoring // Division by gameplay rate is to account for TimeOffset scaling with gameplay rate. double currentValue = e.TimeOffset / e.GameplayRate!.Value; - double mNext = m + (currentValue - m) / count; - s += (currentValue - m) * (currentValue - mNext); - m = mNext; + double nextMean = mean + (currentValue - mean) / count; + sumOfSquares += (currentValue - mean) * (currentValue - nextMean); + mean = nextMean; } if (count == 0) return null; - return 10.0 * Math.Sqrt(s / count); + return 10.0 * Math.Sqrt(sumOfSquares / count); } /// From 7b03bebd5fd8b4288ea03da66ada81bf7f831781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 18:57:55 +0100 Subject: [PATCH 292/915] Move algorithm description to remarks section of xmldoc --- osu.Game/Rulesets/Scoring/HitEventExtensions.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs index f9c6d62608..6e2852676a 100644 --- a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs +++ b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs @@ -11,8 +11,11 @@ namespace osu.Game.Rulesets.Scoring public static class HitEventExtensions { /// - /// Calculates the "unstable rate" for a sequence of s using Welford's online algorithm. + /// Calculates the "unstable rate" for a sequence of s. /// + /// + /// Uses Welford's online algorithm. + /// /// /// A non-null value if unstable rate could be calculated, /// and if unstable rate cannot be calculated due to being empty. From e1a5aeac198903735125d9867389fef946754e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 19:10:14 +0100 Subject: [PATCH 293/915] Commit benchmark to source Co-authored-by: Andrei Zavatski --- osu.Game.Benchmarks/BenchmarkUnstableRate.cs | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 osu.Game.Benchmarks/BenchmarkUnstableRate.cs diff --git a/osu.Game.Benchmarks/BenchmarkUnstableRate.cs b/osu.Game.Benchmarks/BenchmarkUnstableRate.cs new file mode 100644 index 0000000000..aa229c7d06 --- /dev/null +++ b/osu.Game.Benchmarks/BenchmarkUnstableRate.cs @@ -0,0 +1,31 @@ +// 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 BenchmarkDotNet.Attributes; +using osu.Framework.Utils; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Benchmarks +{ + public class BenchmarkUnstableRate : BenchmarkTest + { + private List events = null!; + + public override void SetUp() + { + base.SetUp(); + events = new List(); + + for (int i = 0; i < 1000; i++) + events.Add(new HitEvent(RNG.NextDouble(-200.0, 200.0), RNG.NextDouble(1.0, 2.0), HitResult.Great, new HitObject(), null, null)); + } + + [Benchmark] + public void CalculateUnstableRate() + { + _ = events.CalculateUnstableRate(); + } + } +} From c1feccb4cfc6c7929e7adbfc8c1af04145525f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Feb 2024 19:53:19 +0100 Subject: [PATCH 294/915] Add test coverage for selection behaviour --- .../Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index b938e59d63..0883c626fe 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -64,6 +64,12 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("select first room", () => container.Rooms.First().TriggerClick()); AddAssert("first spotlight selected", () => checkRoomSelected(RoomManager.Rooms.First(r => r.Category.Value == RoomCategory.Spotlight))); + + AddStep("remove last room", () => RoomManager.RemoveRoom(RoomManager.Rooms.MinBy(r => r.RoomID?.Value))); + AddAssert("first spotlight still selected", () => checkRoomSelected(RoomManager.Rooms.First(r => r.Category.Value == RoomCategory.Spotlight))); + + AddStep("remove spotlight room", () => RoomManager.RemoveRoom(RoomManager.Rooms.Single(r => r.Category.Value == RoomCategory.Spotlight))); + AddAssert("selection vacated", () => checkRoomSelected(null)); } [Test] From 4be4ed7ab255fe6cff9b6b882e011a26a5ff15ff Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 23:27:16 +0300 Subject: [PATCH 295/915] Add "ranked" attribute to scores --- osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs | 4 ++++ osu.Game/Scoring/ScoreInfo.cs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs index 732da3d5da..42b9d9414f 100644 --- a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs @@ -115,6 +115,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty("has_replay")] public bool HasReplay { get; set; } + [JsonProperty("ranked")] + public bool Ranked { get; set; } + // These properties are calculated or not relevant to any external usage. public bool ShouldSerializeID() => false; public bool ShouldSerializeUser() => false; @@ -212,6 +215,7 @@ namespace osu.Game.Online.API.Requests.Responses HasOnlineReplay = HasReplay, Mods = mods, PP = PP, + Ranked = Ranked, }; if (beatmap is BeatmapInfo realmBeatmap) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 32e4bbbf29..fd98107792 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -107,6 +107,12 @@ namespace osu.Game.Scoring public double? PP { get; set; } + /// + /// Whether the performance points in this score is awarded to the player. This is used for online display purposes (see ). + /// + [Ignored] + public bool Ranked { get; set; } + /// /// The online ID of this score. /// From 6b7ffc240bbe3eb9138c3620ad175d2d9c7a3487 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 23:28:21 +0300 Subject: [PATCH 296/915] Support displaying "unranked PP" placeholder --- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 8 +++--- .../Scores/TopScoreStatisticsSection.cs | 8 +++--- .../Sections/Ranks/DrawableProfileScore.cs | 11 ++++++++ .../UnrankedPerformancePointsPlaceholder.cs | 26 +++++++++++++++++++ 4 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 1fc997fdad..c8ecb38c86 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -180,10 +180,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (showPerformancePoints) { - if (score.PP != null) - content.Add(new StatisticText(score.PP, format: @"N0")); - else + if (!score.Ranked) + content.Add(new UnrankedPerformancePointsPlaceholder { Font = OsuFont.GetFont(size: text_size) }); + else if (score.PP == null) content.Add(new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(text_size) }); + else + content.Add(new StatisticText(score.PP, format: @"N0")); } content.Add(new ScoreboardTime(score.Date, text_size) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 72e590b009..488b99d620 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -125,10 +125,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores ppColumn.Alpha = value.BeatmapInfo!.Status.GrantsPerformancePoints() ? 1 : 0; - if (value.PP is double pp) - ppColumn.Text = pp.ToLocalisableString(@"N0"); - else + if (!value.Ranked) + ppColumn.Drawable = new UnrankedPerformancePointsPlaceholder { Font = smallFont }; + else if (value.PP is not double pp) ppColumn.Drawable = new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(smallFont.Size) }; + else + ppColumn.Text = pp.ToLocalisableString(@"N0"); statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn); modsColumn.Mods = value.Mods; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index c26f2f19ba..c7d7af0bd7 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -216,7 +216,18 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks if (!Score.PP.HasValue) { if (Score.Beatmap?.Status.GrantsPerformancePoints() == true) + { + if (!Score.Ranked) + { + return new UnrankedPerformancePointsPlaceholder + { + Font = OsuFont.GetFont(weight: FontWeight.Bold), + Colour = colourProvider.Highlight1 + }; + } + return new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(16), Colour = colourProvider.Highlight1 }; + } return new OsuSpriteText { diff --git a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs new file mode 100644 index 0000000000..4c44def1ee --- /dev/null +++ b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable +using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; + +namespace osu.Game.Scoring.Drawables +{ + /// + /// A placeholder used in PP columns for scores that do not award PP. + /// + public partial class UnrankedPerformancePointsPlaceholder : SpriteText, IHasTooltip + { + public LocalisableString TooltipText => "pp is not awarded for this score"; // todo: replace with localised string ScoresStrings.StatusNoPp. + + public UnrankedPerformancePointsPlaceholder() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + Text = "-"; + } + } +} From b78c6ed673353d6d9158dc7b24c5278100a4e74f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 23:28:30 +0300 Subject: [PATCH 297/915] Update design of "unprocessed PP" placeholder to match web --- .../Drawables/UnprocessedPerformancePointsPlaceholder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs b/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs index 99eb7e964d..a2cb69062e 100644 --- a/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs +++ b/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs @@ -21,7 +21,7 @@ namespace osu.Game.Scoring.Drawables { Anchor = Anchor.Centre; Origin = Anchor.Centre; - Icon = FontAwesome.Solid.ExclamationTriangle; + Icon = FontAwesome.Solid.Sync; } } } From b0da0859d8c91a5b0c22805894bb56680c7a15c7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 5 Feb 2024 23:28:53 +0300 Subject: [PATCH 298/915] Add visual test cases --- .../Visual/Online/TestSceneScoresContainer.cs | 19 +++++++++++ .../Online/TestSceneUserProfileScores.cs | 34 ++++++++++++++++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 2bfbf76c10..33f4d577bd 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -154,6 +154,19 @@ namespace osu.Game.Tests.Visual.Online }); } + [Test] + public void TestUnrankedPP() + { + AddStep("Load scores with unranked PP", () => + { + var allScores = createScores(); + allScores.Scores[0].Ranked = false; + allScores.UserScore = createUserBest(); + allScores.UserScore.Score.Ranked = false; + scoresContainer.Scores = allScores; + }); + } + private ulong onlineID = 1; private APIScoresCollection createScores() @@ -184,6 +197,7 @@ namespace osu.Game.Tests.Visual.Online MaxCombo = 1234, TotalScore = 1234567890, Accuracy = 1, + Ranked = true, }, new SoloScoreInfo { @@ -206,6 +220,7 @@ namespace osu.Game.Tests.Visual.Online MaxCombo = 1234, TotalScore = 1234789, Accuracy = 0.9997, + Ranked = true, }, new SoloScoreInfo { @@ -227,6 +242,7 @@ namespace osu.Game.Tests.Visual.Online MaxCombo = 1234, TotalScore = 12345678, Accuracy = 0.9854, + Ranked = true, }, new SoloScoreInfo { @@ -247,6 +263,7 @@ namespace osu.Game.Tests.Visual.Online MaxCombo = 1234, TotalScore = 1234567, Accuracy = 0.8765, + Ranked = true, }, new SoloScoreInfo { @@ -263,6 +280,7 @@ namespace osu.Game.Tests.Visual.Online MaxCombo = 1234, TotalScore = 123456, Accuracy = 0.6543, + Ranked = true, }, } }; @@ -309,6 +327,7 @@ namespace osu.Game.Tests.Visual.Online MaxCombo = 1234, TotalScore = 123456, Accuracy = 0.6543, + Ranked = true, }, Position = 1337, }; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs index 5249e8694d..f72980757b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs @@ -40,7 +40,8 @@ namespace osu.Game.Tests.Visual.Online new APIMod { Acronym = new OsuModHardRock().Acronym }, new APIMod { Acronym = new OsuModDoubleTime().Acronym }, }, - Accuracy = 0.9813 + Accuracy = 0.9813, + Ranked = true, }; var secondScore = new SoloScoreInfo @@ -62,7 +63,8 @@ namespace osu.Game.Tests.Visual.Online new APIMod { Acronym = new OsuModHardRock().Acronym }, new APIMod { Acronym = new OsuModDoubleTime().Acronym }, }, - Accuracy = 0.998546 + Accuracy = 0.998546, + Ranked = true, }; var thirdScore = new SoloScoreInfo @@ -79,7 +81,8 @@ namespace osu.Game.Tests.Visual.Online DifficultyName = "Insane" }, EndedAt = DateTimeOffset.Now, - Accuracy = 0.9726 + Accuracy = 0.9726, + Ranked = true, }; var noPPScore = new SoloScoreInfo @@ -95,7 +98,8 @@ namespace osu.Game.Tests.Visual.Online DifficultyName = "[4K] Cataclysmic Hypernova" }, EndedAt = DateTimeOffset.Now, - Accuracy = 0.55879 + Accuracy = 0.55879, + Ranked = true, }; var unprocessedPPScore = new SoloScoreInfo @@ -112,7 +116,26 @@ namespace osu.Game.Tests.Visual.Online Status = BeatmapOnlineStatus.Ranked, }, EndedAt = DateTimeOffset.Now, - Accuracy = 0.55879 + Accuracy = 0.55879, + Ranked = true, + }; + + var unrankedPPScore = new SoloScoreInfo + { + Rank = ScoreRank.B, + Beatmap = new APIBeatmap + { + BeatmapSet = new APIBeatmapSet + { + Title = "C18H27NO3(extend)", + Artist = "Team Grimoire", + }, + DifficultyName = "[4K] Cataclysmic Hypernova", + Status = BeatmapOnlineStatus.Ranked, + }, + EndedAt = DateTimeOffset.Now, + Accuracy = 0.55879, + Ranked = false, }; Add(new FillFlowContainer @@ -129,6 +152,7 @@ namespace osu.Game.Tests.Visual.Online new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(secondScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(noPPScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(unprocessedPPScore)), + new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(unrankedPPScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(firstScore, 0.97)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(secondScore, 0.85)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(thirdScore, 0.66)), From 0da67e64b371c75aa76a4c01e6c3762aa208c603 Mon Sep 17 00:00:00 2001 From: kongehund <63306696+kongehund@users.noreply.github.com> Date: Tue, 6 Feb 2024 00:28:39 +0100 Subject: [PATCH 299/915] Fix deselecting slider adding control points --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 3575e15d1d..e421d497e7 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -171,7 +171,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders return false; // Allow right click to be handled by context menu case MouseButton.Left: - if (e.ControlPressed && IsSelected) + // If there's more than two objects selected, ctrl+click should deselect + if (e.ControlPressed && IsSelected && selectedObjects.Count < 2) { changeHandler?.BeginChange(); placementControlPoint = addControlPoint(e.MousePosition); From 08fac9772082088526845236c1b6dc471cee0e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Feb 2024 12:27:45 +0100 Subject: [PATCH 300/915] Add resources covering failure case --- .../special-skin/taiko-bar-right@2x.png | Bin 0 -> 39297 bytes .../special-skin/taikohitcircle@2x.png | Bin 0 -> 8720 bytes .../special-skin/taikohitcircleoverlay@2x.png | Bin 0 -> 6478 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taiko-bar-right@2x.png create mode 100644 osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taikohitcircle@2x.png create mode 100644 osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taikohitcircleoverlay@2x.png diff --git a/osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taiko-bar-right@2x.png b/osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taiko-bar-right@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8ad7849e53161dc0e6320582aa54953389236a50 GIT binary patch literal 39297 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taikohitcircle@2x.png b/osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taikohitcircle@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..73f856b16b67b84add2959868e4abca51bb7dea3 GIT binary patch literal 8720 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taikohitcircleoverlay@2x.png b/osu.Game.Rulesets.Taiko.Tests/Resources/special-skin/taikohitcircleoverlay@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..83647266bceeb3a0e5311ecffa0ee7582ca6d6ec GIT binary patch literal 6478 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 A!2kdN literal 0 HcmV?d00001 From 27b97a3c4d720766e4c2468e2890fcaae69d40f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Feb 2024 12:01:35 +0100 Subject: [PATCH 301/915] Convert selected legacy skin sprites to grayscale Matching stable. Closes https://github.com/ppy/osu/issues/9858. I would have liked to apply this in the taiko transformer itself, but the limited accessibility of texture uploads, and as such the raw image data, sort of prevents that... --- osu.Game/Skinning/LegacySkin.cs | 3 + osu.Game/Skinning/LegacyTextureLoaderStore.cs | 92 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 osu.Game/Skinning/LegacyTextureLoaderStore.cs diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index cfa5f972d2..816cfc0a2d 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -58,6 +58,9 @@ namespace osu.Game.Skinning { } + protected override IResourceStore CreateTextureLoaderStore(IStorageResourceProvider resources, IResourceStore storage) + => new LegacyTextureLoaderStore(base.CreateTextureLoaderStore(resources, storage)); + protected override void ParseConfigurationStream(Stream stream) { base.ParseConfigurationStream(stream); diff --git a/osu.Game/Skinning/LegacyTextureLoaderStore.cs b/osu.Game/Skinning/LegacyTextureLoaderStore.cs new file mode 100644 index 0000000000..8c466e6aac --- /dev/null +++ b/osu.Game/Skinning/LegacyTextureLoaderStore.cs @@ -0,0 +1,92 @@ +// 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.IO; +using System.Threading; +using System.Threading.Tasks; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Processing; + +namespace osu.Game.Skinning +{ + public class LegacyTextureLoaderStore : IResourceStore + { + private readonly IResourceStore? wrappedStore; + + public LegacyTextureLoaderStore(IResourceStore? wrappedStore) + { + this.wrappedStore = wrappedStore; + } + + public TextureUpload Get(string name) + { + var textureUpload = wrappedStore?.Get(name); + + if (textureUpload == null) + return null!; + + return shouldConvertToGrayscale(name) + ? convertToGrayscale(textureUpload) + : textureUpload; + } + + public Task GetAsync(string name, CancellationToken cancellationToken = new CancellationToken()) + { + var textureUpload = wrappedStore?.Get(name); + + if (textureUpload == null) + return null!; + + return shouldConvertToGrayscale(name) + ? Task.Run(() => convertToGrayscale(textureUpload), cancellationToken) + : Task.FromResult(textureUpload); + } + + // https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/Graphics/Textures/TextureManager.cs#L91-L96 + private static readonly string[] grayscale_sprites = + { + @"taiko-bar-right", + @"taikobigcircle", + @"taikohitcircle", + @"taikohitcircleoverlay" + }; + + private bool shouldConvertToGrayscale(string name) + { + foreach (string grayscaleSprite in grayscale_sprites) + { + // unfortunately at this level of lookup we can encounter `@2x` scale suffixes in the name, + // so straight equality cannot be used. + if (name.StartsWith(grayscaleSprite, StringComparison.OrdinalIgnoreCase)) + return true; + } + + return false; + } + + private TextureUpload convertToGrayscale(TextureUpload textureUpload) + { + var image = Image.LoadPixelData(textureUpload.Data.ToArray(), textureUpload.Width, textureUpload.Height); + + // stable uses `0.299 * r + 0.587 * g + 0.114 * b` + // (https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/Graphics/Textures/pTexture.cs#L138-L153) + // which matches mode BT.601 (https://en.wikipedia.org/wiki/Grayscale#Luma_coding_in_video_systems) + image.Mutate(i => i.Grayscale(GrayscaleMode.Bt601)); + + return new TextureUpload(image); + } + + public Stream? GetStream(string name) => wrappedStore?.GetStream(name); + + public IEnumerable GetAvailableResources() => wrappedStore?.GetAvailableResources() ?? Array.Empty(); + + public void Dispose() + { + wrappedStore?.Dispose(); + } + } +} From a84f53b1693892973535250163d13dfe8981ee9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Feb 2024 13:03:05 +0100 Subject: [PATCH 302/915] Allow pp for Blinds The mod does impact pp, but it requires no extra difficulty attributes (https://github.com/ppy/osu/pull/26935#issuecomment-1925734171). --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 8b0adbe50f..bb0e984418 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; public override Type[] IncompatibleMods => new[] { typeof(OsuModFlashlight) }; + public override bool Ranked => true; private DrawableOsuBlinds blinds = null!; From 8df593a8e6734f59e9c3dc81b903e8e6dc5f20e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Feb 2024 13:03:38 +0100 Subject: [PATCH 303/915] Allow pp for No Scope Deemed as not affecting difficulty or pp in https://github.com/ppy/osu/pull/26935#issuecomment-1925644008, so can be treated pretty much as nomod. --- osu.Game/Rulesets/Mods/ModNoScope.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModNoScope.cs b/osu.Game/Rulesets/Mods/ModNoScope.cs index 5b9dfc0430..dd1bd9a719 100644 --- a/osu.Game/Rulesets/Mods/ModNoScope.cs +++ b/osu.Game/Rulesets/Mods/ModNoScope.cs @@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.Fun; public override IconUsage? Icon => FontAwesome.Solid.EyeSlash; public override double ScoreMultiplier => 1; + public override bool Ranked => true; /// /// Slightly higher than the cutoff for . From 9e7912e66310fdfaec7bd9e2b27b1f3369eae81a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 6 Feb 2024 21:56:26 +0900 Subject: [PATCH 304/915] Add test showing filled heatmap --- .../TestSceneAccuracyHeatmap.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs index f99518997b..5524af2061 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Rulesets.Osu.Tests { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(130) + Size = new Vector2(300) } }; }); @@ -85,6 +85,30 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("return user input", () => InputManager.UseParentInput = true); } + [Test] + public void TestAllPoints() + { + AddStep("add points", () => + { + float minX = object1.DrawPosition.X - object1.DrawSize.X / 2; + float maxX = object1.DrawPosition.X + object1.DrawSize.X / 2; + + float minY = object1.DrawPosition.Y - object1.DrawSize.Y / 2; + float maxY = object1.DrawPosition.Y + object1.DrawSize.Y / 2; + + for (int i = 0; i < 10; i++) + { + for (float x = minX; x <= maxX; x += 0.5f) + { + for (float y = minY; y <= maxY; y += 0.5f) + { + accuracyHeatmap.AddPoint(object2.Position, object1.Position, new Vector2(x, y), RNG.NextSingle(10, 500)); + } + } + } + }); + } + protected override bool OnMouseDown(MouseDownEvent e) { accuracyHeatmap.AddPoint(object2.Position, object1.Position, background.ToLocalSpace(e.ScreenSpaceMouseDownPosition), 50); From 891346f7958b517d82022cf4ecaf2f980032c5fe Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 6 Feb 2024 21:56:52 +0900 Subject: [PATCH 305/915] Fix hit accuracy heatmap points being offset --- osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index 83bab7dc01..f9d4a3b325 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -191,7 +191,7 @@ namespace osu.Game.Rulesets.Osu.Statistics for (int c = 0; c < points_per_dimension; c++) { - HitPointType pointType = Vector2.Distance(new Vector2(c, r), centre) <= innerRadius + HitPointType pointType = Vector2.Distance(new Vector2(c + 0.5f, r + 0.5f), centre) <= innerRadius ? HitPointType.Hit : HitPointType.Miss; From 5850d6a57807aee271aae79532964bc85d345e1a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 6 Feb 2024 20:06:51 +0900 Subject: [PATCH 306/915] Show near-misses on the results-screen heatmap --- osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs | 7 +- .../Objects/Drawables/DrawableHitCircle.cs | 74 +++++++++++-------- .../Statistics/AccuracyHeatmap.cs | 60 +++++++++------ 3 files changed, 81 insertions(+), 60 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs b/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs index 10d7af5e58..0e3f972d41 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs @@ -95,12 +95,7 @@ namespace osu.Game.Rulesets.Osu.Mods /// private static void blockInputToObjectsUnderSliderHead(DrawableSliderHead slider) { - var oldHitAction = slider.HitArea.Hit; - slider.HitArea.Hit = () => - { - oldHitAction?.Invoke(); - return !slider.DrawableSlider.AllJudged; - }; + slider.HitArea.CanBeHit = () => !slider.DrawableSlider.AllJudged; } private void applyEarlyFading(DrawableHitCircle circle) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index b1c9bef6c4..3727e78d01 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -10,7 +10,6 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; @@ -43,7 +42,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Drawable IHasApproachCircle.ApproachCircle => ApproachCircle; private Container scaleContainer; - private InputManager inputManager; public DrawableHitCircle() : this(null) @@ -73,14 +71,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { HitArea = new HitReceptor { - Hit = () => - { - if (AllJudged) - return false; - - UpdateResult(true); - return true; - }, + CanBeHit = () => !AllJudged, + Hit = () => UpdateResult(true) }, shakeContainer = new ShakeContainer { @@ -114,13 +106,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue)); } - protected override void LoadComplete() - { - base.LoadComplete(); - - inputManager = GetContainingInputManager(); - } - public override double LifetimeStart { get => base.LifetimeStart; @@ -155,7 +140,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyMinResult(); + { + ApplyResult((r, position) => + { + var circleResult = (OsuHitCircleJudgementResult)r; + + circleResult.Type = r.Judgement.MinResult; + circleResult.CursorPositionAtHit = position; + }, computeHitPosition()); + } return; } @@ -169,22 +162,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (result == HitResult.None || clickAction != ClickAction.Hit) return; - Vector2? hitPosition = null; - - // Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss. - if (result.IsHit()) - { - var localMousePosition = ToLocalSpace(inputManager.CurrentState.Mouse.Position); - hitPosition = HitObject.StackedPosition + (localMousePosition - DrawSize / 2); - } - ApplyResult<(HitResult result, Vector2? position)>((r, state) => { var circleResult = (OsuHitCircleJudgementResult)r; circleResult.Type = state.result; circleResult.CursorPositionAtHit = state.position; - }, (result, hitPosition)); + }, (result, computeHitPosition())); + } + + private Vector2? computeHitPosition() + { + if (HitArea.ClosestPressPosition is Vector2 screenSpaceHitPosition) + return HitObject.StackedPosition + (ToLocalSpace(screenSpaceHitPosition) - DrawSize / 2); + + return null; } /// @@ -227,6 +219,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; case ArmedState.Idle: + HitArea.ClosestPressPosition = null; HitArea.HitAction = null; break; @@ -247,9 +240,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // IsHovered is used public override bool HandlePositionalInput => true; - public Func Hit; + public Func CanBeHit; + public Action Hit; public OsuAction? HitAction; + public Vector2? ClosestPressPosition; public HitReceptor() { @@ -264,12 +259,31 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public bool OnPressed(KeyBindingPressEvent e) { + if (!(CanBeHit?.Invoke() ?? false)) + return false; + switch (e.Action) { case OsuAction.LeftButton: case OsuAction.RightButton: - if (IsHovered && (Hit?.Invoke() ?? false)) + // Only update closest press position while the object hasn't been hit yet. + if (HitAction == null) { + if (ClosestPressPosition is Vector2 curClosest) + { + float oldDist = Vector2.DistanceSquared(curClosest, ScreenSpaceDrawQuad.Centre); + float newDist = Vector2.DistanceSquared(e.ScreenSpaceMousePosition, ScreenSpaceDrawQuad.Centre); + + if (newDist < oldDist) + ClosestPressPosition = e.ScreenSpaceMousePosition; + } + else + ClosestPressPosition = e.ScreenSpaceMousePosition; + } + + if (IsHovered) + { + Hit?.Invoke(); HitAction ??= e.Action; return true; } diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index f9d4a3b325..813f3b2e7a 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -197,7 +197,9 @@ namespace osu.Game.Rulesets.Osu.Statistics var point = new HitPoint(pointType, this) { - BaseColour = pointType == HitPointType.Hit ? new Color4(102, 255, 204, 255) : new Color4(255, 102, 102, 255) + BaseColour = pointType == HitPointType.Hit + ? new Color4(102, 255, 204, 255) + : new Color4(255, 102, 102, 255) }; points[r][c] = point; @@ -250,12 +252,15 @@ namespace osu.Game.Rulesets.Osu.Statistics var rotatedCoordinate = -1 * new Vector2((float)Math.Cos(rotatedAngle), (float)Math.Sin(rotatedAngle)); Vector2 localCentre = new Vector2(points_per_dimension - 1) / 2; - float localRadius = localCentre.X * inner_portion * normalisedDistance; // The radius inside the inner portion which of the heatmap which the closest point lies. + float localRadius = localCentre.X * inner_portion * normalisedDistance; Vector2 localPoint = localCentre + localRadius * rotatedCoordinate; // Find the most relevant hit point. - int r = Math.Clamp((int)Math.Round(localPoint.Y), 0, points_per_dimension - 1); - int c = Math.Clamp((int)Math.Round(localPoint.X), 0, points_per_dimension - 1); + int r = (int)Math.Round(localPoint.Y); + int c = (int)Math.Round(localPoint.X); + + if (r < 0 || r >= points_per_dimension || c < 0 || c >= points_per_dimension) + return; PeakValue = Math.Max(PeakValue, ((HitPoint)pointGrid.Content[r][c]).Increment()); @@ -298,28 +303,35 @@ namespace osu.Game.Rulesets.Osu.Statistics { base.Update(); - // the point at which alpha is saturated and we begin to adjust colour lightness. - const float lighten_cutoff = 0.95f; - - // the amount of lightness to attribute regardless of relative value to peak point. - const float non_relative_portion = 0.2f; - - float amount = 0; - - // give some amount of alpha regardless of relative count - amount += non_relative_portion * Math.Min(1, count / 10f); - - // add relative portion - amount += (1 - non_relative_portion) * (count / heatmap.PeakValue); - - // apply easing - amount = (float)Interpolation.ApplyEasing(Easing.OutQuint, Math.Min(1, amount)); - - Debug.Assert(amount <= 1); - - Alpha = Math.Min(amount / lighten_cutoff, 1); if (pointType == HitPointType.Hit) + { + // the point at which alpha is saturated and we begin to adjust colour lightness. + const float lighten_cutoff = 0.95f; + + // the amount of lightness to attribute regardless of relative value to peak point. + const float non_relative_portion = 0.2f; + + float amount = 0; + + // give some amount of alpha regardless of relative count + amount += non_relative_portion * Math.Min(1, count / 10f); + + // add relative portion + amount += (1 - non_relative_portion) * (count / heatmap.PeakValue); + + // apply easing + amount = (float)Interpolation.ApplyEasing(Easing.OutQuint, Math.Min(1, amount)); + + Debug.Assert(amount <= 1); + + Alpha = Math.Min(amount / lighten_cutoff, 1); Colour = BaseColour.Lighten(Math.Max(0, amount - lighten_cutoff)); + } + else + { + Alpha = 0.8f; + Colour = BaseColour; + } } } From 99d716f8fc62aaaf09ca65fa7da6f8f876bd6b8a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 6 Feb 2024 22:23:30 +0900 Subject: [PATCH 307/915] Make miss points into crosses --- .../Statistics/AccuracyHeatmap.cs | 123 ++++++++++-------- 1 file changed, 68 insertions(+), 55 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index 813f3b2e7a..2120b929a7 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -9,6 +9,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -191,18 +192,22 @@ namespace osu.Game.Rulesets.Osu.Statistics for (int c = 0; c < points_per_dimension; c++) { - HitPointType pointType = Vector2.Distance(new Vector2(c + 0.5f, r + 0.5f), centre) <= innerRadius - ? HitPointType.Hit - : HitPointType.Miss; + bool isHit = Vector2.Distance(new Vector2(c + 0.5f, r + 0.5f), centre) <= innerRadius; - var point = new HitPoint(pointType, this) + if (isHit) { - BaseColour = pointType == HitPointType.Hit - ? new Color4(102, 255, 204, 255) - : new Color4(255, 102, 102, 255) - }; - - points[r][c] = point; + points[r][c] = new HitPoint(this) + { + BaseColour = new Color4(102, 255, 204, 255) + }; + } + else + { + points[r][c] = new MissPoint + { + BaseColour = new Color4(255, 102, 102, 255) + }; + } } } @@ -262,33 +267,21 @@ namespace osu.Game.Rulesets.Osu.Statistics if (r < 0 || r >= points_per_dimension || c < 0 || c >= points_per_dimension) return; - PeakValue = Math.Max(PeakValue, ((HitPoint)pointGrid.Content[r][c]).Increment()); + PeakValue = Math.Max(PeakValue, ((GridPoint)pointGrid.Content[r][c]).Increment()); bufferedGrid.ForceRedraw(); } - private partial class HitPoint : Circle + private abstract partial class GridPoint : CompositeDrawable { /// /// The base colour which will be lightened/darkened depending on the value of this . /// public Color4 BaseColour; - private readonly HitPointType pointType; - private readonly AccuracyHeatmap heatmap; + public override bool IsPresent => Count > 0; - public override bool IsPresent => count > 0; - - public HitPoint(HitPointType pointType, AccuracyHeatmap heatmap) - { - this.pointType = pointType; - this.heatmap = heatmap; - - RelativeSizeAxes = Axes.Both; - Alpha = 1; - } - - private int count; + protected int Count { get; private set; } /// /// Increment the value of this point by one. @@ -296,49 +289,69 @@ namespace osu.Game.Rulesets.Osu.Statistics /// The value after incrementing. public int Increment() { - return ++count; + return ++Count; + } + } + + private partial class MissPoint : GridPoint + { + public MissPoint() + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new SpriteIcon + { + RelativeSizeAxes = Axes.Both, + Icon = FontAwesome.Solid.Times + }; + } + + protected override void Update() + { + Alpha = 0.8f; + Colour = BaseColour; + } + } + + private partial class HitPoint : GridPoint + { + private readonly AccuracyHeatmap heatmap; + + public HitPoint(AccuracyHeatmap heatmap) + { + this.heatmap = heatmap; + + RelativeSizeAxes = Axes.Both; + + InternalChild = new Circle { RelativeSizeAxes = Axes.Both }; } protected override void Update() { base.Update(); - if (pointType == HitPointType.Hit) - { - // the point at which alpha is saturated and we begin to adjust colour lightness. - const float lighten_cutoff = 0.95f; + // the point at which alpha is saturated and we begin to adjust colour lightness. + const float lighten_cutoff = 0.95f; - // the amount of lightness to attribute regardless of relative value to peak point. - const float non_relative_portion = 0.2f; + // the amount of lightness to attribute regardless of relative value to peak point. + const float non_relative_portion = 0.2f; - float amount = 0; + float amount = 0; - // give some amount of alpha regardless of relative count - amount += non_relative_portion * Math.Min(1, count / 10f); + // give some amount of alpha regardless of relative count + amount += non_relative_portion * Math.Min(1, Count / 10f); - // add relative portion - amount += (1 - non_relative_portion) * (count / heatmap.PeakValue); + // add relative portion + amount += (1 - non_relative_portion) * (Count / heatmap.PeakValue); - // apply easing - amount = (float)Interpolation.ApplyEasing(Easing.OutQuint, Math.Min(1, amount)); + // apply easing + amount = (float)Interpolation.ApplyEasing(Easing.OutQuint, Math.Min(1, amount)); - Debug.Assert(amount <= 1); + Debug.Assert(amount <= 1); - Alpha = Math.Min(amount / lighten_cutoff, 1); - Colour = BaseColour.Lighten(Math.Max(0, amount - lighten_cutoff)); - } - else - { - Alpha = 0.8f; - Colour = BaseColour; - } + Alpha = Math.Min(amount / lighten_cutoff, 1); + Colour = BaseColour.Lighten(Math.Max(0, amount - lighten_cutoff)); } } - - private enum HitPointType - { - Hit, - Miss - } } } From c21af1bf3d44f3c5b70c95c573748c2f41cd35f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Feb 2024 14:53:01 +0100 Subject: [PATCH 308/915] Use more explicit match `taiko-bar-right-glow` is a prefix of `taiko-bar-right`... --- osu.Game/Skinning/LegacyTextureLoaderStore.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacyTextureLoaderStore.cs b/osu.Game/Skinning/LegacyTextureLoaderStore.cs index 8c466e6aac..29206bbb85 100644 --- a/osu.Game/Skinning/LegacyTextureLoaderStore.cs +++ b/osu.Game/Skinning/LegacyTextureLoaderStore.cs @@ -61,8 +61,11 @@ namespace osu.Game.Skinning { // unfortunately at this level of lookup we can encounter `@2x` scale suffixes in the name, // so straight equality cannot be used. - if (name.StartsWith(grayscaleSprite, StringComparison.OrdinalIgnoreCase)) + if (name.Equals(grayscaleSprite, StringComparison.OrdinalIgnoreCase) + || name.Equals($@"{grayscaleSprite}@2x", StringComparison.OrdinalIgnoreCase)) + { return true; + } } return false; From ee05743921d8ab7a6b1041b4d47adadee9540b00 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 6 Feb 2024 22:58:11 +0900 Subject: [PATCH 309/915] Bump databased star rating versions --- osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs | 2 +- osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 6bb6879052..4190e74e51 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty private readonly bool isForCurrentRuleset; private readonly double originalOverallDifficulty; - public override int Version => 20220902; + public override int Version => 20230817; public ManiaDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap) : base(ruleset, beatmap) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index ab193caaa3..b84c2d25ee 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { private const double difficulty_multiplier = 1.35; - public override int Version => 20220902; + public override int Version => 20221107; public TaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap) : base(ruleset, beatmap) From 5265d33c126c612a787bed98fa1c665d061c78c0 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 6 Feb 2024 23:32:54 +0900 Subject: [PATCH 310/915] Make coverage into a bindable --- .../TestScenePlayfieldCoveringContainer.cs | 12 ++++---- .../Mods/ManiaModPlayfieldCover.cs | 2 +- .../UI/PlayfieldCoveringWrapper.cs | 28 +++++++++++-------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs b/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs index 2a8dc715f9..341d52afcf 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs @@ -39,18 +39,18 @@ namespace osu.Game.Rulesets.Mania.Tests public void TestScrollingDownwards() { AddStep("set down scroll", () => scrollingContainer.Direction = ScrollingDirection.Down); - AddStep("set coverage = 0.5", () => cover.Coverage = 0.5f); - AddStep("set coverage = 0.8f", () => cover.Coverage = 0.8f); - AddStep("set coverage = 0.2f", () => cover.Coverage = 0.2f); + AddStep("set coverage = 0.5", () => cover.Coverage.Value = 0.5f); + AddStep("set coverage = 0.8f", () => cover.Coverage.Value = 0.8f); + AddStep("set coverage = 0.2f", () => cover.Coverage.Value = 0.2f); } [Test] public void TestScrollingUpwards() { AddStep("set up scroll", () => scrollingContainer.Direction = ScrollingDirection.Up); - AddStep("set coverage = 0.5", () => cover.Coverage = 0.5f); - AddStep("set coverage = 0.8f", () => cover.Coverage = 0.8f); - AddStep("set coverage = 0.2f", () => cover.Coverage = 0.2f); + AddStep("set coverage = 0.5", () => cover.Coverage.Value = 0.5f); + AddStep("set coverage = 0.8f", () => cover.Coverage.Value = 0.8f); + AddStep("set coverage = 0.2f", () => cover.Coverage.Value = 0.2f); } } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs index bc76c5cfe9..18c3ecc073 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Mods { c.RelativeSizeAxes = Axes.Both; c.Direction = ExpandDirection; - c.Coverage = Coverage.Value; + c.Coverage.BindTo(Coverage); })); } } diff --git a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs index 92f471e36b..0956b2f98f 100644 --- a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs +++ b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs @@ -19,6 +19,11 @@ namespace osu.Game.Rulesets.Mania.UI /// public partial class PlayfieldCoveringWrapper : CompositeDrawable { + /// + /// The relative area that should be completely covered. This does not include the fade. + /// + public readonly BindableFloat Coverage = new BindableFloat(); + /// /// The complete cover, including gradient and fill. /// @@ -94,21 +99,20 @@ namespace osu.Game.Rulesets.Mania.UI scrollDirection.BindValueChanged(onScrollDirectionChanged, true); } + protected override void LoadComplete() + { + base.LoadComplete(); + + Coverage.BindValueChanged(c => + { + filled.Height = c.NewValue; + gradient.Y = -c.NewValue; + }, true); + } + private void onScrollDirectionChanged(ValueChangedEvent direction) => cover.Rotation = direction.NewValue == ScrollingDirection.Up ? 0 : 180f; - /// - /// The relative area that should be completely covered. This does not include the fade. - /// - public float Coverage - { - set - { - filled.Height = value; - gradient.Y = -value; - } - } - /// /// The direction in which the cover expands. /// From 6ffe8e171373fa78c067f8c38747971ccf91f6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Feb 2024 14:48:49 +0100 Subject: [PATCH 311/915] Use staggered exponential backoff when retrying in `PersistentEndpointClientConnector` There are suspicions that the straight 5s retry could have caused a situation a few days ago for `osu-server-spectator` wherein it was getting hammered by constant retry requests. This should make that a little less likely to happen. Numbers chosen are arbitrary, but mostly follow stable's bancho retry intervals because why not. Stable also skips the exponential backoff in case of errors it considers transient, but I decided not to bother for now. Starts off from 3 seconds, then ramps up to up to 2 minutes. Added stagger factor is 25% of duration, either direction. The stagger factor helps given that if spectator server is dead, each client has three separate connections to it which it will retry on (one to each hub). --- .../PersistentEndpointClientConnector.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/PersistentEndpointClientConnector.cs b/osu.Game/Online/PersistentEndpointClientConnector.cs index 024a0fea73..9e7543ce2b 100644 --- a/osu.Game/Online/PersistentEndpointClientConnector.cs +++ b/osu.Game/Online/PersistentEndpointClientConnector.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Logging; +using osu.Framework.Utils; using osu.Game.Online.API; namespace osu.Game.Online @@ -31,6 +32,12 @@ namespace osu.Game.Online private CancellationTokenSource connectCancelSource = new CancellationTokenSource(); private bool started; + /// + /// How much to delay before attempting to connect again, in milliseconds. + /// Subject to exponential back-off. + /// + private int retryDelay = 3000; + /// /// Constructs a new . /// @@ -78,6 +85,8 @@ namespace osu.Game.Online private async Task connect() { cancelExistingConnect(); + // reset retry delay to default. + retryDelay = 3000; if (!await connectionLock.WaitAsync(10000).ConfigureAwait(false)) throw new TimeoutException("Could not obtain a lock to connect. A previous attempt is likely stuck."); @@ -134,8 +143,15 @@ namespace osu.Game.Online /// private async Task handleErrorAndDelay(Exception exception, CancellationToken cancellationToken) { - Logger.Log($"{ClientName} connect attempt failed: {exception.Message}", LoggingTarget.Network); - await Task.Delay(5000, cancellationToken).ConfigureAwait(false); + // random stagger factor to avoid mass incidental synchronisation + // compare: https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/Online/BanchoClient.cs#L331 + int thisDelay = (int)(retryDelay * RNG.NextDouble(0.75, 1.25)); + // exponential backoff with upper limit + // compare: https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/Online/BanchoClient.cs#L539 + retryDelay = Math.Min(120000, (int)(retryDelay * 1.5)); + + Logger.Log($"{ClientName} connect attempt failed: {exception.Message}. Next attempt in {thisDelay / 1000:N0} seconds.", LoggingTarget.Network); + await Task.Delay(thisDelay, cancellationToken).ConfigureAwait(false); } /// From 5bc7befbd4d780c8f3e473865e3679521bbfe1f7 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 6 Feb 2024 23:47:20 +0900 Subject: [PATCH 312/915] Add progressive cover to mania HD and FI mods --- .../Mods/ManiaModFadeIn.cs | 11 +------ .../Mods/ManiaModHidden.cs | 31 +++++++++++++------ .../Mods/ManiaModPlayfieldCover.cs | 2 -- osu.Game/Rulesets/Mods/ModHidden.cs | 4 +-- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs index 196514c7b1..d436f22cdd 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs @@ -3,13 +3,12 @@ using System; using System.Linq; -using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModFadeIn : ManiaModPlayfieldCover + public class ManiaModFadeIn : ManiaModHidden { public override string Name => "Fade In"; public override string Acronym => "FI"; @@ -19,13 +18,5 @@ namespace osu.Game.Rulesets.Mania.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ManiaModHidden)).ToArray(); protected override CoverExpandDirection ExpandDirection => CoverExpandDirection.AlongScroll; - - public override BindableNumber Coverage { get; } = new BindableFloat(0.5f) - { - Precision = 0.1f, - MinValue = 0.1f, - MaxValue = 0.7f, - Default = 0.5f, - }; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index f23cb335a5..7dcd5816a9 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -6,24 +6,37 @@ using System.Linq; using osu.Framework.Localisation; using osu.Game.Rulesets.Mania.UI; using osu.Framework.Bindables; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModHidden : ManiaModPlayfieldCover { + /// + /// osu!stable is referenced to 480px. + /// + private const float playfield_height = 480; + + private const float min_coverage = 160f / playfield_height; + private const float max_coverage = 400f / playfield_height; + private const float coverage_increase_per_combo = 0.5f / playfield_height; + public override LocalisableString Description => @"Keys fade out before you hit them!"; public override double ScoreMultiplier => 1; - - public override BindableNumber Coverage { get; } = new BindableFloat(0.5f) - { - Precision = 0.1f, - MinValue = 0.2f, - MaxValue = 0.8f, - Default = 0.5f, - }; - public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ManiaModFadeIn)).ToArray(); + public override BindableNumber Coverage { get; } = new BindableFloat(min_coverage); protected override CoverExpandDirection ExpandDirection => CoverExpandDirection.AgainstScroll; + + private readonly BindableInt combo = new BindableInt(); + + public override void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + base.ApplyToScoreProcessor(scoreProcessor); + + combo.UnbindAll(); + combo.BindTo(scoreProcessor.Combo); + combo.BindValueChanged(c => Coverage.Value = Math.Min(max_coverage, min_coverage + c.NewValue * coverage_increase_per_combo), true); + } } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs index 18c3ecc073..aadb9b5717 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; @@ -24,7 +23,6 @@ namespace osu.Game.Rulesets.Mania.Mods /// protected abstract CoverExpandDirection ExpandDirection { get; } - [SettingSource("Coverage", "The proportion of playfield height that notes will be hidden for.")] public abstract BindableNumber Coverage { get; } public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 5a1abf115f..2915cb9bea 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -16,11 +16,11 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyIncrease; public override bool Ranked => UsesDefaultConfiguration; - public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + public virtual void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { } - public ScoreRank AdjustRank(ScoreRank rank, double accuracy) + public virtual ScoreRank AdjustRank(ScoreRank rank, double accuracy) { switch (rank) { From bacb1d0dc7cf484a0a6b70f5ecdd0f4ec28bd350 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 6 Feb 2024 23:58:27 +0900 Subject: [PATCH 313/915] Add easing to make the transition less awkward --- .../UI/PlayfieldCoveringWrapper.cs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs index 0956b2f98f..f0ac18d7ca 100644 --- a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs +++ b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.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 osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -8,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Utils; using osu.Game.Rulesets.UI.Scrolling; using osuTK; using osuTK.Graphics; @@ -103,11 +105,20 @@ namespace osu.Game.Rulesets.Mania.UI { base.LoadComplete(); - Coverage.BindValueChanged(c => - { - filled.Height = c.NewValue; - gradient.Y = -c.NewValue; - }, true); + updateHeight(Coverage.Value); + } + + protected override void Update() + { + base.Update(); + + updateHeight((float)Interpolation.DampContinuously(filled.Height, Coverage.Value, 25, Math.Abs(Time.Elapsed))); + } + + private void updateHeight(float height) + { + filled.Height = height; + gradient.Y = -height; } private void onScrollDirectionChanged(ValueChangedEvent direction) From 69db1b2778035b0d02ce94b842f8bedc3b88971c Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 7 Feb 2024 00:15:06 +0900 Subject: [PATCH 314/915] Add ManiaModCover to take over old roles of the mods --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModCover.cs | 44 +++++++++++++++++++ .../Mods/ManiaModFadeIn.cs | 6 ++- .../Mods/ManiaModHidden.cs | 9 +++- ...Cover.cs => ManiaModWithPlayfieldCover.cs} | 5 ++- 5 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Mods/ManiaModCover.cs rename osu.Game.Rulesets.Mania/Mods/{ManiaModPlayfieldCover.cs => ManiaModWithPlayfieldCover.cs} (88%) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c38d6519bd..f19d43826f 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -247,7 +247,7 @@ namespace osu.Game.Rulesets.Mania new ManiaModHardRock(), new MultiMod(new ManiaModSuddenDeath(), new ManiaModPerfect()), new MultiMod(new ManiaModDoubleTime(), new ManiaModNightcore()), - new MultiMod(new ManiaModFadeIn(), new ManiaModHidden()), + new MultiMod(new ManiaModFadeIn(), new ManiaModHidden(), new ManiaModCover()), new ManiaModFlashlight(), new ModAccuracyChallenge(), }; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModCover.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModCover.cs new file mode 100644 index 0000000000..eb243bfab7 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModCover.cs @@ -0,0 +1,44 @@ +// 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.Bindables; +using osu.Framework.Localisation; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModCover : ManiaModWithPlayfieldCover + { + public override string Name => "Cover"; + public override string Acronym => "CO"; + + public override LocalisableString Description => @"Decrease the playfield's viewing area."; + + public override double ScoreMultiplier => 1; + + protected override CoverExpandDirection ExpandDirection => Direction.Value; + + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] + { + typeof(ManiaModHidden), + typeof(ManiaModFadeIn) + }).ToArray(); + + public override bool Ranked => false; + + [SettingSource("Coverage", "The proportion of playfield height that notes will be hidden for.")] + public override BindableNumber Coverage { get; } = new BindableFloat(0.5f) + { + Precision = 0.1f, + MinValue = 0.2f, + MaxValue = 0.8f, + Default = 0.5f, + }; + + [SettingSource("Direction", "The direction on which the cover is applied")] + public Bindable Direction { get; } = new Bindable(); + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs index d436f22cdd..54a0b8f36d 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs @@ -15,7 +15,11 @@ namespace osu.Game.Rulesets.Mania.Mods public override LocalisableString Description => @"Keys appear out of nowhere!"; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ManiaModHidden)).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] + { + typeof(ManiaModHidden), + typeof(ManiaModCover) + }).ToArray(); protected override CoverExpandDirection ExpandDirection => CoverExpandDirection.AlongScroll; } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index 7dcd5816a9..f4d5386d70 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModHidden : ManiaModPlayfieldCover + public class ManiaModHidden : ManiaModWithPlayfieldCover { /// /// osu!stable is referenced to 480px. @@ -23,7 +23,12 @@ namespace osu.Game.Rulesets.Mania.Mods public override LocalisableString Description => @"Keys fade out before you hit them!"; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ManiaModFadeIn)).ToArray(); + + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] + { + typeof(ManiaModFadeIn), + typeof(ManiaModCover) + }).ToArray(); public override BindableNumber Coverage { get; } = new BindableFloat(min_coverage); protected override CoverExpandDirection ExpandDirection => CoverExpandDirection.AgainstScroll; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModWithPlayfieldCover.cs similarity index 88% rename from osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs rename to osu.Game.Rulesets.Mania/Mods/ManiaModWithPlayfieldCover.cs index aadb9b5717..bb5807269a 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModWithPlayfieldCover.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.Mods { - public abstract class ManiaModPlayfieldCover : ModHidden, IApplicableToDrawableRuleset + public abstract class ManiaModWithPlayfieldCover : ModHidden, IApplicableToDrawableRuleset { public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) }; @@ -23,6 +23,9 @@ namespace osu.Game.Rulesets.Mania.Mods /// protected abstract CoverExpandDirection ExpandDirection { get; } + /// + /// The relative area that should be completely covered. This does not include the fade. + /// public abstract BindableNumber Coverage { get; } public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) From af20eacc82747661f2408b4540d221814ea5e1d8 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 7 Feb 2024 00:25:22 +0900 Subject: [PATCH 315/915] Fix coordinate space --- osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index f4d5386d70..9def29f82b 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -13,9 +13,9 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModHidden : ManiaModWithPlayfieldCover { /// - /// osu!stable is referenced to 480px. + /// osu!stable is referenced to 768px. /// - private const float playfield_height = 480; + private const float playfield_height = 768; private const float min_coverage = 160f / playfield_height; private const float max_coverage = 400f / playfield_height; From 9314de640fe6f34f41d5aab45be148d7c0af4a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Feb 2024 18:30:48 +0100 Subject: [PATCH 316/915] Populate `TotalScoreInfo` when converting `SoloScoreInfo` to `ScoreInfo` For use in https://github.com/ppy/osu-tools/pull/195. --- osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs index 732da3d5da..e4ae83ca74 100644 --- a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs @@ -203,6 +203,7 @@ namespace osu.Game.Online.API.Requests.Responses Ruleset = new RulesetInfo { OnlineID = RulesetID }, Passed = Passed, TotalScore = TotalScore, + LegacyTotalScore = LegacyTotalScore, Accuracy = Accuracy, MaxCombo = MaxCombo, Rank = Rank, From ff7cd67909d72c520ec2aabaf7ac96083d812cd3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 6 Feb 2024 21:14:36 +0300 Subject: [PATCH 317/915] Move all the circles into their own container --- .../Expanded/Accuracy/GradedCircles.cs | 66 +++++++++---------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs index 57b6d8e4ac..33b71c53a7 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs @@ -20,49 +20,45 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy set { progress = value; - dProgress.RevealProgress = value; - cProgress.RevealProgress = value; - bProgress.RevealProgress = value; - aProgress.RevealProgress = value; - sProgress.RevealProgress = value; - xProgress.RevealProgress = value; + + foreach (var circle in circles) + circle.RevealProgress = value; } } - private readonly GradedCircle dProgress; - private readonly GradedCircle cProgress; - private readonly GradedCircle bProgress; - private readonly GradedCircle aProgress; - private readonly GradedCircle sProgress; - private readonly GradedCircle xProgress; + private readonly Container circles; public GradedCircles(double accuracyC, double accuracyB, double accuracyA, double accuracyS, double accuracyX) { - InternalChildren = new Drawable[] + InternalChild = circles = new Container { - dProgress = new GradedCircle(0.0, accuracyC) + RelativeSizeAxes = Axes.Both, + Children = new[] { - Colour = OsuColour.ForRank(ScoreRank.D), - }, - cProgress = new GradedCircle(accuracyC, accuracyB) - { - Colour = OsuColour.ForRank(ScoreRank.C), - }, - bProgress = new GradedCircle(accuracyB, accuracyA) - { - Colour = OsuColour.ForRank(ScoreRank.B), - }, - aProgress = new GradedCircle(accuracyA, accuracyS) - { - Colour = OsuColour.ForRank(ScoreRank.A), - }, - sProgress = new GradedCircle(accuracyS, accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE) - { - Colour = OsuColour.ForRank(ScoreRank.S), - }, - xProgress = new GradedCircle(accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE, 1.0) - { - Colour = OsuColour.ForRank(ScoreRank.X) + new GradedCircle(0.0, accuracyC) + { + Colour = OsuColour.ForRank(ScoreRank.D), + }, + new GradedCircle(accuracyC, accuracyB) + { + Colour = OsuColour.ForRank(ScoreRank.C), + }, + new GradedCircle(accuracyB, accuracyA) + { + Colour = OsuColour.ForRank(ScoreRank.B), + }, + new GradedCircle(accuracyA, accuracyS) + { + Colour = OsuColour.ForRank(ScoreRank.A), + }, + new GradedCircle(accuracyS, accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE) + { + Colour = OsuColour.ForRank(ScoreRank.S), + }, + new GradedCircle(accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE, 1.0) + { + Colour = OsuColour.ForRank(ScoreRank.X) + } } }; } From 44b1515cc5395486963615d238f2f77c16b5888c Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 7 Feb 2024 03:28:40 +0900 Subject: [PATCH 318/915] Remove LangVersion redefintions --- osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 1 - osu.Game/osu.Game.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 518ab362ca..7817d55f57 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -4,7 +4,6 @@ Library true click the circles. to the beat. - 10 diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 935b759e4d..9bcdebc347 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -3,7 +3,6 @@ net8.0 Library true - 10 osu! From 9b8f2064867472009e3c5c621c1fbf5823ad7592 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 7 Feb 2024 03:38:07 +0900 Subject: [PATCH 319/915] Enable NRT for DrawableHitCircle to clean up --- .../Objects/Drawables/DrawableHitCircle.cs | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 3727e78d01..b950ef4bbb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -1,12 +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 disable - using System; using System.Collections.Generic; using System.Diagnostics; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -27,34 +24,30 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public partial class DrawableHitCircle : DrawableOsuHitObject, IHasApproachCircle { - public OsuAction? HitAction => HitArea?.HitAction; + public OsuAction? HitAction => HitArea.HitAction; protected virtual OsuSkinComponents CirclePieceComponent => OsuSkinComponents.HitCircle; - public SkinnableDrawable ApproachCircle { get; private set; } - public HitReceptor HitArea { get; private set; } - public SkinnableDrawable CirclePiece { get; private set; } + public SkinnableDrawable ApproachCircle { get; private set; } = null!; + public HitReceptor HitArea { get; private set; } = null!; + public SkinnableDrawable CirclePiece { get; private set; } = null!; - protected override IEnumerable DimmablePieces => new[] - { - CirclePiece, - }; + protected override IEnumerable DimmablePieces => new[] { CirclePiece }; Drawable IHasApproachCircle.ApproachCircle => ApproachCircle; - private Container scaleContainer; + private Container scaleContainer = null!; + private ShakeContainer shakeContainer = null!; public DrawableHitCircle() : this(null) { } - public DrawableHitCircle([CanBeNull] HitCircle h = null) + public DrawableHitCircle(HitCircle? h = null) : base(h) { } - private ShakeContainer shakeContainer; - [BackgroundDependencyLoader] private void load() { @@ -219,8 +212,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; case ArmedState.Idle: - HitArea.ClosestPressPosition = null; - HitArea.HitAction = null; + HitArea.Reset(); break; case ArmedState.Miss: @@ -240,11 +232,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // IsHovered is used public override bool HandlePositionalInput => true; - public Func CanBeHit; - public Action Hit; + public required Func CanBeHit { get; set; } + public required Action Hit { get; set; } - public OsuAction? HitAction; - public Vector2? ClosestPressPosition; + public OsuAction? HitAction { get; private set; } + public Vector2? ClosestPressPosition { get; private set; } public HitReceptor() { @@ -259,7 +251,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public bool OnPressed(KeyBindingPressEvent e) { - if (!(CanBeHit?.Invoke() ?? false)) + if (CanBeHit()) return false; switch (e.Action) @@ -283,7 +275,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (IsHovered) { - Hit?.Invoke(); + Hit(); HitAction ??= e.Action; return true; } @@ -297,13 +289,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public void OnReleased(KeyBindingReleaseEvent e) { } + + public void Reset() + { + HitAction = null; + ClosestPressPosition = null; + } } private partial class ProxyableSkinnableDrawable : SkinnableDrawable { public override bool RemoveWhenNotAlive => false; - public ProxyableSkinnableDrawable(ISkinComponentLookup lookup, Func defaultImplementation = null, ConfineMode confineMode = ConfineMode.NoScaling) + public ProxyableSkinnableDrawable(ISkinComponentLookup lookup, Func? defaultImplementation = null, ConfineMode confineMode = ConfineMode.NoScaling) : base(lookup, defaultImplementation, confineMode) { } From 38f7913b31bbc64f99882668b7d8cb89de4d51fd Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 7 Feb 2024 03:50:56 +0900 Subject: [PATCH 320/915] Fix inverted condition --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index b950ef4bbb..c9f2983b1e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -251,7 +251,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public bool OnPressed(KeyBindingPressEvent e) { - if (CanBeHit()) + if (!CanBeHit()) return false; switch (e.Action) From 2fc06f16b50c0112522b3c2f164de6aa2aa36608 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 7 Feb 2024 03:51:28 +0900 Subject: [PATCH 321/915] Fix inspections --- osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index c624fbbe73..9d79cb0db4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -91,11 +91,11 @@ namespace osu.Game.Rulesets.Osu.Tests var skinnable = firstObject.ApproachCircle; - if (skin == null && skinnable?.Drawable is DefaultApproachCircle) + if (skin == null && skinnable.Drawable is DefaultApproachCircle) // check for default skin provider return true; - var text = skinnable?.Drawable as SpriteText; + var text = skinnable.Drawable as SpriteText; return text?.Text == skin; }); From e2867986c591f042b63c6da36e1f27d40cb89341 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 7 Feb 2024 03:47:36 +0900 Subject: [PATCH 322/915] Add xmldocs --- .../Objects/Drawables/DrawableHitCircle.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index c9f2983b1e..f7237d4c03 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -232,10 +232,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // IsHovered is used public override bool HandlePositionalInput => true; + /// + /// Whether the hitobject can still be hit at the current point in time. + /// public required Func CanBeHit { get; set; } + + /// + /// An action that's invoked to perform the hit. + /// public required Action Hit { get; set; } + /// + /// The with which the hit was attempted. + /// public OsuAction? HitAction { get; private set; } + + /// + /// The closest position to the hit receptor at the point where the hit was attempted. + /// public Vector2? ClosestPressPosition { get; private set; } public HitReceptor() @@ -290,6 +304,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { } + /// + /// Resets to a fresh state. + /// public void Reset() { HitAction = null; From 1f13124b3834b846281c5d63acc65275c356258e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 7 Feb 2024 03:52:51 +0900 Subject: [PATCH 323/915] Always process position as long as it's hittable For example... If a hitobject is pressed but the result is a shake, this will stop processing hits. --- .../Objects/Drawables/DrawableHitCircle.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index f7237d4c03..c3ce6acce9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -272,20 +272,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { case OsuAction.LeftButton: case OsuAction.RightButton: - // Only update closest press position while the object hasn't been hit yet. - if (HitAction == null) + if (ClosestPressPosition is Vector2 curClosest) { - if (ClosestPressPosition is Vector2 curClosest) - { - float oldDist = Vector2.DistanceSquared(curClosest, ScreenSpaceDrawQuad.Centre); - float newDist = Vector2.DistanceSquared(e.ScreenSpaceMousePosition, ScreenSpaceDrawQuad.Centre); + float oldDist = Vector2.DistanceSquared(curClosest, ScreenSpaceDrawQuad.Centre); + float newDist = Vector2.DistanceSquared(e.ScreenSpaceMousePosition, ScreenSpaceDrawQuad.Centre); - if (newDist < oldDist) - ClosestPressPosition = e.ScreenSpaceMousePosition; - } - else + if (newDist < oldDist) ClosestPressPosition = e.ScreenSpaceMousePosition; } + else + ClosestPressPosition = e.ScreenSpaceMousePosition; if (IsHovered) { From 8f59cb7659d2fddaaa588417c9c534bee6cc5ebd Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 6 Feb 2024 12:54:53 -0800 Subject: [PATCH 324/915] Hide ruleset selector when on kudosu ranking --- osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index a23ec18afe..1c743ff152 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -39,5 +39,15 @@ namespace osu.Game.Overlays.Rankings Icon = OsuIcon.Ranking; } } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(scope => + { + rulesetSelector.FadeTo(scope.NewValue <= RankingsScope.Country ? 1 : 0, 200, Easing.OutQuint); + }); + } } } From 21e5ae5ba975aa072e0246196971ebd347aa05a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Feb 2024 16:43:53 +0800 Subject: [PATCH 325/915] Minor adjustments --- .../Rankings/RankingsOverlayHeader.cs | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 1c743ff152..cf132ed4da 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -1,13 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Bindables; -using osu.Game.Localisation; -using osu.Game.Resources.Localisation.Web; using osu.Framework.Graphics; using osu.Game.Graphics; +using osu.Game.Localisation; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Users; @@ -19,8 +17,8 @@ namespace osu.Game.Overlays.Rankings public Bindable Country => countryFilter.Current; - private OverlayRulesetSelector rulesetSelector; - private CountryFilter countryFilter; + private OverlayRulesetSelector rulesetSelector = null!; + private CountryFilter countryFilter = null!; protected override OverlayTitle CreateTitle() => new RankingsTitle(); @@ -46,8 +44,23 @@ namespace osu.Game.Overlays.Rankings Current.BindValueChanged(scope => { - rulesetSelector.FadeTo(scope.NewValue <= RankingsScope.Country ? 1 : 0, 200, Easing.OutQuint); - }); + rulesetSelector.FadeTo(showRulesetSelector(scope.NewValue) ? 1 : 0, 200, Easing.OutQuint); + }, true); + + bool showRulesetSelector(RankingsScope scope) + { + switch (scope) + { + case RankingsScope.Performance: + case RankingsScope.Spotlights: + case RankingsScope.Score: + case RankingsScope.Country: + return true; + + default: + return false; + } + } } } } From 9a3c947319c93e19299424a40b9aa982dffe11c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Feb 2024 13:35:12 +0100 Subject: [PATCH 326/915] Remove unnecessary `#nullable disable` --- .../Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs index 4c44def1ee..025977e745 100644 --- a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs +++ b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.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. -#nullable disable using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; From f22828bc50db359957c13abceee296ac7b3b95fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Feb 2024 13:36:46 +0100 Subject: [PATCH 327/915] Flip `if`s to reduce nesting --- .../Sections/Ranks/DrawableProfileScore.cs | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index c7d7af0bd7..d1988956be 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -213,22 +213,36 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks private Drawable createDrawablePerformance() { - if (!Score.PP.HasValue) + if (Score.PP.HasValue) { - if (Score.Beatmap?.Status.GrantsPerformancePoints() == true) + return new FillFlowContainer { - if (!Score.Ranked) + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] { - return new UnrankedPerformancePointsPlaceholder + new OsuSpriteText { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(weight: FontWeight.Bold), + Text = $"{Score.PP:0}", Colour = colourProvider.Highlight1 - }; + }, + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = "pp", + Colour = colourProvider.Light3 + } } + }; + } - return new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(16), Colour = colourProvider.Highlight1 }; - } - + if (Score.Beatmap?.Status.GrantsPerformancePoints() != true) + { return new OsuSpriteText { Font = OsuFont.GetFont(weight: FontWeight.Bold), @@ -237,30 +251,16 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks }; } - return new FillFlowContainer + if (!Score.Ranked) { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] + return new UnrankedPerformancePointsPlaceholder { - new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(weight: FontWeight.Bold), - Text = $"{Score.PP:0}", - Colour = colourProvider.Highlight1 - }, - new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), - Text = "pp", - Colour = colourProvider.Light3 - } - } - }; + Font = OsuFont.GetFont(weight: FontWeight.Bold), + Colour = colourProvider.Highlight1 + }; + } + + return new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(16), Colour = colourProvider.Highlight1 }; } private partial class ScoreBeatmapMetadataContainer : BeatmapMetadataContainer From 3f51148719918f0b5d8d91b1575a87319d21a3b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Feb 2024 13:37:37 +0100 Subject: [PATCH 328/915] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 935b759e4d..db41b04e44 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From 706a16677c1e86b921301d8d499487c7b954c354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Feb 2024 13:38:05 +0100 Subject: [PATCH 329/915] Use localised string --- .../Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs index 025977e745..c5c190e1a1 100644 --- a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs +++ b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Scoring.Drawables { @@ -13,7 +14,7 @@ namespace osu.Game.Scoring.Drawables /// public partial class UnrankedPerformancePointsPlaceholder : SpriteText, IHasTooltip { - public LocalisableString TooltipText => "pp is not awarded for this score"; // todo: replace with localised string ScoresStrings.StatusNoPp. + public LocalisableString TooltipText => ScoresStrings.StatusNoPp; public UnrankedPerformancePointsPlaceholder() { From 8f995a30af27f3cd90df67d1c45e434e028daf5d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 8 Feb 2024 00:20:32 +0900 Subject: [PATCH 330/915] Fix legacy coverage metrics --- .../Mods/ManiaModHidden.cs | 29 +++++++++++++++---- .../Mods/ManiaModWithPlayfieldCover.cs | 4 ++- .../UI/PlayfieldCoveringWrapper.cs | 14 ++++++--- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index 9def29f82b..211f21513d 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -6,20 +6,21 @@ using System.Linq; using osu.Framework.Localisation; using osu.Game.Rulesets.Mania.UI; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModHidden : ManiaModWithPlayfieldCover + public partial class ManiaModHidden : ManiaModWithPlayfieldCover { /// /// osu!stable is referenced to 768px. /// - private const float playfield_height = 768; + private const float reference_playfield_height = 768; - private const float min_coverage = 160f / playfield_height; - private const float max_coverage = 400f / playfield_height; - private const float coverage_increase_per_combo = 0.5f / playfield_height; + private const float min_coverage = 160 / reference_playfield_height; + private const float max_coverage = 400f / reference_playfield_height; + private const float coverage_increase_per_combo = 0.5f / reference_playfield_height; public override LocalisableString Description => @"Keys fade out before you hit them!"; public override double ScoreMultiplier => 1; @@ -43,5 +44,23 @@ namespace osu.Game.Rulesets.Mania.Mods combo.BindTo(scoreProcessor.Combo); combo.BindValueChanged(c => Coverage.Value = Math.Min(max_coverage, min_coverage + c.NewValue * coverage_increase_per_combo), true); } + + protected override PlayfieldCoveringWrapper CreateCover(Drawable content) => new LegacyPlayfieldCover(content); + + private partial class LegacyPlayfieldCover : PlayfieldCoveringWrapper + { + public LegacyPlayfieldCover(Drawable content) + : base(content) + { + } + + protected override float GetHeight(float coverage) + { + if (DrawHeight == 0) + return base.GetHeight(coverage); + + return base.GetHeight(coverage) * reference_playfield_height / DrawHeight; + } + } } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModWithPlayfieldCover.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModWithPlayfieldCover.cs index bb5807269a..864ef6c3d6 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModWithPlayfieldCover.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModWithPlayfieldCover.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Mods Container hocParent = (Container)hoc.Parent!; hocParent.Remove(hoc, false); - hocParent.Add(new PlayfieldCoveringWrapper(hoc).With(c => + hocParent.Add(CreateCover(hoc).With(c => { c.RelativeSizeAxes = Axes.Both; c.Direction = ExpandDirection; @@ -47,6 +47,8 @@ namespace osu.Game.Rulesets.Mania.Mods } } + protected virtual PlayfieldCoveringWrapper CreateCover(Drawable content) => new PlayfieldCoveringWrapper(content); + protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { } diff --git a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs index f0ac18d7ca..2b70c527ae 100644 --- a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs +++ b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs @@ -43,6 +43,8 @@ namespace osu.Game.Rulesets.Mania.UI private readonly IBindable scrollDirection = new Bindable(); + private float currentCoverage; + public PlayfieldCoveringWrapper(Drawable content) { InternalChild = new BufferedContainer @@ -112,15 +114,19 @@ namespace osu.Game.Rulesets.Mania.UI { base.Update(); - updateHeight((float)Interpolation.DampContinuously(filled.Height, Coverage.Value, 25, Math.Abs(Time.Elapsed))); + updateHeight((float)Interpolation.DampContinuously(currentCoverage, Coverage.Value, 25, Math.Abs(Time.Elapsed))); } - private void updateHeight(float height) + private void updateHeight(float coverage) { - filled.Height = height; - gradient.Y = -height; + filled.Height = GetHeight(coverage); + gradient.Y = -GetHeight(coverage); + + currentCoverage = coverage; } + protected virtual float GetHeight(float coverage) => coverage; + private void onScrollDirectionChanged(ValueChangedEvent direction) => cover.Rotation = direction.NewValue == ScrollingDirection.Up ? 0 : 180f; From 0d7e82ab8df41e6950d97c1fa67e28389ca699d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Feb 2024 00:20:53 +0800 Subject: [PATCH 331/915] Improve exception logging of unobserved exceptions via `FireAndForget` Coming from https://github.com/ppy/osu/issues/27076, where the log output makes finding where the exception arrived for nigh impossible. --- osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs b/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs index 2083aa4e28..d846e7f566 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs @@ -23,9 +23,12 @@ namespace osu.Game.Online.Multiplayer Debug.Assert(exception != null); - string message = exception.GetHubExceptionMessage() ?? exception.Message; + if (exception.GetHubExceptionMessage() is string message) + // Hub exceptions generally contain something we can show the user directly. + Logger.Log(message, level: LogLevel.Important); + else + Logger.Error(exception, $"Unobserved exception occurred via {nameof(FireAndForget)} call: {exception.Message}"); - Logger.Log(message, level: LogLevel.Important); onError?.Invoke(exception); } else From dcb195f3c813c72d2bd694d1488e0c37c67f1764 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 8 Feb 2024 02:16:08 +0900 Subject: [PATCH 332/915] Add delayed resume for taiko/catch/mania --- .../UI/DrawableCatchRuleset.cs | 3 ++ .../UI/DrawableManiaRuleset.cs | 3 ++ .../UI/DrawableTaikoRuleset.cs | 3 ++ osu.Game/Screens/Play/DelayedResumeOverlay.cs | 32 +++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 osu.Game/Screens/Play/DelayedResumeOverlay.cs diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index f0a327d7ac..580c90bcb4 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -16,6 +16,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Scoring; +using osu.Game.Screens.Play; namespace osu.Game.Rulesets.Catch.UI { @@ -52,5 +53,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); public override DrawableHitObject? CreateDrawableRepresentation(CatchHitObject h) => null; + + protected override ResumeOverlay CreateResumeOverlay() => new DelayedResumeOverlay(); } } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index decf670c5d..275b1311de 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -26,6 +26,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.UI @@ -164,6 +165,8 @@ namespace osu.Game.Rulesets.Mania.UI protected override ReplayRecorder CreateReplayRecorder(Score score) => new ManiaReplayRecorder(score); + protected override ResumeOverlay CreateResumeOverlay() => new DelayedResumeOverlay(); + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 77b2b06c0e..cd9ed399e6 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -22,6 +22,7 @@ using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osu.Game.Skinning; using osuTK; @@ -101,5 +102,7 @@ namespace osu.Game.Rulesets.Taiko.UI protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new TaikoFramedReplayInputHandler(replay); protected override ReplayRecorder CreateReplayRecorder(Score score) => new TaikoReplayRecorder(score); + + protected override ResumeOverlay CreateResumeOverlay() => new DelayedResumeOverlay(); } } diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs new file mode 100644 index 0000000000..ef39c8eb76 --- /dev/null +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.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 osu.Framework.Localisation; +using osu.Framework.Threading; + +namespace osu.Game.Screens.Play +{ + /// + /// Simple that resumes after 800ms. + /// + public partial class DelayedResumeOverlay : ResumeOverlay + { + protected override LocalisableString Message => string.Empty; + + private ScheduledDelegate? scheduledResume; + + protected override void PopIn() + { + base.PopIn(); + + scheduledResume?.Cancel(); + scheduledResume = Scheduler.AddDelayed(Resume, 800); + } + + protected override void PopOut() + { + base.PopOut(); + scheduledResume?.Cancel(); + } + } +} From 57d5717e6a6d4fb4007e6f42aa7bca525ea176e6 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 21:33:23 +0100 Subject: [PATCH 333/915] Remove `Win32Icon` class and use plain strings instead --- osu.Desktop/Windows/Icons.cs | 9 ++++++++- osu.Desktop/Windows/Win32Icon.cs | 16 ---------------- osu.Desktop/Windows/WindowsAssociationManager.cs | 8 ++++---- 3 files changed, 12 insertions(+), 21 deletions(-) delete mode 100644 osu.Desktop/Windows/Win32Icon.cs diff --git a/osu.Desktop/Windows/Icons.cs b/osu.Desktop/Windows/Icons.cs index cc60f92810..67915c101a 100644 --- a/osu.Desktop/Windows/Icons.cs +++ b/osu.Desktop/Windows/Icons.cs @@ -1,10 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.IO; + namespace osu.Desktop.Windows { public static class Icons { - public static Win32Icon Lazer => new Win32Icon(@"lazer.ico"); + /// + /// Fully qualified path to the directory that contains icons (in the installation folder). + /// + private static readonly string icon_directory = Path.GetDirectoryName(typeof(Icons).Assembly.Location)!; + + public static string Lazer => Path.Join(icon_directory, "lazer.ico"); } } diff --git a/osu.Desktop/Windows/Win32Icon.cs b/osu.Desktop/Windows/Win32Icon.cs deleted file mode 100644 index 401e7a2be3..0000000000 --- a/osu.Desktop/Windows/Win32Icon.cs +++ /dev/null @@ -1,16 +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.Desktop.Windows -{ - public class Win32Icon - { - public readonly string Path; - - internal Win32Icon(string name) - { - string dir = System.IO.Path.GetDirectoryName(typeof(Win32Icon).Assembly.Location)!; - Path = System.IO.Path.Join(dir, name); - } - } -} diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 7131067224..a93161ae47 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -173,7 +173,7 @@ namespace osu.Desktop.Windows #endregion - private record FileAssociation(string Extension, LocalisableString Description, Win32Icon Icon) + private record FileAssociation(string Extension, LocalisableString Description, string IconPath) { private string getProgramId(string prefix) => $@"{prefix}.File{Extension}"; @@ -188,7 +188,7 @@ namespace osu.Desktop.Windows using (var programKey = classes.CreateSubKey(programId)) { using (var defaultIconKey = programKey.CreateSubKey(DEFAULT_ICON)) - defaultIconKey.SetValue(null, Icon.Path); + defaultIconKey.SetValue(null, IconPath); using (var openCommandKey = programKey.CreateSubKey(SHELL_OPEN_COMMAND)) openCommandKey.SetValue(null, $@"""{exePath}"" ""%1"""); @@ -225,7 +225,7 @@ namespace osu.Desktop.Windows } } - private record UriAssociation(string Protocol, LocalisableString Description, Win32Icon Icon) + private record UriAssociation(string Protocol, LocalisableString Description, string IconPath) { /// /// "The URL Protocol string value indicates that this key declares a custom pluggable protocol handler." @@ -243,7 +243,7 @@ namespace osu.Desktop.Windows protocolKey.SetValue(URL_PROTOCOL, string.Empty); using (var defaultIconKey = protocolKey.CreateSubKey(DEFAULT_ICON)) - defaultIconKey.SetValue(null, Icon.Path); + defaultIconKey.SetValue(null, IconPath); using (var openCommandKey = protocolKey.CreateSubKey(SHELL_OPEN_COMMAND)) openCommandKey.SetValue(null, $@"""{exePath}"" ""%1"""); From eeba93768641b05a470aa1e8ebe18389596f5d49 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 21:45:36 +0100 Subject: [PATCH 334/915] Make `WindowsAssociationManager` `static` Usages/localisation logic TBD --- osu.Desktop/Program.cs | 2 +- .../Windows/WindowsAssociationManager.cs | 57 ++++++------------- 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index edbf39a30a..38e4110f62 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -181,7 +181,7 @@ namespace osu.Desktop { tools.RemoveShortcutForThisExe(); tools.RemoveUninstallerRegistryEntry(); - WindowsAssociationManager.UninstallAssociations(@"osu"); + WindowsAssociationManager.UninstallAssociations(); }, onEveryRun: (_, _, _) => { // While setting the `ProcessAppUserModelId` fixes duplicate icons/shortcuts on the taskbar, it currently diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index a93161ae47..f1fc98090f 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -6,9 +6,6 @@ using System.IO; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Microsoft.Win32; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Localisation; @@ -16,7 +13,7 @@ using osu.Game.Localisation; namespace osu.Desktop.Windows { [SupportedOSPlatform("windows")] - public partial class WindowsAssociationManager : Component + public static class WindowsAssociationManager { public const string SOFTWARE_CLASSES = @"Software\Classes"; @@ -54,25 +51,7 @@ namespace osu.Desktop.Windows new UriAssociation(@"osump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer), }; - [Resolved] - private LocalisationManager localisation { get; set; } = null!; - - private IBindable localisationParameters = null!; - - [BackgroundDependencyLoader] - private void load() - { - localisationParameters = localisation.CurrentParameters.GetBoundCopy(); - InstallAssociations(); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - localisationParameters.ValueChanged += _ => updateDescriptions(); - } - - public void InstallAssociations() + public static void InstallAssociations(LocalisationManager? localisation) { try { @@ -88,7 +67,7 @@ namespace osu.Desktop.Windows association.Install(classes, EXE_PATH); } - updateDescriptions(); + updateDescriptions(localisation); } catch (Exception e) { @@ -96,7 +75,7 @@ namespace osu.Desktop.Windows } } - private void updateDescriptions() + private static void updateDescriptions(LocalisationManager? localisation) { try { @@ -105,18 +84,10 @@ namespace osu.Desktop.Windows return; foreach (var association in file_associations) - { - var b = localisation.GetLocalisedBindableString(association.Description); - association.UpdateDescription(classes, PROGRAM_ID_PREFIX, b.Value); - b.UnbindAll(); - } + association.UpdateDescription(classes, PROGRAM_ID_PREFIX, getLocalisedString(association.Description)); foreach (var association in uri_associations) - { - var b = localisation.GetLocalisedBindableString(association.Description); - association.UpdateDescription(classes, b.Value); - b.UnbindAll(); - } + association.UpdateDescription(classes, getLocalisedString(association.Description)); NotifyShellUpdate(); } @@ -124,11 +95,19 @@ namespace osu.Desktop.Windows { Logger.Log($@"Failed to update file and URI associations: {e.Message}"); } + + string getLocalisedString(LocalisableString s) + { + if (localisation == null) + return s.ToString(); + + var b = localisation.GetLocalisedBindableString(s); + b.UnbindAll(); + return b.Value; + } } - public void UninstallAssociations() => UninstallAssociations(PROGRAM_ID_PREFIX); - - public static void UninstallAssociations(string programIdPrefix) + public static void UninstallAssociations() { try { @@ -137,7 +116,7 @@ namespace osu.Desktop.Windows return; foreach (var association in file_associations) - association.Uninstall(classes, programIdPrefix); + association.Uninstall(classes, PROGRAM_ID_PREFIX); foreach (var association in uri_associations) association.Uninstall(classes); From f9d257b99ea176222671aa4594ec78c01f157db7 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 21:56:39 +0100 Subject: [PATCH 335/915] Install associations as part of initial squirrel install --- osu.Desktop/OsuGameDesktop.cs | 3 --- osu.Desktop/Program.cs | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 2e1b34fb38..a0db896f46 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -137,9 +137,6 @@ namespace osu.Desktop if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows) LoadComponentAsync(new GameplayWinKeyBlocker(), Add); - if (OperatingSystem.IsWindows() && IsDeployedBuild) - LoadComponentAsync(new WindowsAssociationManager(), Add); - LoadComponentAsync(new ElevatedPrivilegesChecker(), Add); osuSchemeLinkIPCChannel = new OsuSchemeLinkIPCChannel(Host, this); diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 38e4110f62..65236940c6 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -174,6 +174,7 @@ namespace osu.Desktop { tools.CreateShortcutForThisExe(); tools.CreateUninstallerRegistryEntry(); + WindowsAssociationManager.InstallAssociations(null); }, onAppUpdate: (_, tools) => { tools.CreateUninstallerRegistryEntry(); From 0563507295dcf68c150cfc99949964d521f98b0e Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:03:16 +0100 Subject: [PATCH 336/915] Remove duplicate try-catch and move `NotifyShellUpdate()` to less hidden place --- .../Windows/WindowsAssociationManager.cs | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index f1fc98090f..c91ab459d6 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -68,6 +68,7 @@ namespace osu.Desktop.Windows } updateDescriptions(localisation); + NotifyShellUpdate(); } catch (Exception e) { @@ -77,24 +78,15 @@ namespace osu.Desktop.Windows private static void updateDescriptions(LocalisationManager? localisation) { - try - { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); - if (classes == null) - return; + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) + return; - foreach (var association in file_associations) - association.UpdateDescription(classes, PROGRAM_ID_PREFIX, getLocalisedString(association.Description)); + foreach (var association in file_associations) + association.UpdateDescription(classes, PROGRAM_ID_PREFIX, getLocalisedString(association.Description)); - foreach (var association in uri_associations) - association.UpdateDescription(classes, getLocalisedString(association.Description)); - - NotifyShellUpdate(); - } - catch (Exception e) - { - Logger.Log($@"Failed to update file and URI associations: {e.Message}"); - } + foreach (var association in uri_associations) + association.UpdateDescription(classes, getLocalisedString(association.Description)); string getLocalisedString(LocalisableString s) { From 6bdb07602794d7eb59e7356f9fa5a04188652ff2 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:06:09 +0100 Subject: [PATCH 337/915] Move update/install logic into helper --- .../Windows/WindowsAssociationManager.cs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index c91ab459d6..3d61ad534b 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -55,18 +55,7 @@ namespace osu.Desktop.Windows { try { - using (var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, writable: true)) - { - if (classes == null) - return; - - foreach (var association in file_associations) - association.Install(classes, EXE_PATH, PROGRAM_ID_PREFIX); - - foreach (var association in uri_associations) - association.Install(classes, EXE_PATH); - } - + updateAssociations(); updateDescriptions(localisation); NotifyShellUpdate(); } @@ -76,6 +65,24 @@ namespace osu.Desktop.Windows } } + /// + /// Installs or updates associations. + /// + private static void updateAssociations() + { + using (var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, writable: true)) + { + if (classes == null) + return; + + foreach (var association in file_associations) + association.Install(classes, EXE_PATH, PROGRAM_ID_PREFIX); + + foreach (var association in uri_associations) + association.Install(classes, EXE_PATH); + } + } + private static void updateDescriptions(LocalisationManager? localisation) { using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); From 738c28755c53fd587d7ecee0cc6e8365c6aa8a44 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:17:13 +0100 Subject: [PATCH 338/915] Refactor public methods --- osu.Desktop/Program.cs | 3 +- .../Windows/WindowsAssociationManager.cs | 42 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 65236940c6..494d0df3c6 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -174,10 +174,11 @@ namespace osu.Desktop { tools.CreateShortcutForThisExe(); tools.CreateUninstallerRegistryEntry(); - WindowsAssociationManager.InstallAssociations(null); + WindowsAssociationManager.InstallAssociations(); }, onAppUpdate: (_, tools) => { tools.CreateUninstallerRegistryEntry(); + WindowsAssociationManager.UpdateAssociations(); }, onAppUninstall: (_, tools) => { tools.RemoveShortcutForThisExe(); diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 3d61ad534b..18a3c2da3d 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -51,12 +51,18 @@ namespace osu.Desktop.Windows new UriAssociation(@"osump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer), }; - public static void InstallAssociations(LocalisationManager? localisation) + /// + /// Installs file and URI associations. + /// + /// + /// Call in a timely fashion to keep descriptions up-to-date and localised. + /// + public static void InstallAssociations() { try { updateAssociations(); - updateDescriptions(localisation); + updateDescriptions(null); // write default descriptions in case `UpdateDescriptions()` is not called. NotifyShellUpdate(); } catch (Exception e) @@ -65,6 +71,38 @@ namespace osu.Desktop.Windows } } + /// + /// Updates associations with latest definitions. + /// + /// + /// Call in a timely fashion to keep descriptions up-to-date and localised. + /// + public static void UpdateAssociations() + { + try + { + updateAssociations(); + NotifyShellUpdate(); + } + catch (Exception e) + { + Logger.Log(@$"Failed to update file and URI associations: {e.Message}"); + } + } + + public static void UpdateDescriptions(LocalisationManager localisationManager) + { + try + { + updateDescriptions(localisationManager); + NotifyShellUpdate(); + } + catch (Exception e) + { + Logger.Log(@$"Failed to update file and URI association descriptions: {e.Message}"); + } + } + /// /// Installs or updates associations. /// From ffdefbc742fa1948d1e9356b438adbf319221bd3 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:18:12 +0100 Subject: [PATCH 339/915] Move public methods closer together --- .../Windows/WindowsAssociationManager.cs | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 18a3c2da3d..b7465e5ffc 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -103,6 +103,28 @@ namespace osu.Desktop.Windows } } + public static void UninstallAssociations() + { + try + { + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) + return; + + foreach (var association in file_associations) + association.Uninstall(classes, PROGRAM_ID_PREFIX); + + foreach (var association in uri_associations) + association.Uninstall(classes); + + NotifyShellUpdate(); + } + catch (Exception e) + { + Logger.Log($@"Failed to uninstall file and URI associations: {e.Message}"); + } + } + /// /// Installs or updates associations. /// @@ -144,28 +166,6 @@ namespace osu.Desktop.Windows } } - public static void UninstallAssociations() - { - try - { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); - if (classes == null) - return; - - foreach (var association in file_associations) - association.Uninstall(classes, PROGRAM_ID_PREFIX); - - foreach (var association in uri_associations) - association.Uninstall(classes); - - NotifyShellUpdate(); - } - catch (Exception e) - { - Logger.Log($@"Failed to uninstall file and URI associations: {e.Message}"); - } - } - internal static void NotifyShellUpdate() => SHChangeNotify(EventId.SHCNE_ASSOCCHANGED, Flags.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero); #region Native interop From da8c4541dbfe8c8c0690ca57d91b6d428e94870d Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:21:04 +0100 Subject: [PATCH 340/915] Use `Logger.Error` --- osu.Desktop/Windows/WindowsAssociationManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index b7465e5ffc..c978e46b5b 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -67,7 +67,7 @@ namespace osu.Desktop.Windows } catch (Exception e) { - Logger.Log(@$"Failed to install file and URI associations: {e.Message}"); + Logger.Error(e, @$"Failed to install file and URI associations: {e.Message}"); } } @@ -86,7 +86,7 @@ namespace osu.Desktop.Windows } catch (Exception e) { - Logger.Log(@$"Failed to update file and URI associations: {e.Message}"); + Logger.Error(e, @"Failed to update file and URI associations."); } } @@ -99,7 +99,7 @@ namespace osu.Desktop.Windows } catch (Exception e) { - Logger.Log(@$"Failed to update file and URI association descriptions: {e.Message}"); + Logger.Error(e, @"Failed to update file and URI association descriptions."); } } @@ -121,7 +121,7 @@ namespace osu.Desktop.Windows } catch (Exception e) { - Logger.Log($@"Failed to uninstall file and URI associations: {e.Message}"); + Logger.Error(e, @"Failed to uninstall file and URI associations."); } } From 7f5dedc118059189e0d2bcb77e65ed39444de765 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:23:59 +0100 Subject: [PATCH 341/915] Refactor ProgID logic so it's more visible --- osu.Desktop/Windows/WindowsAssociationManager.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index c978e46b5b..aeda1e6283 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -35,7 +35,7 @@ namespace osu.Desktop.Windows /// Program ID prefix used for file associations. Should be relatively short since the full program ID has a 39 character limit, /// see https://learn.microsoft.com/en-us/windows/win32/com/-progid--key. /// - public const string PROGRAM_ID_PREFIX = "osu"; + public const string PROGRAM_ID_PREFIX = "osu.File"; private static readonly FileAssociation[] file_associations = { @@ -136,7 +136,7 @@ namespace osu.Desktop.Windows return; foreach (var association in file_associations) - association.Install(classes, EXE_PATH, PROGRAM_ID_PREFIX); + association.Install(classes, EXE_PATH); foreach (var association in uri_associations) association.Install(classes, EXE_PATH); @@ -191,15 +191,13 @@ namespace osu.Desktop.Windows private record FileAssociation(string Extension, LocalisableString Description, string IconPath) { - private string getProgramId(string prefix) => $@"{prefix}.File{Extension}"; + private string programId => $@"{PROGRAM_ID_PREFIX}{Extension}"; /// /// Installs a file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key /// - public void Install(RegistryKey classes, string exePath, string programIdPrefix) + public void Install(RegistryKey classes, string exePath) { - string programId = getProgramId(programIdPrefix); - // register a program id for the given extension using (var programKey = classes.CreateSubKey(programId)) { @@ -224,14 +222,12 @@ namespace osu.Desktop.Windows public void UpdateDescription(RegistryKey classes, string programIdPrefix, string description) { - using (var programKey = classes.OpenSubKey(getProgramId(programIdPrefix), true)) + using (var programKey = classes.OpenSubKey(programId, true)) programKey?.SetValue(null, description); } public void Uninstall(RegistryKey classes, string programIdPrefix) { - string programId = getProgramId(programIdPrefix); - // importantly, we don't delete the default program entry because some other program could have taken it. using (var extensionKey = classes.OpenSubKey($@"{Extension}\OpenWithProgIds", true)) From 3419b8ffa854b4b40daf26fe248e89a4e812e84a Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:26:21 +0100 Subject: [PATCH 342/915] Standardise using declaration --- osu.Desktop/Windows/WindowsAssociationManager.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index aeda1e6283..a786afde55 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -130,17 +130,15 @@ namespace osu.Desktop.Windows /// private static void updateAssociations() { - using (var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, writable: true)) - { - if (classes == null) - return; + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) + return; - foreach (var association in file_associations) - association.Install(classes, EXE_PATH); + foreach (var association in file_associations) + association.Install(classes, EXE_PATH); - foreach (var association in uri_associations) - association.Install(classes, EXE_PATH); - } + foreach (var association in uri_associations) + association.Install(classes, EXE_PATH); } private static void updateDescriptions(LocalisationManager? localisation) From 139072fa818a088f300fce9cfd38682c9c57dbcd Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:29:20 +0100 Subject: [PATCH 343/915] Standardise using declaration --- osu.Desktop/Windows/WindowsAssociationManager.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index a786afde55..2373cfa609 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -108,8 +109,7 @@ namespace osu.Desktop.Windows try { using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); - if (classes == null) - return; + Debug.Assert(classes != null); foreach (var association in file_associations) association.Uninstall(classes, PROGRAM_ID_PREFIX); @@ -131,8 +131,7 @@ namespace osu.Desktop.Windows private static void updateAssociations() { using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); - if (classes == null) - return; + Debug.Assert(classes != null); foreach (var association in file_associations) association.Install(classes, EXE_PATH); @@ -144,8 +143,7 @@ namespace osu.Desktop.Windows private static void updateDescriptions(LocalisationManager? localisation) { using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); - if (classes == null) - return; + Debug.Assert(classes != null); foreach (var association in file_associations) association.UpdateDescription(classes, PROGRAM_ID_PREFIX, getLocalisedString(association.Description)); From bf47221594a805530cee18ab5e2ff802bd54f232 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:42:42 +0100 Subject: [PATCH 344/915] Make things testable via 'Run static method' in Rider --- osu.Desktop/Windows/WindowsAssociationManager.cs | 2 +- osu.Desktop/osu.Desktop.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 2373cfa609..83fadfcae2 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -30,7 +30,7 @@ namespace osu.Desktop.Windows /// public const string SHELL_OPEN_COMMAND = @"Shell\Open\Command"; - public static readonly string EXE_PATH = Path.ChangeExtension(typeof(WindowsAssociationManager).Assembly.Location, ".exe"); + public static readonly string EXE_PATH = Path.ChangeExtension(typeof(WindowsAssociationManager).Assembly.Location, ".exe").Replace('/', '\\'); /// /// Program ID prefix used for file associations. Should be relatively short since the full program ID has a 39 character limit, diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index c6a95c1623..57752aa1f7 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -31,7 +31,7 @@ - + From 8049270ad2e17447a5f80446a7e39e73dc5e52e2 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Feb 2024 22:45:58 +0100 Subject: [PATCH 345/915] Remove unused param --- osu.Desktop/Windows/WindowsAssociationManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 83fadfcae2..83c2a97b56 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -112,7 +112,7 @@ namespace osu.Desktop.Windows Debug.Assert(classes != null); foreach (var association in file_associations) - association.Uninstall(classes, PROGRAM_ID_PREFIX); + association.Uninstall(classes); foreach (var association in uri_associations) association.Uninstall(classes); @@ -146,7 +146,7 @@ namespace osu.Desktop.Windows Debug.Assert(classes != null); foreach (var association in file_associations) - association.UpdateDescription(classes, PROGRAM_ID_PREFIX, getLocalisedString(association.Description)); + association.UpdateDescription(classes, getLocalisedString(association.Description)); foreach (var association in uri_associations) association.UpdateDescription(classes, getLocalisedString(association.Description)); @@ -216,13 +216,13 @@ namespace osu.Desktop.Windows } } - public void UpdateDescription(RegistryKey classes, string programIdPrefix, string description) + public void UpdateDescription(RegistryKey classes, string description) { using (var programKey = classes.OpenSubKey(programId, true)) programKey?.SetValue(null, description); } - public void Uninstall(RegistryKey classes, string programIdPrefix) + public void Uninstall(RegistryKey classes) { // importantly, we don't delete the default program entry because some other program could have taken it. From dfa0c51bc8b1067a08811f221da52109a6806c94 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Thu, 8 Feb 2024 00:23:46 +0100 Subject: [PATCH 346/915] Copy icons to nuget and install package Don't ask me why this uses the folder for .NET Framework 4.5 --- osu.Desktop/osu.nuspec | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec index f85698680e..66b3970351 100644 --- a/osu.Desktop/osu.nuspec +++ b/osu.Desktop/osu.nuspec @@ -20,6 +20,7 @@ + From 1dc54d6f25d030db88936ecbfec7dd8f55c71d3e Mon Sep 17 00:00:00 2001 From: Susko3 Date: Thu, 8 Feb 2024 00:54:48 +0100 Subject: [PATCH 347/915] Fix stable install path lookup `osu` is the `osu://` protocol handler, which gets overriden by lazer. Instead, use `osu!` which is the stable file handler. --- osu.Desktop/OsuGameDesktop.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index a0db896f46..5ac6ac7322 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -86,8 +86,8 @@ namespace osu.Desktop [SupportedOSPlatform("windows")] private string? getStableInstallPathFromRegistry() { - using (RegistryKey? key = Registry.ClassesRoot.OpenSubKey("osu")) - return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", ""); + using (RegistryKey? key = Registry.ClassesRoot.OpenSubKey("osu!")) + return key?.OpenSubKey(WindowsAssociationManager.SHELL_OPEN_COMMAND)?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", ""); } protected override UpdateManager CreateUpdateManager() From 6ded79cf0728010aedfb367cf48f3fd3f84abe6c Mon Sep 17 00:00:00 2001 From: Susko3 Date: Thu, 8 Feb 2024 01:15:37 +0100 Subject: [PATCH 348/915] Make `NotifyShellUpdate()` `public` to ease testing --- osu.Desktop/Windows/WindowsAssociationManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 83c2a97b56..4bb8e57c9d 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -125,6 +125,8 @@ namespace osu.Desktop.Windows } } + public static void NotifyShellUpdate() => SHChangeNotify(EventId.SHCNE_ASSOCCHANGED, Flags.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero); + /// /// Installs or updates associations. /// @@ -162,8 +164,6 @@ namespace osu.Desktop.Windows } } - internal static void NotifyShellUpdate() => SHChangeNotify(EventId.SHCNE_ASSOCCHANGED, Flags.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero); - #region Native interop [DllImport("Shell32.dll")] From 6adf0ac01ebbdd82c19617fe5e96f291c58365c7 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Thu, 8 Feb 2024 18:01:00 +0100 Subject: [PATCH 349/915] Use new LINQ Order() instead of OrderBy() when possible --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 2 +- osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs | 4 ++-- osu.Game.Rulesets.Taiko/Difficulty/Skills/Peaks.cs | 2 +- osu.Game.Tournament/IO/TournamentStorage.cs | 2 +- osu.Game/Beatmaps/BeatmapImporter.cs | 4 ++-- osu.Game/Collections/CollectionDropdown.cs | 2 +- osu.Game/Database/RealmArchiveModelImporter.cs | 4 ++-- osu.Game/Overlays/Music/PlaylistOverlay.cs | 2 +- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 2 +- osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs | 2 +- osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs | 4 ++-- osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs | 2 +- osu.Game/Rulesets/RealmRulesetStore.cs | 2 +- .../Edit/Compose/Components/BeatDivisorPresetCollection.cs | 2 +- .../Edit/Compose/Components/Timeline/DifficultyPointPiece.cs | 2 +- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c38d6519bd..75a642924c 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -375,7 +375,7 @@ namespace osu.Game.Rulesets.Mania /// The that corresponds to . private PlayfieldType getPlayfieldType(int variant) { - return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast().OrderByDescending(i => i).First(v => variant >= v); + return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast().OrderDescending().First(v => variant >= v); } protected override IEnumerable GetValidHitResults() diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 1947d86a97..0444394d87 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Scoring } protected override IEnumerable EnumerateHitObjects(IBeatmap beatmap) - => base.EnumerateHitObjects(beatmap).OrderBy(ho => ho, JudgementOrderComparer.DEFAULT); + => base.EnumerateHitObjects(beatmap).Order(JudgementOrderComparer.DEFAULT); protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index 15b20a5572..4a6328010b 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills // These sections will not contribute to the difficulty. var peaks = GetCurrentStrainPeaks().Where(p => p > 0); - List strains = peaks.OrderByDescending(d => d).ToList(); + List strains = peaks.OrderDescending().ToList(); // We are reducing the highest strains first to account for extreme difficulty spikes for (int i = 0; i < Math.Min(strains.Count, ReducedSectionCount); i++) @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills // Difficulty is the weighted sum of the highest strains from every section. // We're sorting from highest to lowest strain. - foreach (double strain in strains.OrderByDescending(d => d)) + foreach (double strain in strains.OrderDescending()) { difficulty += strain * weight; weight *= DecayWeight; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Peaks.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Peaks.cs index ec8e754c5c..91d8e93543 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Peaks.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Peaks.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills double difficulty = 0; double weight = 1; - foreach (double strain in peaks.OrderByDescending(d => d)) + foreach (double strain in peaks.OrderDescending()) { difficulty += strain * weight; weight *= 0.9; diff --git a/osu.Game.Tournament/IO/TournamentStorage.cs b/osu.Game.Tournament/IO/TournamentStorage.cs index 7c5f3e44a7..48cd45fdd4 100644 --- a/osu.Game.Tournament/IO/TournamentStorage.cs +++ b/osu.Game.Tournament/IO/TournamentStorage.cs @@ -45,6 +45,6 @@ namespace osu.Game.Tournament.IO Logger.Log("Changing tournament storage: " + GetFullPath(string.Empty)); } - public IEnumerable ListTournaments() => AllTournaments.GetDirectories(string.Empty).OrderBy(directory => directory, StringComparer.CurrentCultureIgnoreCase); + public IEnumerable ListTournaments() => AllTournaments.GetDirectories(string.Empty).Order(StringComparer.CurrentCultureIgnoreCase); } } diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 7bb52eef52..5ff3ab64b2 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -266,8 +266,8 @@ namespace osu.Game.Beatmaps if (!base.CanReuseExisting(existing, import)) return false; - var existingIds = existing.Beatmaps.Select(b => b.OnlineID).OrderBy(i => i); - var importIds = import.Beatmaps.Select(b => b.OnlineID).OrderBy(i => i); + var existingIds = existing.Beatmaps.Select(b => b.OnlineID).Order(); + var importIds = import.Beatmaps.Select(b => b.OnlineID).Order(); // force re-import if we are not in a sane state. return existing.OnlineID == import.OnlineID && existingIds.SequenceEqual(importIds); diff --git a/osu.Game/Collections/CollectionDropdown.cs b/osu.Game/Collections/CollectionDropdown.cs index 249a0c35e7..15dd644073 100644 --- a/osu.Game/Collections/CollectionDropdown.cs +++ b/osu.Game/Collections/CollectionDropdown.cs @@ -74,7 +74,7 @@ namespace osu.Game.Collections } else { - foreach (int i in changes.DeletedIndices.OrderByDescending(i => i)) + foreach (int i in changes.DeletedIndices.OrderDescending()) filters.RemoveAt(i + 1); foreach (int i in changes.InsertedIndices) diff --git a/osu.Game/Database/RealmArchiveModelImporter.cs b/osu.Game/Database/RealmArchiveModelImporter.cs index 5383040eb4..bc4954c6ea 100644 --- a/osu.Game/Database/RealmArchiveModelImporter.cs +++ b/osu.Game/Database/RealmArchiveModelImporter.cs @@ -279,7 +279,7 @@ namespace osu.Game.Database // note that this should really be checking filesizes on disk (of existing files) for some degree of sanity. // or alternatively doing a faster hash check. either of these require database changes and reprocessing of existing files. if (CanSkipImport(existing, item) && - getFilenames(existing.Files).SequenceEqual(getShortenedFilenames(archive).Select(p => p.shortened).OrderBy(f => f)) && + getFilenames(existing.Files).SequenceEqual(getShortenedFilenames(archive).Select(p => p.shortened).Order()) && checkAllFilesExist(existing)) { LogForModel(item, @$"Found existing (optimised) {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import."); @@ -437,7 +437,7 @@ namespace osu.Game.Database { MemoryStream hashable = new MemoryStream(); - foreach (string? 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))).Order()) { using (Stream s = reader.GetStream(file)) s.CopyTo(hashable); diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 7784643163..6ecd0f51d3 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -122,7 +122,7 @@ namespace osu.Game.Overlays.Music foreach (int i in changes.InsertedIndices) beatmapSets.Insert(i, sender[i].ToLive(realm)); - foreach (int i in changes.DeletedIndices.OrderByDescending(i => i)) + foreach (int i in changes.DeletedIndices.OrderDescending()) beatmapSets.RemoveAt(i); } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index d4cef3f4d1..fc5dd34971 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { LabelText = GraphicsSettingsStrings.Renderer, Current = renderer, - Items = host.GetPreferredRenderersForCurrentPlatform().OrderBy(t => t).Where(t => t != RendererType.Vulkan), + Items = host.GetPreferredRenderersForCurrentPlatform().Order().Where(t => t != RendererType.Vulkan), Keywords = new[] { @"compatibility", @"directx" }, }, // TODO: this needs to be a custom dropdown at some point diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index b43a272324..b07e8399c0 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills // Difficulty is the weighted sum of the highest strains from every section. // We're sorting from highest to lowest strain. - foreach (double strain in peaks.OrderByDescending(d => d)) + foreach (double strain in peaks.OrderDescending()) { difficulty += strain * weight; weight *= DecayWeight; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs index 94369443c2..0842ff5453 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBreaks.cs @@ -31,8 +31,8 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - var startTimes = context.Beatmap.HitObjects.Select(ho => ho.StartTime).OrderBy(x => x).ToList(); - var endTimes = context.Beatmap.HitObjects.Select(ho => ho.GetEndTime()).OrderBy(x => x).ToList(); + var startTimes = context.Beatmap.HitObjects.Select(ho => ho.StartTime).Order().ToList(); + var endTimes = context.Beatmap.HitObjects.Select(ho => ho.GetEndTime()).Order().ToList(); foreach (var breakPeriod in context.Beatmap.Breaks) { diff --git a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs index 77aa5cdc15..19554b6504 100644 --- a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs +++ b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs @@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToBeatmap(IBeatmap beatmap) { var hitObjects = getAllApplicableHitObjects(beatmap.HitObjects).ToList(); - var endTimes = hitObjects.Select(x => x.GetEndTime()).OrderBy(x => x).Distinct().ToList(); + var endTimes = hitObjects.Select(x => x.GetEndTime()).Order().Distinct().ToList(); foreach (HitObject hitObject in hitObjects) { diff --git a/osu.Game/Rulesets/RealmRulesetStore.cs b/osu.Game/Rulesets/RealmRulesetStore.cs index 456f6e399b..ba6f4583d1 100644 --- a/osu.Game/Rulesets/RealmRulesetStore.cs +++ b/osu.Game/Rulesets/RealmRulesetStore.cs @@ -107,7 +107,7 @@ namespace osu.Game.Rulesets } } - availableRulesets.AddRange(detachedRulesets.OrderBy(r => r)); + availableRulesets.AddRange(detachedRulesets.Order()); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs index 56df0552cc..43ab47d2d7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Edit.Compose.Components presets.Add(maxDivisor / candidate); } - return new BeatDivisorPresetCollection(BeatDivisorType.Custom, presets.Distinct().OrderBy(d => d)); + return new BeatDivisorPresetCollection(BeatDivisorType.Custom, presets.Distinct().Order()); } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index ca1e9a5d9b..fc240c570b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -169,7 +169,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline InspectorText.Clear(); - double[] sliderVelocities = EditorBeatmap.HitObjects.OfType().Select(sv => sv.SliderVelocityMultiplier).OrderBy(v => v).ToArray(); + double[] sliderVelocities = EditorBeatmap.HitObjects.OfType().Select(sv => sv.SliderVelocityMultiplier).Order().ToArray(); AddHeader("Base velocity (from beatmap setup)"); AddValue($"{beatmapVelocity:#,0.00}x"); From c500264306adceec5edbbab0baa40a7bc13c65c4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 9 Feb 2024 23:20:31 +0300 Subject: [PATCH 350/915] Cache created judgement in HitObject --- .../TestSceneCatchSkinConfiguration.cs | 2 +- osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Banana.cs | 2 +- osu.Game.Rulesets.Catch/Objects/BananaShower.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Droplet.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Fruit.cs | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs | 2 +- osu.Game.Rulesets.Mania/Objects/BarLine.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs | 2 +- osu.Game.Rulesets.Mania/Objects/Note.cs | 2 +- osu.Game.Rulesets.Mania/Objects/TailNote.cs | 2 +- .../TestSceneSpinnerRotation.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs | 2 +- osu.Game.Rulesets.Osu/Objects/HitCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs | 2 +- .../TaikoHealthProcessorTest.cs | 8 ++++---- osu.Game.Rulesets.Taiko/Objects/BarLine.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs | 2 +- .../Objects/StrongNestedHitObject.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs | 2 +- osu.Game/Beatmaps/IBeatmap.cs | 2 +- osu.Game/Database/StandardisedScoreMigrationTools.cs | 2 +- .../Difficulty/PerformanceBreakdownCalculator.cs | 4 ++-- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- osu.Game/Rulesets/Objects/HitObject.cs | 10 +++++++++- osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs | 2 +- osu.Game/Rulesets/Scoring/JudgementProcessor.cs | 2 +- .../Rulesets/Scoring/LegacyDrainingHealthProcessor.cs | 2 +- 41 files changed, 54 insertions(+), 46 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs index e2fc31d869..0d7aa6af10 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Catch.Tests { fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); var drawableFruit = new DrawableFruit(fruit) { X = x }; - var judgement = fruit.CreateJudgement(); + var judgement = fruit.Judgement; catcher.OnNewResult(drawableFruit, new CatchJudgementResult(fruit, judgement) { Type = judgement.MaxResult diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index f60ae29f77..b03fa00f76 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -293,7 +293,7 @@ namespace osu.Game.Rulesets.Catch.Tests private JudgementResult createResult(CatchHitObject hitObject) { - return new CatchJudgementResult(hitObject, hitObject.CreateJudgement()) + return new CatchJudgementResult(hitObject, hitObject.Judgement) { Type = catcher.CanCatch(hitObject) ? HitResult.Great : HitResult.Miss }; diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index b80527f379..30bdb24b14 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Objects /// public int BananaIndex; - public override Judgement CreateJudgement() => new CatchBananaJudgement(); + protected override Judgement CreateJudgement() => new CatchBananaJudgement(); private static readonly IList default_banana_samples = new List { new BananaHitSampleInfo() }.AsReadOnly(); diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 328cc2b52a..86c41fce90 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Objects { public override bool LastInCombo => true; - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); protected override void CreateNestedHitObjects(CancellationToken cancellationToken) { diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index 9c1004a04b..107c6c3979 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class Droplet : PalpableCatchHitObject { - public override Judgement CreateJudgement() => new CatchDropletJudgement(); + protected override Judgement CreateJudgement() => new CatchDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index 4818fe2cad..17270b803c 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Catch.Objects { public class Fruit : PalpableCatchHitObject { - public override Judgement CreateJudgement() => new CatchJudgement(); + protected override Judgement CreateJudgement() => new CatchJudgement(); public static FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => (FruitVisualRepresentation)(indexInBeatmap % 4); } diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 671291ef0e..49c24df5b9 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.Objects /// private const float base_scoring_distance = 100; - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); public int RepeatCount { get; set; } diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index 1bf160b5a6..ddcb92875f 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class TinyDroplet : Droplet { - public override Judgement CreateJudgement() => new CatchTinyDropletJudgement(); + protected override Judgement CreateJudgement() => new CatchTinyDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs index cf576239ed..742b5e4b0d 100644 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/BarLine.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Mania.Objects set => major.Value = value; } - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 3f930a310b..4aac455bc5 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.Objects }); } - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs index 47163d0d81..92b649c174 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class HoldNoteBody : ManiaHitObject { - public override Judgement CreateJudgement() => new HoldNoteBodyJudgement(); + protected override Judgement CreateJudgement() => new HoldNoteBodyJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 0035960c63..b0f2991918 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class Note : ManiaHitObject { - public override Judgement CreateJudgement() => new ManiaJudgement(); + protected override Judgement CreateJudgement() => new ManiaJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index def32880f1..bddb4630cb 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// public const double RELEASE_WINDOW_LENIENCE = 1.5; - public override Judgement CreateJudgement() => new ManiaJudgement(); + protected override Judgement CreateJudgement() => new ManiaJudgement(); public override double MaximumJudgementOffset => base.MaximumJudgementOffset * RELEASE_WINDOW_LENIENCE; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index 6706d20080..8d81fe3017 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Tests // multipled by 2 to nullify the score multiplier. (autoplay mod selected) long totalScore = scoreProcessor.TotalScore.Value * 2; - return totalScore == (int)(drawableSpinner.Result.TotalRotation / 360) * scoreProcessor.GetBaseScoreForResult(new SpinnerTick().CreateJudgement().MaxResult); + return totalScore == (int)(drawableSpinner.Result.TotalRotation / 360) * scoreProcessor.GetBaseScoreForResult(new SpinnerTick().Judgement.MaxResult); }); addSeekStep(0); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs index 2c9292c58b..f07a1e930b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Mods { } - public override Judgement CreateJudgement() => new OsuJudgement(); + protected override Judgement CreateJudgement() => new OsuJudgement(); } private partial class StrictTrackingDrawableSliderTail : DrawableSliderTail diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index d652db0fd4..6336482ccc 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Osu.Objects { public class HitCircle : OsuHitObject { - public override Judgement CreateJudgement() => new OsuJudgement(); + protected override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 506145568e..fc0248cbbd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Osu.Objects TailSamples = this.GetNodeSamples(repeatCount + 1); } - public override Judgement CreateJudgement() => ClassicSliderBehaviour + protected override Judgement CreateJudgement() => ClassicSliderBehaviour // Final combo is provided by the slider itself - see logic in `DrawableSlider.CheckForResult()` ? new OsuJudgement() // Final combo is provided by the tail circle - see `SliderTailCircle` diff --git a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs index 2d5a5b7727..8d60864f0b 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Objects protected override HitWindows CreateHitWindows() => HitWindows.Empty; - public override Judgement CreateJudgement() => new SliderEndJudgement(); + protected override Judgement CreateJudgement() => new SliderEndJudgement(); public class SliderEndJudgement : OsuJudgement { diff --git a/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs index 8305481788..4760135081 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Osu.Objects /// public bool ClassicSliderBehaviour; - public override Judgement CreateJudgement() => ClassicSliderBehaviour ? new SliderTickJudgement() : base.CreateJudgement(); + protected override Judgement CreateJudgement() => ClassicSliderBehaviour ? new SliderTickJudgement() : base.CreateJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index ee2490439f..42d8d895e4 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Objects { } - public override Judgement CreateJudgement() => ClassicSliderBehaviour ? new LegacyTailJudgement() : new TailJudgement(); + protected override Judgement CreateJudgement() => ClassicSliderBehaviour ? new LegacyTailJudgement() : new TailJudgement(); public class LegacyTailJudgement : OsuJudgement { diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 74ec4d6eb3..1d7ba2fbaf 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -32,6 +32,6 @@ namespace osu.Game.Rulesets.Osu.Objects protected override HitWindows CreateHitWindows() => HitWindows.Empty; - public override Judgement CreateJudgement() => new SliderTickJudgement(); + protected override Judgement CreateJudgement() => new SliderTickJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index e3dfe8e69a..9baa645b3c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Osu.Objects } } - public override Judgement CreateJudgement() => new OsuJudgement(); + protected override Judgement CreateJudgement() => new OsuJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs index 8d53100529..57db29ef0c 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Osu.Objects { public class SpinnerBonusTick : SpinnerTick { - public override Judgement CreateJudgement() => new OsuSpinnerBonusTickJudgement(); + protected override Judgement CreateJudgement() => new OsuSpinnerBonusTickJudgement(); public class OsuSpinnerBonusTickJudgement : OsuSpinnerTickJudgement { diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs index 7989c9b7ff..cb59014909 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects /// public double SpinnerDuration { get; set; } - public override Judgement CreateJudgement() => new OsuSpinnerTickJudgement(); + protected override Judgement CreateJudgement() => new OsuSpinnerTickJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs index f4a1e888c9..b28e870481 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs @@ -126,11 +126,11 @@ namespace osu.Game.Rulesets.Taiko.Tests foreach (var nested in beatmap.HitObjects[0].NestedHitObjects) { - var nestedJudgement = nested.CreateJudgement(); + var nestedJudgement = nested.Judgement; healthProcessor.ApplyResult(new JudgementResult(nested, nestedJudgement) { Type = nestedJudgement.MaxResult }); } - var judgement = beatmap.HitObjects[0].CreateJudgement(); + var judgement = beatmap.HitObjects[0].Judgement; healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], judgement) { Type = judgement.MaxResult }); Assert.Multiple(() => @@ -159,11 +159,11 @@ namespace osu.Game.Rulesets.Taiko.Tests foreach (var nested in beatmap.HitObjects[0].NestedHitObjects) { - var nestedJudgement = nested.CreateJudgement(); + var nestedJudgement = nested.Judgement; healthProcessor.ApplyResult(new JudgementResult(nested, nestedJudgement) { Type = nestedJudgement.MaxResult }); } - var judgement = beatmap.HitObjects[0].CreateJudgement(); + var judgement = beatmap.HitObjects[0].Judgement; healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], judgement) { Type = judgement.MaxResult }); Assert.Multiple(() => diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs index 46b3f13501..d87f8b3232 100644 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Taiko.Objects set => major.Value = value; } - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index f3143de345..50cd722a3f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Taiko.Objects } } - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Taiko.Objects public class StrongNestedHit : StrongNestedHitObject { // The strong hit of the drum roll doesn't actually provide any score. - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); public StrongNestedHit(TaikoHitObject parent) : base(parent) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index dc082ffd21..c1d4102042 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Objects Parent = parent; } - public override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); + protected override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs b/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs index 302f940ef4..44cd700faf 100644 --- a/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs @@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class IgnoreHit : Hit { - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs index 14cbe338ed..227ab4ab52 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Objects Parent = parent; } - public override Judgement CreateJudgement() => new TaikoStrongJudgement(); + protected override Judgement CreateJudgement() => new TaikoStrongJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index a8db8df021..76d106f924 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Taiko.Objects } } - public override Judgement CreateJudgement() => new TaikoSwellJudgement(); + protected override Judgement CreateJudgement() => new TaikoSwellJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index 41fb9cac7e..be1c1101de 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class SwellTick : TaikoHitObject { - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 1a1fde1990..697c23addf 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public const float DEFAULT_SIZE = 0.475f; - public override Judgement CreateJudgement() => new TaikoJudgement(); + protected override Judgement CreateJudgement() => new TaikoJudgement(); protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); } diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index d97eb00d7e..b5bb6ccafc 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -94,7 +94,7 @@ namespace osu.Game.Beatmaps static void addCombo(HitObject hitObject, ref int combo) { - if (hitObject.CreateJudgement().MaxResult.AffectsCombo()) + if (hitObject.Judgement.MaxResult.AffectsCombo()) combo++; foreach (var nested in hitObject.NestedHitObjects) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index 403e73ab77..576d08f491 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -655,7 +655,7 @@ namespace osu.Game.Database { private readonly Judgement judgement; - public override Judgement CreateJudgement() => judgement; + protected override Judgement CreateJudgement() => judgement; public FakeHit(Judgement judgement) { diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs index 4563c264f7..946d83b14b 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs @@ -113,9 +113,9 @@ namespace osu.Game.Rulesets.Difficulty private IEnumerable getPerfectHitResults(HitObject hitObject) { foreach (HitObject nested in hitObject.NestedHitObjects) - yield return nested.CreateJudgement().MaxResult; + yield return nested.Judgement.MaxResult; - yield return hitObject.CreateJudgement().MaxResult; + yield return hitObject.Judgement.MaxResult; } } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index c9192ae3eb..16bd4b565c 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -770,7 +770,7 @@ namespace osu.Game.Rulesets.Objects.Drawables private void ensureEntryHasResult() { Debug.Assert(Entry != null); - Entry.Result ??= CreateResult(HitObject.CreateJudgement()) + Entry.Result ??= CreateResult(HitObject.Judgement) ?? throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index ef8bd08bf4..aed821332d 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -162,11 +162,19 @@ namespace osu.Game.Rulesets.Objects protected void AddNested(HitObject hitObject) => nestedHitObjects.Add(hitObject); + /// + /// The that represents the scoring information for this . + /// + [JsonIgnore] + public Judgement Judgement => judgement ??= CreateJudgement(); + + private Judgement judgement; + /// /// Creates the that represents the scoring information for this . /// [NotNull] - public virtual Judgement CreateJudgement() => new Judgement(); + protected virtual Judgement CreateJudgement() => new Judgement(); /// /// Creates the for this . diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs index bb36aab0b3..499953dab9 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public int ComboOffset { get; set; } - public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index e9f3bcb949..0e90330651 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -149,7 +149,7 @@ namespace osu.Game.Rulesets.Scoring foreach (var obj in EnumerateHitObjects(beatmap)) { - var judgement = obj.CreateJudgement(); + var judgement = obj.Judgement; var result = CreateResult(obj, judgement); if (result == null) diff --git a/osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs index ce2f7d5624..2bc3ea80ec 100644 --- a/osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs @@ -141,7 +141,7 @@ namespace osu.Game.Rulesets.Scoring void increaseHp(HitObject hitObject) { - double amount = GetHealthIncreaseFor(hitObject, hitObject.CreateJudgement().MaxResult); + double amount = GetHealthIncreaseFor(hitObject, hitObject.Judgement.MaxResult); currentHpUncapped += amount; currentHp = Math.Max(0, Math.Min(1, currentHp + amount)); } From 666c57da5023627624c546c4450c7f04af676b5c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 30 Dec 2023 12:17:14 -0800 Subject: [PATCH 351/915] Fix profile current location and interests icons not matching web --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 85751e7457..83ddb024c6 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -144,8 +144,8 @@ namespace osu.Game.Overlays.Profile.Header bool anyInfoAdded = false; - anyInfoAdded |= tryAddInfo(FontAwesome.Solid.MapMarker, user.Location); - anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Heart, user.Interests); + anyInfoAdded |= tryAddInfo(FontAwesome.Solid.MapMarkerAlt, user.Location); + anyInfoAdded |= tryAddInfo(FontAwesome.Regular.Heart, user.Interests); anyInfoAdded |= tryAddInfo(FontAwesome.Solid.Suitcase, user.Occupation); if (anyInfoAdded) From ed2362b63da113e45e46756a47b94a3938ce4973 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 30 Dec 2023 12:17:46 -0800 Subject: [PATCH 352/915] Fix icon family and weight not transferring to text conversion --- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 83ddb024c6..d5b4d844b2 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -171,7 +171,7 @@ namespace osu.Game.Overlays.Profile.Header bottomLinkContainer.AddIcon(icon, text => { - text.Font = text.Font.With(size: 10); + text.Font = text.Font.With(icon.Family, 10, icon.Weight); text.Colour = iconColour; }); From c9c39ecb2f616b27b088bb455d5c122323127b10 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 9 Feb 2024 15:15:27 -0800 Subject: [PATCH 353/915] Add `RankHighest` to `APIUser` --- .../Visual/Online/TestSceneUserProfileOverlay.cs | 5 +++++ osu.Game/Online/API/Requests/Responses/APIUser.cs | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index bc8f75d4ce..020e020b10 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -137,6 +137,11 @@ namespace osu.Game.Tests.Visual.Online @"top_ranks", @"medals" }, + RankHighest = new APIUser.UserRankHighest + { + Rank = 1, + UpdatedAt = DateTimeOffset.Now, + }, Statistics = new UserStatistics { IsRanked = true, diff --git a/osu.Game/Online/API/Requests/Responses/APIUser.cs b/osu.Game/Online/API/Requests/Responses/APIUser.cs index 56eec19fa1..4a31718f28 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -34,6 +34,19 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"previous_usernames")] public string[] PreviousUsernames; + [JsonProperty(@"rank_highest")] + [CanBeNull] + public UserRankHighest RankHighest; + + public class UserRankHighest + { + [JsonProperty(@"rank")] + public int Rank; + + [JsonProperty(@"updated_at")] + public DateTimeOffset UpdatedAt; + } + [JsonProperty(@"country_code")] private string countryCodeString; From 8d1d65a469c717f29115743ab231ce791930668d Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 9 Feb 2024 15:17:34 -0800 Subject: [PATCH 354/915] Add `ContentTooltipText` to `ProfileValueDisplay` --- .../Header/Components/ProfileValueDisplay.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileValueDisplay.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileValueDisplay.cs index 4b1a0409a3..b2c23458b1 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileValueDisplay.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileValueDisplay.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -13,7 +14,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public partial class ProfileValueDisplay : CompositeDrawable { private readonly OsuSpriteText title; - private readonly OsuSpriteText content; + private readonly ContentText content; public LocalisableString Title { @@ -25,6 +26,11 @@ namespace osu.Game.Overlays.Profile.Header.Components set => content.Text = value; } + public LocalisableString ContentTooltipText + { + set => content.TooltipText = value; + } + public ProfileValueDisplay(bool big = false, int minimumWidth = 60) { AutoSizeAxes = Axes.Both; @@ -38,9 +44,9 @@ namespace osu.Game.Overlays.Profile.Header.Components { Font = OsuFont.GetFont(size: 12) }, - content = new OsuSpriteText + content = new ContentText { - Font = OsuFont.GetFont(size: big ? 30 : 20, weight: FontWeight.Light) + Font = OsuFont.GetFont(size: big ? 30 : 20, weight: FontWeight.Light), }, new Container // Add a minimum size to the FillFlowContainer { @@ -56,5 +62,10 @@ namespace osu.Game.Overlays.Profile.Header.Components title.Colour = colourProvider.Content1; content.Colour = colourProvider.Content2; } + + private partial class ContentText : OsuSpriteText, IHasTooltip + { + public LocalisableString TooltipText { get; set; } + } } } From ae89b89928af680dc921cfc4880241aa787e44ce Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 9 Feb 2024 15:33:49 -0800 Subject: [PATCH 355/915] Centralise global rank display logic to new class --- .../Header/Components/GlobalRankDisplay.cs | 32 +++++++++++++++++++ .../Profile/Header/Components/MainDetails.cs | 9 ++---- osu.Game/Users/UserRankPanel.cs | 6 ++-- 3 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs diff --git a/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs b/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs new file mode 100644 index 0000000000..290b052e27 --- /dev/null +++ b/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.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 osu.Framework.Bindables; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; +using osu.Game.Users; + +namespace osu.Game.Overlays.Profile.Header.Components +{ + public partial class GlobalRankDisplay : ProfileValueDisplay + { + public readonly Bindable UserStatistics = new Bindable(); + + public GlobalRankDisplay() + : base(true) + { + Title = UsersStrings.ShowRankGlobalSimple; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + UserStatistics.BindValueChanged(s => + { + Content = s.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; + }, true); + } + } +} diff --git a/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs b/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs index b89973c5e5..2aea897451 100644 --- a/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private readonly Dictionary scoreRankInfos = new Dictionary(); private ProfileValueDisplay medalInfo = null!; private ProfileValueDisplay ppInfo = null!; - private ProfileValueDisplay detailGlobalRank = null!; + private GlobalRankDisplay detailGlobalRank = null!; private ProfileValueDisplay detailCountryRank = null!; private RankGraph rankGraph = null!; @@ -52,10 +52,7 @@ namespace osu.Game.Overlays.Profile.Header.Components Spacing = new Vector2(20), Children = new Drawable[] { - detailGlobalRank = new ProfileValueDisplay(true) - { - Title = UsersStrings.ShowRankGlobalSimple, - }, + detailGlobalRank = new GlobalRankDisplay(), detailCountryRank = new ProfileValueDisplay(true) { Title = UsersStrings.ShowRankCountrySimple, @@ -142,7 +139,7 @@ namespace osu.Game.Overlays.Profile.Header.Components foreach (var scoreRankInfo in scoreRankInfos) scoreRankInfo.Value.RankCount = user?.Statistics?.GradesCount[scoreRankInfo.Key] ?? 0; - detailGlobalRank.Content = user?.Statistics?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; + detailGlobalRank.UserStatistics.Value = user?.Statistics; detailCountryRank.Content = user?.Statistics?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; rankGraph.Statistics.Value = user?.Statistics; diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index 84ff3114fc..ba9ef1eee4 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -27,7 +27,6 @@ namespace osu.Game.Users [Resolved] private IAPIProvider api { get; set; } = null!; - private ProfileValueDisplay globalRankDisplay = null!; private ProfileValueDisplay countryRankDisplay = null!; private readonly IBindable statistics = new Bindable(); @@ -47,7 +46,6 @@ namespace osu.Game.Users statistics.BindTo(api.Statistics); statistics.BindValueChanged(stats => { - globalRankDisplay.Content = stats.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? "-"; countryRankDisplay.Content = stats.NewValue?.CountryRank?.ToLocalisableString("\\##,##0") ?? "-"; }, true); } @@ -163,9 +161,9 @@ namespace osu.Game.Users { new Drawable[] { - globalRankDisplay = new ProfileValueDisplay(true) + new GlobalRankDisplay { - Title = UsersStrings.ShowRankGlobalSimple, + UserStatistics = { BindTarget = statistics }, }, countryRankDisplay = new ProfileValueDisplay(true) { From ffd0d9bb3994f7471746921f63a3594efc16c49d Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 9 Feb 2024 15:36:15 -0800 Subject: [PATCH 356/915] Add highest rank tooltip to global rank display --- .../Profile/Header/Components/GlobalRankDisplay.cs | 12 ++++++++++++ .../Profile/Header/Components/MainDetails.cs | 1 + osu.Game/Users/UserRankPanel.cs | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs b/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs index 290b052e27..dcd4129b45 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs @@ -4,6 +4,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; using osu.Game.Users; @@ -12,6 +13,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public partial class GlobalRankDisplay : ProfileValueDisplay { public readonly Bindable UserStatistics = new Bindable(); + public readonly Bindable User = new Bindable(); public GlobalRankDisplay() : base(true) @@ -27,6 +29,16 @@ namespace osu.Game.Overlays.Profile.Header.Components { Content = s.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; }, true); + + // needed as statistics doesn't populate User + User.BindValueChanged(u => + { + var rankHighest = u.NewValue?.RankHighest; + + ContentTooltipText = rankHighest != null + ? UsersStrings.ShowRankHighest(rankHighest.Rank.ToLocalisableString("\\##,##0"), rankHighest.UpdatedAt.ToLocalisableString(@"d MMM yyyy")) + : string.Empty; + }, true); } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs b/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs index 2aea897451..ffdf8edc21 100644 --- a/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs @@ -140,6 +140,7 @@ namespace osu.Game.Overlays.Profile.Header.Components scoreRankInfo.Value.RankCount = user?.Statistics?.GradesCount[scoreRankInfo.Key] ?? 0; detailGlobalRank.UserStatistics.Value = user?.Statistics; + detailGlobalRank.User.Value = user; detailCountryRank.Content = user?.Statistics?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; rankGraph.Statistics.Value = user?.Statistics; diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index ba9ef1eee4..4a00583094 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -30,6 +30,7 @@ namespace osu.Game.Users private ProfileValueDisplay countryRankDisplay = null!; private readonly IBindable statistics = new Bindable(); + private readonly IBindable user = new Bindable(); public UserRankPanel(APIUser user) : base(user) @@ -48,6 +49,8 @@ namespace osu.Game.Users { countryRankDisplay.Content = stats.NewValue?.CountryRank?.ToLocalisableString("\\##,##0") ?? "-"; }, true); + + user.BindTo(api.LocalUser!); } protected override Drawable CreateLayout() @@ -164,6 +167,9 @@ namespace osu.Game.Users new GlobalRankDisplay { UserStatistics = { BindTarget = statistics }, + // TODO: make highest rank update, as api.LocalUser doesn't update + // maybe move to statistics in api, so `SoloStatisticsWatcher` can update the value + User = { BindTarget = user }, }, countryRankDisplay = new ProfileValueDisplay(true) { From 7b0b39dbaa515e5d2455de0da7e9884d222fc601 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 9 Feb 2024 15:46:14 -0800 Subject: [PATCH 357/915] Fix total play time tooltip area including label --- .../Profile/Header/Components/TotalPlayTime.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/TotalPlayTime.cs b/osu.Game/Overlays/Profile/Header/Components/TotalPlayTime.cs index 08ca59d89b..a3c22d61d2 100644 --- a/osu.Game/Overlays/Profile/Header/Components/TotalPlayTime.cs +++ b/osu.Game/Overlays/Profile/Header/Components/TotalPlayTime.cs @@ -5,25 +5,19 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Profile.Header.Components { - public partial class TotalPlayTime : CompositeDrawable, IHasTooltip + public partial class TotalPlayTime : CompositeDrawable { public readonly Bindable User = new Bindable(); - public LocalisableString TooltipText { get; set; } - private ProfileValueDisplay info = null!; public TotalPlayTime() { AutoSizeAxes = Axes.Both; - - TooltipText = "0 hours"; } [BackgroundDependencyLoader] @@ -32,6 +26,7 @@ namespace osu.Game.Overlays.Profile.Header.Components InternalChild = info = new ProfileValueDisplay(minimumWidth: 140) { Title = UsersStrings.ShowStatsPlayTime, + ContentTooltipText = "0 hours", }; User.BindValueChanged(updateTime, true); @@ -40,7 +35,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private void updateTime(ValueChangedEvent user) { int? playTime = user.NewValue?.User.Statistics?.PlayTime; - TooltipText = (playTime ?? 0) / 3600 + " hours"; + info.ContentTooltipText = (playTime ?? 0) / 3600 + " hours"; info.Content = formatTime(playTime); } From 7c04e8bfba9da67118ae3ffc28abe6e2de04191b Mon Sep 17 00:00:00 2001 From: Stoppedpuma <58333920+Stoppedpuma@users.noreply.github.com> Date: Sat, 10 Feb 2024 07:48:24 +0100 Subject: [PATCH 358/915] Alias author to creator Allows "author" to show the results of "creator" --- osu.Game/Screens/Select/FilterQueryParser.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 0d8905347b..f6023c0b61 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -68,6 +68,7 @@ namespace osu.Game.Screens.Select return TryUpdateCriteriaRange(ref criteria.OnlineStatus, op, value, tryParseEnum); case "creator": + case "author": return TryUpdateCriteriaText(ref criteria.Creator, op, value); case "artist": From bfeb90c1b6d7e09edf59c42ed14a567a4bcdee7e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 10 Feb 2024 17:20:17 +0900 Subject: [PATCH 359/915] Add additional gameplay metadata to room score request --- osu.Game/Online/Rooms/CreateRoomScoreRequest.cs | 10 +++++++++- osu.Game/Screens/Play/RoomSubmittingPlayer.cs | 12 +++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs b/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs index c31c6a929a..e0f91032fd 100644 --- a/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs +++ b/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Globalization; using System.Net.Http; using osu.Framework.IO.Network; +using osu.Game.Beatmaps; using osu.Game.Online.API; namespace osu.Game.Online.Rooms @@ -11,12 +13,16 @@ namespace osu.Game.Online.Rooms { private readonly long roomId; private readonly long playlistItemId; + private readonly BeatmapInfo beatmapInfo; + private readonly int rulesetId; private readonly string versionHash; - public CreateRoomScoreRequest(long roomId, long playlistItemId, string versionHash) + public CreateRoomScoreRequest(long roomId, long playlistItemId, BeatmapInfo beatmapInfo, int rulesetId, string versionHash) { this.roomId = roomId; this.playlistItemId = playlistItemId; + this.beatmapInfo = beatmapInfo; + this.rulesetId = rulesetId; this.versionHash = versionHash; } @@ -25,6 +31,8 @@ namespace osu.Game.Online.Rooms var req = base.CreateWebRequest(); req.Method = HttpMethod.Post; req.AddParameter("version_hash", versionHash); + req.AddParameter("beatmap_hash", beatmapInfo.MD5Hash); + req.AddParameter("ruleset_id", rulesetId.ToString(CultureInfo.InvariantCulture)); return req; } diff --git a/osu.Game/Screens/Play/RoomSubmittingPlayer.cs b/osu.Game/Screens/Play/RoomSubmittingPlayer.cs index e21daa737e..3f74f49384 100644 --- a/osu.Game/Screens/Play/RoomSubmittingPlayer.cs +++ b/osu.Game/Screens/Play/RoomSubmittingPlayer.cs @@ -4,6 +4,7 @@ #nullable disable using System.Diagnostics; +using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Scoring; @@ -30,7 +31,16 @@ namespace osu.Game.Screens.Play if (!(Room.RoomID.Value is long roomId)) return null; - return new CreateRoomScoreRequest(roomId, PlaylistItem.ID, Game.VersionHash); + int beatmapId = Beatmap.Value.BeatmapInfo.OnlineID; + int rulesetId = Ruleset.Value.OnlineID; + + if (beatmapId <= 0) + return null; + + if (!Ruleset.Value.IsLegacyRuleset()) + return null; + + return new CreateRoomScoreRequest(roomId, PlaylistItem.ID, Beatmap.Value.BeatmapInfo, rulesetId, Game.VersionHash); } protected override APIRequest CreateSubmissionRequest(Score score, long token) From 5fa54c8c6355aeb85df2daa905d4c02d66995132 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 10 Feb 2024 14:16:45 +0300 Subject: [PATCH 360/915] Fix remaining use cases --- .../Objects/EmptyFreeformHitObject.cs | 2 +- .../Objects/PippidonHitObject.cs | 2 +- .../Objects/EmptyScrollingHitObject.cs | 2 +- .../Objects/PippidonHitObject.cs | 2 +- .../Gameplay/TestSceneDrainingHealthProcessor.cs | 2 +- .../Gameplay/TestSceneDrawableHitObject.cs | 2 +- .../Gameplay/TestSceneScoreProcessor.cs | 14 +++++++------- .../Rulesets/Scoring/ScoreProcessorTest.cs | 15 ++++++--------- 8 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/EmptyFreeformHitObject.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/EmptyFreeformHitObject.cs index 9cd18d2d9f..e166d09f84 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/EmptyFreeformHitObject.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/EmptyFreeformHitObject.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Objects { public class EmptyFreeformHitObject : HitObject, IHasPosition { - public override Judgement CreateJudgement() => new Judgement(); + protected override Judgement CreateJudgement() => new Judgement(); public Vector2 Position { get; set; } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs index 0c22554e82..748e6d3b53 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Pippidon.Objects { public class PippidonHitObject : HitObject, IHasPosition { - public override Judgement CreateJudgement() => new Judgement(); + protected override Judgement CreateJudgement() => new Judgement(); public Vector2 Position { get; set; } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/EmptyScrollingHitObject.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/EmptyScrollingHitObject.cs index 9b469be496..4564bd1e09 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/EmptyScrollingHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/EmptyScrollingHitObject.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.EmptyScrolling.Objects { public class EmptyScrollingHitObject : HitObject { - public override Judgement CreateJudgement() => new Judgement(); + protected override Judgement CreateJudgement() => new Judgement(); } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs index 9dd135479f..ed16bce9f6 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Pippidon.Objects /// public int Lane; - public override Judgement CreateJudgement() => new Judgement(); + protected override Judgement CreateJudgement() => new Judgement(); } } diff --git a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs index 584a9e09c0..f0f93f59b5 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs @@ -358,7 +358,7 @@ namespace osu.Game.Tests.Gameplay this.maxResult = maxResult; } - public override Judgement CreateJudgement() => new TestJudgement(maxResult); + protected override Judgement CreateJudgement() => new TestJudgement(maxResult); protected override HitWindows CreateHitWindows() => new HitWindows(); private class TestJudgement : Judgement diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs index 73177e36e1..22643feebb 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs @@ -175,7 +175,7 @@ namespace osu.Game.Tests.Gameplay var hitObject = new HitObject { StartTime = Time.Current }; lifetimeEntry = new HitObjectLifetimeEntry(hitObject) { - Result = new JudgementResult(hitObject, hitObject.CreateJudgement()) + Result = new JudgementResult(hitObject, hitObject.Judgement) { Type = HitResult.Great } diff --git a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs index 1a644ad600..a428979015 100644 --- a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs @@ -129,10 +129,10 @@ namespace osu.Game.Tests.Gameplay var scoreProcessor = new ScoreProcessor(new OsuRuleset()); scoreProcessor.ApplyBeatmap(beatmap); - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], beatmap.HitObjects[0].CreateJudgement()) { Type = HitResult.Ok }); - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], beatmap.HitObjects[1].CreateJudgement()) { Type = HitResult.LargeTickHit }); - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[2], beatmap.HitObjects[2].CreateJudgement()) { Type = HitResult.SmallTickMiss }); - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[3], beatmap.HitObjects[3].CreateJudgement()) { Type = HitResult.SmallBonus }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], beatmap.HitObjects[0].Judgement) { Type = HitResult.Ok }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], beatmap.HitObjects[1].Judgement) { Type = HitResult.LargeTickHit }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[2], beatmap.HitObjects[2].Judgement) { Type = HitResult.SmallTickMiss }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[3], beatmap.HitObjects[3].Judgement) { Type = HitResult.SmallBonus }); var score = new ScoreInfo { Ruleset = new OsuRuleset().RulesetInfo }; scoreProcessor.FailScore(score); @@ -169,8 +169,8 @@ namespace osu.Game.Tests.Gameplay Assert.That(scoreProcessor.MinimumAccuracy.Value, Is.EqualTo(0)); Assert.That(scoreProcessor.MaximumAccuracy.Value, Is.EqualTo(1)); - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], beatmap.HitObjects[0].CreateJudgement()) { Type = HitResult.Ok }); - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], beatmap.HitObjects[1].CreateJudgement()) { Type = HitResult.Great }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], beatmap.HitObjects[0].Judgement) { Type = HitResult.Ok }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], beatmap.HitObjects[1].Judgement) { Type = HitResult.Great }); Assert.That(scoreProcessor.Accuracy.Value, Is.EqualTo((double)(100 + 300) / (2 * 300)).Within(Precision.DOUBLE_EPSILON)); Assert.That(scoreProcessor.MinimumAccuracy.Value, Is.EqualTo((double)(100 + 300) / (4 * 300)).Within(Precision.DOUBLE_EPSILON)); @@ -196,7 +196,7 @@ namespace osu.Game.Tests.Gameplay this.maxResult = maxResult; } - public override Judgement CreateJudgement() => new TestJudgement(maxResult); + protected override Judgement CreateJudgement() => new TestJudgement(maxResult); } } } diff --git a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs index a3f91fffba..ea43a65825 100644 --- a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs +++ b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs @@ -112,7 +112,7 @@ namespace osu.Game.Tests.Rulesets.Scoring for (int i = 0; i < 4; i++) { - var judgementResult = new JudgementResult(fourObjectBeatmap.HitObjects[i], fourObjectBeatmap.HitObjects[i].CreateJudgement()) + var judgementResult = new JudgementResult(fourObjectBeatmap.HitObjects[i], fourObjectBeatmap.HitObjects[i].Judgement) { Type = i == 2 ? minResult : hitResult }; @@ -141,7 +141,7 @@ namespace osu.Game.Tests.Rulesets.Scoring for (int i = 0; i < object_count; ++i) { - var judgementResult = new JudgementResult(largeBeatmap.HitObjects[i], largeBeatmap.HitObjects[i].CreateJudgement()) + var judgementResult = new JudgementResult(largeBeatmap.HitObjects[i], largeBeatmap.HitObjects[i].Judgement) { Type = HitResult.Great }; @@ -325,11 +325,11 @@ namespace osu.Game.Tests.Rulesets.Scoring scoreProcessor = new TestScoreProcessor(); scoreProcessor.ApplyBeatmap(beatmap); - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], beatmap.HitObjects[0].CreateJudgement()) { Type = HitResult.Great }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], beatmap.HitObjects[0].Judgement) { Type = HitResult.Great }); Assert.That(scoreProcessor.Combo.Value, Is.EqualTo(1)); Assert.That(scoreProcessor.Accuracy.Value, Is.EqualTo(1)); - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], beatmap.HitObjects[1].CreateJudgement()) { Type = HitResult.ComboBreak }); + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], beatmap.HitObjects[1].Judgement) { Type = HitResult.ComboBreak }); Assert.That(scoreProcessor.Combo.Value, Is.EqualTo(0)); Assert.That(scoreProcessor.Accuracy.Value, Is.EqualTo(1)); } @@ -350,7 +350,7 @@ namespace osu.Game.Tests.Rulesets.Scoring for (int i = 0; i < beatmap.HitObjects.Count; i++) { - scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[i], beatmap.HitObjects[i].CreateJudgement()) + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[i], beatmap.HitObjects[i].Judgement) { Type = i == 0 ? HitResult.Miss : HitResult.Great }); @@ -441,10 +441,7 @@ namespace osu.Game.Tests.Rulesets.Scoring private readonly HitResult maxResult; private readonly HitResult? minResult; - public override Judgement CreateJudgement() - { - return new TestJudgement(maxResult, minResult); - } + protected override Judgement CreateJudgement() => new TestJudgement(maxResult, minResult); public TestHitObject(HitResult maxResult, HitResult? minResult = null) { From ae5f108f01444dc4c7449858ed77f63ba22d153e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 10 Feb 2024 13:08:26 +0100 Subject: [PATCH 361/915] Add visual test coverage of user profile info section --- osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index bc8f75d4ce..1b9ca8717a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -206,6 +206,12 @@ namespace osu.Game.Tests.Visual.Online Total = 50 }, SupportLevel = 2, + Location = "Somewhere", + Interests = "Rhythm games", + Occupation = "Gamer", + Twitter = "test_user", + Discord = "test_user", + Website = "https://google.com", }; } } From 6894f17b2311019a18cd1553b569998e263981f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 10 Feb 2024 15:34:12 +0100 Subject: [PATCH 362/915] Add test coverage --- .../Editor/TestSceneOsuComposerSelection.cs | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs index 623cefff6b..b97fe5c5a8 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuComposerSelection.cs @@ -124,6 +124,113 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddAssert("selection preserved", () => EditorBeatmap.SelectedHitObjects.Count == 2); } + [Test] + public void TestControlClickAddsControlPointsIfSingleSliderSelected() + { + var firstSlider = new Slider + { + StartTime = 0, + Position = new Vector2(0, 0), + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(100)) + } + } + }; + var secondSlider = new Slider + { + StartTime = 1000, + Position = new Vector2(200, 200), + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(100, -100)) + } + } + }; + + AddStep("add objects", () => EditorBeatmap.AddRange(new HitObject[] { firstSlider, secondSlider })); + AddStep("select first slider", () => EditorBeatmap.SelectedHitObjects.AddRange(new HitObject[] { secondSlider })); + + AddStep("move mouse to middle of slider", () => + { + var pos = blueprintContainer.SelectionBlueprints + .First(s => s.Item == secondSlider) + .ChildrenOfType().First() + .ScreenSpaceDrawQuad.Centre; + + InputManager.MoveMouseTo(pos); + }); + AddStep("control-click left mouse", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); + AddAssert("selection preserved", () => EditorBeatmap.SelectedHitObjects.Count, () => Is.EqualTo(1)); + AddAssert("slider has 3 anchors", () => secondSlider.Path.ControlPoints.Count, () => Is.EqualTo(3)); + } + + [Test] + public void TestControlClickDoesNotAddSliderControlPointsIfMultipleObjectsSelected() + { + var firstSlider = new Slider + { + StartTime = 0, + Position = new Vector2(0, 0), + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(100)) + } + } + }; + var secondSlider = new Slider + { + StartTime = 1000, + Position = new Vector2(200, 200), + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(100, -100)) + } + } + }; + + AddStep("add objects", () => EditorBeatmap.AddRange(new HitObject[] { firstSlider, secondSlider })); + AddStep("select first slider", () => EditorBeatmap.SelectedHitObjects.AddRange(new HitObject[] { firstSlider, secondSlider })); + + AddStep("move mouse to middle of slider", () => + { + var pos = blueprintContainer.SelectionBlueprints + .First(s => s.Item == secondSlider) + .ChildrenOfType().First() + .ScreenSpaceDrawQuad.Centre; + + InputManager.MoveMouseTo(pos); + }); + AddStep("control-click left mouse", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Click(MouseButton.Left); + InputManager.ReleaseKey(Key.ControlLeft); + }); + AddAssert("selection not preserved", () => EditorBeatmap.SelectedHitObjects.Count, () => Is.EqualTo(1)); + AddAssert("second slider not selected", + () => blueprintContainer.SelectionBlueprints.First(s => s.Item == secondSlider).IsSelected, + () => Is.False); + AddAssert("slider still has 2 anchors", () => secondSlider.Path.ControlPoints.Count, () => Is.EqualTo(2)); + } + private ComposeBlueprintContainer blueprintContainer => Editor.ChildrenOfType().First(); From d99187302894c50cee5f84b493e7050f899cc21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 10 Feb 2024 15:54:43 +0100 Subject: [PATCH 363/915] Add note to never run release config to contributing guidelines See https://discord.com/channels/188630481301012481/188630652340404224/1205886296439136286 for the latest instance of this, but this really keeps happening. Maybe someone will read this and stop themselves from making the same mistake. One can dream. --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4106641adb..4f969ab915 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,6 +68,7 @@ Aside from the above, below is a brief checklist of things to watch out when you - Please do not make code changes via the GitHub web interface. - Please add tests for your changes. We expect most new features and bugfixes to have test coverage, unless the effort of adding them is prohibitive. The visual testing methodology we use is described in more detail [here](https://github.com/ppy/osu-framework/wiki/Development-and-Testing). - Please run tests and code style analysis (via `InspectCode.{ps1,sh}` scripts in the root of this repository) before opening the PR. This is particularly important if you're a first-time contributor, as CI will not run for your PR until we allow it to do so. +- Do not run the game in release configuration at any point during your testing (the sole exception to this being benchmarks). Using release is an unnecessary and harmful practice, and can even lead to you losing your local realm database if you start making changes to the schema. The debug configuration has a completely separated full-stack environment, including a development website instance at https://dev.ppy.sh/. It is permitted to register an account on that development instance for testing purposes and not worry about multi-accounting infractions. After you're done with your changes and you wish to open the PR, please observe the following recommendations: From c5f392c17d92ef061d480782ee195726099dab2e Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Sat, 10 Feb 2024 15:25:03 +0000 Subject: [PATCH 364/915] only compute flashlight in osu! difficulty calculations when required --- .../Difficulty/OsuDifficultyCalculator.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 3b580a5b59..007cd977e5 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -40,7 +40,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty double aimRatingNoSliders = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[2].DifficultyValue()) * difficulty_multiplier; double speedNotes = ((Speed)skills[2]).RelevantNoteCount(); - double flashlightRating = Math.Sqrt(skills[3].DifficultyValue()) * difficulty_multiplier; + + double flashlightRating = 0.0; + + if (mods.Any(h => h is OsuModFlashlight)) + flashlightRating = Math.Sqrt(skills[3].DifficultyValue()) * difficulty_multiplier; double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1; @@ -126,13 +130,17 @@ namespace osu.Game.Rulesets.Osu.Difficulty protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) { - return new Skill[] + var skills = new List { new Aim(mods, true), new Aim(mods, false), - new Speed(mods), - new Flashlight(mods) + new Speed(mods) }; + + if (mods.Any(h => h is OsuModFlashlight)) + skills.Add(new Flashlight(mods)); + + return skills.ToArray(); } protected override Mod[] DifficultyAdjustmentMods => new Mod[] From bd04377643d3f42836ff10b6fc6af53728fee215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 10 Feb 2024 16:42:19 +0100 Subject: [PATCH 365/915] Tell people to not run in release harder Co-authored-by: Dean Herbert --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f969ab915..0fe6b6fb4d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,7 +68,7 @@ Aside from the above, below is a brief checklist of things to watch out when you - Please do not make code changes via the GitHub web interface. - Please add tests for your changes. We expect most new features and bugfixes to have test coverage, unless the effort of adding them is prohibitive. The visual testing methodology we use is described in more detail [here](https://github.com/ppy/osu-framework/wiki/Development-and-Testing). - Please run tests and code style analysis (via `InspectCode.{ps1,sh}` scripts in the root of this repository) before opening the PR. This is particularly important if you're a first-time contributor, as CI will not run for your PR until we allow it to do so. -- Do not run the game in release configuration at any point during your testing (the sole exception to this being benchmarks). Using release is an unnecessary and harmful practice, and can even lead to you losing your local realm database if you start making changes to the schema. The debug configuration has a completely separated full-stack environment, including a development website instance at https://dev.ppy.sh/. It is permitted to register an account on that development instance for testing purposes and not worry about multi-accounting infractions. +- **Do not run the game in release configuration at any point during your testing** (the sole exception to this being benchmarks). Using release is an unnecessary and harmful practice, and can even lead to you losing your local realm database if you start making changes to the schema. The debug configuration has a completely separated full-stack environment, including a development website instance at https://dev.ppy.sh/. It is permitted to register an account on that development instance for testing purposes and not worry about multi-accounting infractions. After you're done with your changes and you wish to open the PR, please observe the following recommendations: From 901b82384d5fbc224c18b96347bc3b07e37b0e8b Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Sat, 10 Feb 2024 15:42:55 +0000 Subject: [PATCH 366/915] replace linq usage in `Previous` and `Next` with more direct computation --- .../Difficulty/Preprocessing/DifficultyHitObject.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs b/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs index 9ce0906dea..9785865192 100644 --- a/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs +++ b/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs @@ -4,7 +4,6 @@ #nullable disable using System.Collections.Generic; -using System.Linq; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Difficulty.Preprocessing @@ -65,8 +64,16 @@ namespace osu.Game.Rulesets.Difficulty.Preprocessing EndTime = hitObject.GetEndTime() / clockRate; } - public DifficultyHitObject Previous(int backwardsIndex) => difficultyHitObjects.ElementAtOrDefault(Index - (backwardsIndex + 1)); + public DifficultyHitObject Previous(int backwardsIndex) + { + int index = Index - (backwardsIndex + 1); + return index >= 0 && index < difficultyHitObjects.Count ? difficultyHitObjects[index] : default; + } - public DifficultyHitObject Next(int forwardsIndex) => difficultyHitObjects.ElementAtOrDefault(Index + (forwardsIndex + 1)); + public DifficultyHitObject Next(int forwardsIndex) + { + int index = Index + (forwardsIndex + 1); + return index >= 0 && index < difficultyHitObjects.Count ? difficultyHitObjects[index] : default; + } } } From 7dba21fdaca9d405b1856dcc635a79a4313b91a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 11 Feb 2024 20:05:58 +0800 Subject: [PATCH 367/915] Move init method to bottom of file --- .../LocalCachedBeatmapMetadataSource.cs | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs index ff88fecd86..3f93c32283 100644 --- a/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs +++ b/osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs @@ -49,57 +49,6 @@ namespace osu.Game.Beatmaps prepareLocalCache(); } - private void prepareLocalCache() - { - string cacheFilePath = storage.GetFullPath(cache_database_name); - string compressedCacheFilePath = $@"{cacheFilePath}.bz2"; - - cacheDownloadRequest = new FileWebRequest(compressedCacheFilePath, $@"https://assets.ppy.sh/client-resources/{cache_database_name}.bz2?{DateTimeOffset.UtcNow:yyyyMMdd}"); - - cacheDownloadRequest.Failed += ex => - { - File.Delete(compressedCacheFilePath); - File.Delete(cacheFilePath); - - Logger.Log($@"{nameof(BeatmapUpdaterMetadataLookup)}'s online cache download failed: {ex}", LoggingTarget.Database); - }; - - cacheDownloadRequest.Finished += () => - { - try - { - using (var stream = File.OpenRead(cacheDownloadRequest.Filename)) - using (var outStream = File.OpenWrite(cacheFilePath)) - using (var bz2 = new BZip2Stream(stream, CompressionMode.Decompress, false)) - bz2.CopyTo(outStream); - - // set to null on completion to allow lookups to begin using the new source - cacheDownloadRequest = null; - } - catch (Exception ex) - { - Logger.Log($@"{nameof(LocalCachedBeatmapMetadataSource)}'s online cache extraction failed: {ex}", LoggingTarget.Database); - File.Delete(cacheFilePath); - } - finally - { - File.Delete(compressedCacheFilePath); - } - }; - - Task.Run(async () => - { - try - { - await cacheDownloadRequest.PerformAsync().ConfigureAwait(false); - } - catch - { - // Prevent throwing unobserved exceptions, as they will be logged from the network request to the log file anyway. - } - }); - } - public bool Available => // no download in progress. cacheDownloadRequest == null @@ -173,6 +122,57 @@ namespace osu.Game.Beatmaps return false; } + private void prepareLocalCache() + { + string cacheFilePath = storage.GetFullPath(cache_database_name); + string compressedCacheFilePath = $@"{cacheFilePath}.bz2"; + + cacheDownloadRequest = new FileWebRequest(compressedCacheFilePath, $@"https://assets.ppy.sh/client-resources/{cache_database_name}.bz2?{DateTimeOffset.UtcNow:yyyyMMdd}"); + + cacheDownloadRequest.Failed += ex => + { + File.Delete(compressedCacheFilePath); + File.Delete(cacheFilePath); + + Logger.Log($@"{nameof(BeatmapUpdaterMetadataLookup)}'s online cache download failed: {ex}", LoggingTarget.Database); + }; + + cacheDownloadRequest.Finished += () => + { + try + { + using (var stream = File.OpenRead(cacheDownloadRequest.Filename)) + using (var outStream = File.OpenWrite(cacheFilePath)) + using (var bz2 = new BZip2Stream(stream, CompressionMode.Decompress, false)) + bz2.CopyTo(outStream); + + // set to null on completion to allow lookups to begin using the new source + cacheDownloadRequest = null; + } + catch (Exception ex) + { + Logger.Log($@"{nameof(LocalCachedBeatmapMetadataSource)}'s online cache extraction failed: {ex}", LoggingTarget.Database); + File.Delete(cacheFilePath); + } + finally + { + File.Delete(compressedCacheFilePath); + } + }; + + Task.Run(async () => + { + try + { + await cacheDownloadRequest.PerformAsync().ConfigureAwait(false); + } + catch + { + // Prevent throwing unobserved exceptions, as they will be logged from the network request to the log file anyway. + } + }); + } + private void logForModel(BeatmapSetInfo set, string message) => RealmArchiveModelImporter.LogForModel(set, $@"[{nameof(LocalCachedBeatmapMetadataSource)}] {message}"); From 5e692345dedb62c67914485347943595748cfc9a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 11 Feb 2024 17:44:54 +0300 Subject: [PATCH 368/915] Don't convert pixel data to array --- osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs index acd60b664d..128e100e4b 100644 --- a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs +++ b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs @@ -59,7 +59,7 @@ namespace osu.Game.Beatmaps private TextureUpload limitTextureUploadSize(TextureUpload textureUpload) { - var image = Image.LoadPixelData(textureUpload.Data.ToArray(), textureUpload.Width, textureUpload.Height); + var image = Image.LoadPixelData(textureUpload.Data, textureUpload.Width, textureUpload.Height); // The original texture upload will no longer be returned or used. textureUpload.Dispose(); From ca0819cf7a4529fc27a71d9e9e6ff4ff3a25ff3f Mon Sep 17 00:00:00 2001 From: Stoppedpuma <58333920+Stoppedpuma@users.noreply.github.com> Date: Sun, 11 Feb 2024 20:28:16 +0100 Subject: [PATCH 369/915] Alias "mapper" as well --- osu.Game/Screens/Select/FilterQueryParser.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index f6023c0b61..5d3ff1261f 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -69,6 +69,7 @@ namespace osu.Game.Screens.Select case "creator": case "author": + case "mapper": return TryUpdateCriteriaText(ref criteria.Creator, op, value); case "artist": From 36005a5449d4169edf7d77d948d1b0c0b38e2abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 12 Feb 2024 08:33:08 +0100 Subject: [PATCH 370/915] Fix selected legacy skins crashing on zero-length hold notes Closes https://github.com/ppy/osu/issues/27134. --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index 07045b76ca..a8200e0144 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -243,7 +243,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy bodySprite.FillMode = FillMode.Stretch; // i dunno this looks about right?? - bodySprite.Scale = new Vector2(1, scaleDirection * 32800 / sprite.DrawHeight); + // the guard against zero draw height is intended for zero-length hold notes. yes, such cases have been spotted in the wild. + if (sprite.DrawHeight > 0) + bodySprite.Scale = new Vector2(1, scaleDirection * 32800 / sprite.DrawHeight); } break; From 2ae616a88ea17cc1dc03ab6c0dfa46aeb20f93ee Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 12 Feb 2024 12:29:31 +0300 Subject: [PATCH 371/915] Combine other cases of displaying dash in scores PP --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 2 +- .../BeatmapSet/Scores/TopScoreStatisticsSection.cs | 2 +- .../Profile/Sections/Ranks/DrawableProfileScore.cs | 10 +++++----- .../Drawables/UnrankedPerformancePointsPlaceholder.cs | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index c8ecb38c86..9dd0e26da2 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -181,7 +181,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (showPerformancePoints) { if (!score.Ranked) - content.Add(new UnrankedPerformancePointsPlaceholder { Font = OsuFont.GetFont(size: text_size) }); + content.Add(new UnrankedPerformancePointsPlaceholder(ScoresStrings.StatusNoPp) { Font = OsuFont.GetFont(size: text_size) }); else if (score.PP == null) content.Add(new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(text_size) }); else diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 488b99d620..4aad3cf953 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores ppColumn.Alpha = value.BeatmapInfo!.Status.GrantsPerformancePoints() ? 1 : 0; if (!value.Ranked) - ppColumn.Drawable = new UnrankedPerformancePointsPlaceholder { Font = smallFont }; + ppColumn.Drawable = new UnrankedPerformancePointsPlaceholder(ScoresStrings.StatusNoPp) { Font = smallFont }; else if (value.PP is not double pp) ppColumn.Drawable = new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(smallFont.Size) }; else diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index d1988956be..1211d65816 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; @@ -243,20 +244,19 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks if (Score.Beatmap?.Status.GrantsPerformancePoints() != true) { - return new OsuSpriteText + return new UnrankedPerformancePointsPlaceholder(UsersStrings.ShowExtraTopRanksNotRanked) { Font = OsuFont.GetFont(weight: FontWeight.Bold), - Text = "-", - Colour = colourProvider.Highlight1 + Colour = colourProvider.Highlight1, }; } if (!Score.Ranked) { - return new UnrankedPerformancePointsPlaceholder + return new UnrankedPerformancePointsPlaceholder(ScoresStrings.StatusNoPp) { Font = OsuFont.GetFont(weight: FontWeight.Bold), - Colour = colourProvider.Highlight1 + Colour = colourProvider.Highlight1, }; } diff --git a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs index c5c190e1a1..0097497ef1 100644 --- a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs +++ b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs @@ -5,22 +5,22 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; -using osu.Game.Resources.Localisation.Web; namespace osu.Game.Scoring.Drawables { /// - /// A placeholder used in PP columns for scores that do not award PP. + /// A placeholder used in PP columns for scores that do not award PP due to a reason specified by . /// public partial class UnrankedPerformancePointsPlaceholder : SpriteText, IHasTooltip { - public LocalisableString TooltipText => ScoresStrings.StatusNoPp; + public LocalisableString TooltipText { get; } - public UnrankedPerformancePointsPlaceholder() + public UnrankedPerformancePointsPlaceholder(LocalisableString tooltipText) { Anchor = Anchor.Centre; Origin = Anchor.Centre; Text = "-"; + TooltipText = tooltipText; } } } From 80b14f1aaef3627935873cdc0be2649d588d4f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 20:06:07 +0200 Subject: [PATCH 372/915] Add test coverage for beatmap confusion scenarios --- .../BeatmapUpdaterMetadataLookupTest.cs | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs index 84195f1e7c..e6c06f7aec 100644 --- a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs +++ b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs @@ -193,5 +193,110 @@ namespace osu.Game.Tests.Beatmaps Assert.That(beatmap.OnlineID, Is.EqualTo(123456)); } + + [Test] + public void TestReturnedMetadataHasDifferentOnlineID([Values] bool preferOnlineFetch) + { + var lookupResult = new OnlineBeatmapMetadata { BeatmapID = 654321, BeatmapStatus = BeatmapOnlineStatus.Ranked }; + + var targetMock = preferOnlineFetch ? apiMetadataSourceMock : localCachedMetadataSourceMock; + targetMock.Setup(src => src.Available).Returns(true); + targetMock.Setup(src => src.TryLookup(It.IsAny(), out lookupResult)) + .Returns(true); + + var beatmap = new BeatmapInfo { OnlineID = 123456 }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(beatmap.OnlineID, Is.EqualTo(-1)); + } + + [Test] + public void TestMetadataLookupForBeatmapWithoutPopulatedIDAndCorrectHash([Values] bool preferOnlineFetch) + { + var lookupResult = new OnlineBeatmapMetadata + { + BeatmapID = 654321, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + MD5Hash = @"deadbeef", + }; + + var targetMock = preferOnlineFetch ? apiMetadataSourceMock : localCachedMetadataSourceMock; + targetMock.Setup(src => src.Available).Returns(true); + targetMock.Setup(src => src.TryLookup(It.IsAny(), out lookupResult)) + .Returns(true); + + var beatmap = new BeatmapInfo + { + MD5Hash = @"deadbeef" + }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + Assert.That(beatmap.OnlineID, Is.EqualTo(654321)); + } + + [Test] + public void TestMetadataLookupForBeatmapWithoutPopulatedIDAndIncorrectHash([Values] bool preferOnlineFetch) + { + var lookupResult = new OnlineBeatmapMetadata + { + BeatmapID = 654321, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + MD5Hash = @"cafebabe", + }; + + var targetMock = preferOnlineFetch ? apiMetadataSourceMock : localCachedMetadataSourceMock; + targetMock.Setup(src => src.Available).Returns(true); + targetMock.Setup(src => src.TryLookup(It.IsAny(), out lookupResult)) + .Returns(true); + + var beatmap = new BeatmapInfo + { + MD5Hash = @"deadbeef" + }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(beatmap.OnlineID, Is.EqualTo(-1)); + } + + [Test] + public void TestReturnedMetadataHasDifferentHash([Values] bool preferOnlineFetch) + { + var lookupResult = new OnlineBeatmapMetadata + { + BeatmapID = 654321, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + MD5Hash = @"deadbeef" + }; + + var targetMock = preferOnlineFetch ? apiMetadataSourceMock : localCachedMetadataSourceMock; + targetMock.Setup(src => src.Available).Returns(true); + targetMock.Setup(src => src.TryLookup(It.IsAny(), out lookupResult)) + .Returns(true); + + var beatmap = new BeatmapInfo + { + OnlineID = 654321, + MD5Hash = @"cafebabe", + }; + var beatmapSet = new BeatmapSetInfo(beatmap.Yield()); + beatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch); + + Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(beatmap.OnlineID, Is.EqualTo(654321)); + } } } From 834db989f721a38bb03cf8f8c1f9d24e4e5f0ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 12 Feb 2024 11:03:08 +0100 Subject: [PATCH 373/915] Add more test coverage for more failure --- .../BeatmapUpdaterMetadataLookupTest.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs index e6c06f7aec..fe9d15a89d 100644 --- a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs +++ b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs @@ -298,5 +298,59 @@ namespace osu.Game.Tests.Beatmaps Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); Assert.That(beatmap.OnlineID, Is.EqualTo(654321)); } + + [Test] + public void TestPartiallyModifiedSet([Values] bool preferOnlineFetch) + { + var firstResult = new OnlineBeatmapMetadata + { + BeatmapID = 654321, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + BeatmapSetStatus = BeatmapOnlineStatus.Ranked, + MD5Hash = @"cafebabe" + }; + var secondResult = new OnlineBeatmapMetadata + { + BeatmapID = 666666, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + BeatmapSetStatus = BeatmapOnlineStatus.Ranked, + MD5Hash = @"dededede" + }; + + var targetMock = preferOnlineFetch ? apiMetadataSourceMock : localCachedMetadataSourceMock; + targetMock.Setup(src => src.Available).Returns(true); + targetMock.Setup(src => src.TryLookup(It.Is(bi => bi.OnlineID == 654321), out firstResult)) + .Returns(true); + targetMock.Setup(src => src.TryLookup(It.Is(bi => bi.OnlineID == 666666), out secondResult)) + .Returns(true); + + var firstBeatmap = new BeatmapInfo + { + OnlineID = 654321, + MD5Hash = @"cafebabe", + }; + var secondBeatmap = new BeatmapInfo + { + OnlineID = 666666, + MD5Hash = @"deadbeef" + }; + var beatmapSet = new BeatmapSetInfo(new[] + { + firstBeatmap, + secondBeatmap + }); + firstBeatmap.BeatmapSet = beatmapSet; + secondBeatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch); + + Assert.That(firstBeatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + Assert.That(firstBeatmap.OnlineID, Is.EqualTo(654321)); + + Assert.That(secondBeatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(secondBeatmap.OnlineID, Is.EqualTo(666666)); + + Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + } } } From 4f0ae4197a456dde07cf4aa9868026ef0d9d0918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 12 Feb 2024 11:12:01 +0100 Subject: [PATCH 374/915] Refuse to apply online metadata in the most dodgy scenarios --- osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index b32310990c..13823147b0 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -43,7 +43,7 @@ namespace osu.Game.Beatmaps if (!tryLookup(beatmapInfo, preferOnlineFetch, out var res)) continue; - if (res == null) + if (res == null || shouldDiscardLookupResult(res, beatmapInfo)) { beatmapInfo.ResetOnlineInfo(); continue; @@ -72,6 +72,17 @@ namespace osu.Game.Beatmaps } } + private bool shouldDiscardLookupResult(OnlineBeatmapMetadata result, BeatmapInfo beatmapInfo) + { + if (beatmapInfo.OnlineID > 0 && result.BeatmapID != beatmapInfo.OnlineID) + return true; + + if (beatmapInfo.OnlineID == -1 && result.MD5Hash != beatmapInfo.MD5Hash) + return true; + + return false; + } + /// /// Attempts to retrieve the for the given . /// From 87702b331271d1291ad65d0b4399408dbbf5244e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 12 Feb 2024 11:35:11 +0100 Subject: [PATCH 375/915] Only check online matching when determining whether to save online metadata After https://github.com/ppy/osu/pull/23362 I'm not sure the `LocallyModified` check is doing anything useful. It was confusing me really hard when trying to parse this logic, and it can misbehave (as `None` will also pass the check). --- osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index 13823147b0..f46ce11663 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -57,13 +57,13 @@ namespace osu.Game.Beatmaps beatmapInfo.BeatmapSet.OnlineID = res.BeatmapSetID; // Some metadata should only be applied if there's no local changes. - if (shouldSaveOnlineMetadata(beatmapInfo)) + if (beatmapInfo.MatchesOnlineVersion) { beatmapInfo.Status = res.BeatmapStatus; beatmapInfo.Metadata.Author.OnlineID = res.AuthorID; } - if (beatmapInfo.BeatmapSet.Beatmaps.All(shouldSaveOnlineMetadata)) + if (beatmapInfo.BeatmapSet.Beatmaps.All(b => b.MatchesOnlineVersion)) { beatmapInfo.BeatmapSet.Status = res.BeatmapSetStatus ?? BeatmapOnlineStatus.None; beatmapInfo.BeatmapSet.DateRanked = res.DateRanked; @@ -115,12 +115,6 @@ namespace osu.Game.Beatmaps return false; } - /// - /// Check whether the provided beatmap is in a state where online "ranked" status metadata should be saved against it. - /// Handles the case where a user may have locally modified a beatmap in the editor and expects the local status to stick. - /// - private static bool shouldSaveOnlineMetadata(BeatmapInfo beatmapInfo) => beatmapInfo.MatchesOnlineVersion || beatmapInfo.Status != BeatmapOnlineStatus.LocallyModified; - public void Dispose() { apiMetadataSource.Dispose(); From 133e61a1b223156b986eb45c45fa7e1b16aefefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 12 Feb 2024 11:38:13 +0100 Subject: [PATCH 376/915] Add another test for even more failure --- .../BeatmapUpdaterMetadataLookupTest.cs | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs index fe9d15a89d..74812236bf 100644 --- a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs +++ b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs @@ -352,5 +352,58 @@ namespace osu.Game.Tests.Beatmaps Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.None)); } + + [Test] + public void TestPartiallyMaliciousSet([Values] bool preferOnlineFetch) + { + var firstResult = new OnlineBeatmapMetadata + { + BeatmapID = 654321, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + BeatmapSetStatus = BeatmapOnlineStatus.Ranked, + MD5Hash = @"cafebabe" + }; + var secondResult = new OnlineBeatmapMetadata + { + BeatmapStatus = BeatmapOnlineStatus.Ranked, + BeatmapSetStatus = BeatmapOnlineStatus.Ranked, + MD5Hash = @"dededede" + }; + + var targetMock = preferOnlineFetch ? apiMetadataSourceMock : localCachedMetadataSourceMock; + targetMock.Setup(src => src.Available).Returns(true); + targetMock.Setup(src => src.TryLookup(It.Is(bi => bi.OnlineID == 654321), out firstResult)) + .Returns(true); + targetMock.Setup(src => src.TryLookup(It.Is(bi => bi.OnlineID == 666666), out secondResult)) + .Returns(true); + + var firstBeatmap = new BeatmapInfo + { + OnlineID = 654321, + MD5Hash = @"cafebabe", + }; + var secondBeatmap = new BeatmapInfo + { + OnlineID = 666666, + MD5Hash = @"deadbeef" + }; + var beatmapSet = new BeatmapSetInfo(new[] + { + firstBeatmap, + secondBeatmap + }); + firstBeatmap.BeatmapSet = beatmapSet; + secondBeatmap.BeatmapSet = beatmapSet; + + metadataLookup.Update(beatmapSet, preferOnlineFetch); + + Assert.That(firstBeatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + Assert.That(firstBeatmap.OnlineID, Is.EqualTo(654321)); + + Assert.That(secondBeatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(secondBeatmap.OnlineID, Is.EqualTo(-1)); + + Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + } } } From 138fea8c387190605ba5099b9d3385f4bb6903ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 12 Feb 2024 11:47:30 +0100 Subject: [PATCH 377/915] Only apply set-level metadata after all difficulties have been processed --- .../Beatmaps/BeatmapUpdaterMetadataLookup.cs | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index f46ce11663..f395718a93 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Platform; @@ -38,6 +39,8 @@ namespace osu.Game.Beatmaps /// Whether metadata from an online source should be preferred. If true, the local cache will be skipped to ensure the freshest data state possible. public void Update(BeatmapSetInfo beatmapSet, bool preferOnlineFetch) { + var lookupResults = new List(); + foreach (var beatmapInfo in beatmapSet.Beatmaps) { if (!tryLookup(beatmapInfo, preferOnlineFetch, out var res)) @@ -46,9 +49,12 @@ namespace osu.Game.Beatmaps if (res == null || shouldDiscardLookupResult(res, beatmapInfo)) { beatmapInfo.ResetOnlineInfo(); + lookupResults.Add(null); // mark lookup failure continue; } + lookupResults.Add(res); + beatmapInfo.OnlineID = res.BeatmapID; beatmapInfo.OnlineMD5Hash = res.MD5Hash; beatmapInfo.LastOnlineUpdate = res.LastUpdated; @@ -62,13 +68,17 @@ namespace osu.Game.Beatmaps beatmapInfo.Status = res.BeatmapStatus; beatmapInfo.Metadata.Author.OnlineID = res.AuthorID; } + } - if (beatmapInfo.BeatmapSet.Beatmaps.All(b => b.MatchesOnlineVersion)) - { - beatmapInfo.BeatmapSet.Status = res.BeatmapSetStatus ?? BeatmapOnlineStatus.None; - beatmapInfo.BeatmapSet.DateRanked = res.DateRanked; - beatmapInfo.BeatmapSet.DateSubmitted = res.DateSubmitted; - } + if (beatmapSet.Beatmaps.All(b => b.MatchesOnlineVersion) + && lookupResults.All(r => r != null) + && lookupResults.Select(r => r!.BeatmapSetID).Distinct().Count() == 1) + { + var representative = lookupResults.First()!; + + beatmapSet.Status = representative.BeatmapSetStatus ?? BeatmapOnlineStatus.None; + beatmapSet.DateRanked = representative.DateRanked; + beatmapSet.DateSubmitted = representative.DateSubmitted; } } From e5e0b0e38585f292ce1775f0d4016e9ed55ebec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 12 Feb 2024 11:55:30 +0100 Subject: [PATCH 378/915] Add test coverage for correct setting of beatmap set status --- .../BeatmapUpdaterMetadataLookupTest.cs | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs index 74812236bf..11c4c54ea6 100644 --- a/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs +++ b/osu.Game.Tests/Beatmaps/BeatmapUpdaterMetadataLookupTest.cs @@ -28,7 +28,12 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestLocalCacheQueriedFirst() { - var localLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }; + var localLookupResult = new OnlineBeatmapMetadata + { + BeatmapID = 123456, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + BeatmapSetStatus = BeatmapOnlineStatus.Ranked, + }; localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) .Returns(true); @@ -42,6 +47,7 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: false); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); apiMetadataSourceMock.Verify(src => src.TryLookup(It.IsAny(), out It.Ref.IsAny!), Times.Never); } @@ -54,7 +60,12 @@ namespace osu.Game.Tests.Beatmaps localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) .Returns(false); - var onlineLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }; + var onlineLookupResult = new OnlineBeatmapMetadata + { + BeatmapID = 123456, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + BeatmapSetStatus = BeatmapOnlineStatus.Ranked, + }; apiMetadataSourceMock.Setup(src => src.Available).Returns(true); apiMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out onlineLookupResult)) .Returns(true); @@ -66,6 +77,7 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: false); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); apiMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); } @@ -73,12 +85,22 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestPreferOnlineFetch() { - var localLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }; + var localLookupResult = new OnlineBeatmapMetadata + { + BeatmapID = 123456, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + BeatmapSetStatus = BeatmapOnlineStatus.Ranked, + }; localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) .Returns(true); - var onlineLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Graveyard }; + var onlineLookupResult = new OnlineBeatmapMetadata + { + BeatmapID = 123456, + BeatmapStatus = BeatmapOnlineStatus.Graveyard, + BeatmapSetStatus = BeatmapOnlineStatus.Graveyard, + }; apiMetadataSourceMock.Setup(src => src.Available).Returns(true); apiMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out onlineLookupResult)) .Returns(true); @@ -90,6 +112,7 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: true); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Graveyard)); + Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.Graveyard)); localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Never); apiMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); } @@ -97,7 +120,12 @@ namespace osu.Game.Tests.Beatmaps [Test] public void TestPreferOnlineFetchFallsBackToLocalCacheIfOnlineSourceUnavailable() { - var localLookupResult = new OnlineBeatmapMetadata { BeatmapID = 123456, BeatmapStatus = BeatmapOnlineStatus.Ranked }; + var localLookupResult = new OnlineBeatmapMetadata + { + BeatmapID = 123456, + BeatmapStatus = BeatmapOnlineStatus.Ranked, + BeatmapSetStatus = BeatmapOnlineStatus.Ranked, + }; localCachedMetadataSourceMock.Setup(src => src.Available).Returns(true); localCachedMetadataSourceMock.Setup(src => src.TryLookup(It.IsAny(), out localLookupResult)) .Returns(true); @@ -111,6 +139,7 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: true); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); + Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.Ranked)); localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); apiMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Never); } @@ -135,6 +164,7 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch: false); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.None)); Assert.That(beatmap.OnlineID, Is.EqualTo(-1)); localCachedMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); apiMetadataSourceMock.Verify(src => src.TryLookup(beatmap, out It.Ref.IsAny!), Times.Once); @@ -163,6 +193,7 @@ namespace osu.Game.Tests.Beatmaps metadataLookup.Update(beatmapSet, preferOnlineFetch); Assert.That(beatmap.Status, Is.EqualTo(BeatmapOnlineStatus.None)); + Assert.That(beatmapSet.Status, Is.EqualTo(BeatmapOnlineStatus.None)); Assert.That(beatmap.OnlineID, Is.EqualTo(123456)); } From 1944a12634817ea43888e8ffec7b6359e6499f44 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 12 Feb 2024 21:18:31 +0900 Subject: [PATCH 379/915] allow `ModMuted` to ranked when setting adjusted --- osu.Game/Rulesets/Mods/ModMuted.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 3ecd9aa6a1..7aefefc58d 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mods public override LocalisableString Description => "Can you still feel the rhythm without music?"; public override ModType Type => ModType.Fun; public override double ScoreMultiplier => 1; - public override bool Ranked => UsesDefaultConfiguration; + public override bool Ranked => true; } public abstract class ModMuted : ModMuted, IApplicableToDrawableRuleset, IApplicableToTrack, IApplicableToScoreProcessor From 581ae2f679a00e98ea3e773a9c0c59494b9be8e5 Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Mon, 12 Feb 2024 12:51:35 +0000 Subject: [PATCH 380/915] handle key presses when watching legacy relax replays --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 3679425389..55d8b6f55f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -38,12 +38,17 @@ namespace osu.Game.Rulesets.Osu.Mods private ReplayState state = null!; private double lastStateChangeTime; + private DrawableOsuRuleset ruleset = null!; + private bool hasReplay; + private bool legacyReplay; public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { + ruleset = (DrawableOsuRuleset)drawableRuleset; + // grab the input manager for future use. - osuInputManager = ((DrawableOsuRuleset)drawableRuleset).KeyBindingInputManager; + osuInputManager = ruleset.KeyBindingInputManager; } public void ApplyToPlayer(Player player) @@ -51,6 +56,7 @@ namespace osu.Game.Rulesets.Osu.Mods if (osuInputManager.ReplayInputHandler != null) { hasReplay = true; + legacyReplay = ruleset.ReplayScore.ScoreInfo.IsLegacyScore; return; } @@ -59,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void Update(Playfield playfield) { - if (hasReplay) + if (hasReplay && !legacyReplay) return; bool requiresHold = false; @@ -125,6 +131,20 @@ namespace osu.Game.Rulesets.Osu.Mods isDownState = down; lastStateChangeTime = time; + // legacy replays do not contain key-presses with Relax mod, so they need to be triggered by themselves. + if (legacyReplay) + { + if (!down) + { + osuInputManager.KeyBindingContainer.TriggerReleased(wasLeft ? OsuAction.RightButton : OsuAction.LeftButton); + return; + } + + osuInputManager.KeyBindingContainer.TriggerPressed(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + wasLeft = !wasLeft; + return; + } + state = new ReplayState { PressedActions = new List() From 96711eb185c0692868dc924b6b4368e8e1a8735d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 12 Feb 2024 18:02:34 +0100 Subject: [PATCH 381/915] Add test coverage --- .../NonVisual/Filtering/FilterQueryParserTest.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 739a72df08..899be1e06c 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -274,10 +274,12 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.IsTrue(filterCriteria.OnlineStatus.IsUpperInclusive); } - [Test] - public void TestApplyCreatorQueries() + [TestCase("creator")] + [TestCase("author")] + [TestCase("mapper")] + public void TestApplyCreatorQueries(string keyword) { - const string query = "beatmap specifically by creator=my_fav"; + string query = $"beatmap specifically by {keyword}=my_fav"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual("beatmap specifically by", filterCriteria.SearchText.Trim()); From 2a02566283f831b469a2b37a4a645aae2cb07bc3 Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Mon, 12 Feb 2024 17:45:00 +0000 Subject: [PATCH 382/915] refactor `down` and `wasLeft` management into respective `PressHandler` classes --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 67 +++++++++++++++++------ 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 55d8b6f55f..47b7e543d8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -39,6 +39,7 @@ namespace osu.Game.Rulesets.Osu.Mods private double lastStateChangeTime; private DrawableOsuRuleset ruleset = null!; + private PressHandler pressHandler = null!; private bool hasReplay; private bool legacyReplay; @@ -56,10 +57,16 @@ namespace osu.Game.Rulesets.Osu.Mods if (osuInputManager.ReplayInputHandler != null) { hasReplay = true; + + Debug.Assert(ruleset.ReplayScore != null); legacyReplay = ruleset.ReplayScore.ScoreInfo.IsLegacyScore; + + pressHandler = new LegacyReplayPressHandler(this); + return; } + pressHandler = new PressHandler(this); osuInputManager.AllowGameplayInputs = false; } @@ -131,20 +138,6 @@ namespace osu.Game.Rulesets.Osu.Mods isDownState = down; lastStateChangeTime = time; - // legacy replays do not contain key-presses with Relax mod, so they need to be triggered by themselves. - if (legacyReplay) - { - if (!down) - { - osuInputManager.KeyBindingContainer.TriggerReleased(wasLeft ? OsuAction.RightButton : OsuAction.LeftButton); - return; - } - - osuInputManager.KeyBindingContainer.TriggerPressed(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); - wasLeft = !wasLeft; - return; - } - state = new ReplayState { PressedActions = new List() @@ -152,11 +145,53 @@ namespace osu.Game.Rulesets.Osu.Mods if (down) { - state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + pressHandler.HandlePress(wasLeft); wasLeft = !wasLeft; } + else + { + pressHandler.HandleRelease(wasLeft); + } + } + } - state.Apply(osuInputManager.CurrentState, osuInputManager); + private class PressHandler + { + protected readonly OsuModRelax Mod; + + public PressHandler(OsuModRelax mod) + { + Mod = mod; + } + + public virtual void HandlePress(bool wasLeft) + { + Mod.state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + Mod.state.Apply(Mod.osuInputManager.CurrentState, Mod.osuInputManager); + } + + public virtual void HandleRelease(bool wasLeft) + { + Mod.state.Apply(Mod.osuInputManager.CurrentState, Mod.osuInputManager); + } + } + + // legacy replays do not contain key-presses with Relax mod, so they need to be triggered by themselves. + private class LegacyReplayPressHandler : PressHandler + { + public LegacyReplayPressHandler(OsuModRelax mod) + : base(mod) + { + } + + public override void HandlePress(bool wasLeft) + { + Mod.osuInputManager.KeyBindingContainer.TriggerPressed(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + } + + public override void HandleRelease(bool wasLeft) + { + Mod.osuInputManager.KeyBindingContainer.TriggerReleased(wasLeft ? OsuAction.RightButton : OsuAction.LeftButton); } } } From cc733ea809f3eb1d0887bf8c92605581fd21a9b3 Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Mon, 12 Feb 2024 18:00:05 +0000 Subject: [PATCH 383/915] add inline comment for supposedly backwards ternary --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 47b7e543d8..a5643e5b49 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -191,6 +191,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override void HandleRelease(bool wasLeft) { + // this intentionally releases right when `wasLeft` is true because `wasLeft` is set at point of press and not at point of release Mod.osuInputManager.KeyBindingContainer.TriggerReleased(wasLeft ? OsuAction.RightButton : OsuAction.LeftButton); } } From 4f0f07d55a45be5ff93e271d3adfde3b71945138 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 12 Feb 2024 21:30:10 +0300 Subject: [PATCH 384/915] Remove placeholder classes and inline everything --- .../Graphics/Sprites/SpriteIconWithTooltip.cs | 14 +++++++ .../Graphics/Sprites/SpriteTextWithTooltip.cs | 13 +++++++ .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 20 ++++++++-- .../Scores/TopScoreStatisticsSection.cs | 19 +++++++-- .../Sections/Ranks/DrawableProfileScore.cs | 39 +++++++++++++++---- ...UnprocessedPerformancePointsPlaceholder.cs | 27 ------------- .../UnrankedPerformancePointsPlaceholder.cs | 26 ------------- 7 files changed, 91 insertions(+), 67 deletions(-) create mode 100644 osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs create mode 100644 osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs delete mode 100644 osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs delete mode 100644 osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs diff --git a/osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs b/osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs new file mode 100644 index 0000000000..572a17571b --- /dev/null +++ b/osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs @@ -0,0 +1,14 @@ +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; + +namespace osu.Game.Graphics.Sprites +{ + /// + /// A with a publicly settable tooltip text. + /// + public partial class SpriteIconWithTooltip : SpriteIcon, IHasTooltip + { + public LocalisableString TooltipText { get; set; } + } +} diff --git a/osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs b/osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs new file mode 100644 index 0000000000..db98e8ba57 --- /dev/null +++ b/osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs @@ -0,0 +1,13 @@ +using osu.Framework.Graphics.Cursor; +using osu.Framework.Localisation; + +namespace osu.Game.Graphics.Sprites +{ + /// + /// An with a publicly settable tooltip text. + /// + internal partial class SpriteTextWithTooltip : OsuSpriteText, IHasTooltip + { + public LocalisableString TooltipText { get; set; } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 9dd0e26da2..7a817c43eb 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -23,9 +23,9 @@ using osuTK.Graphics; using osu.Framework.Localisation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; -using osu.Game.Scoring.Drawables; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -181,9 +181,23 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (showPerformancePoints) { if (!score.Ranked) - content.Add(new UnrankedPerformancePointsPlaceholder(ScoresStrings.StatusNoPp) { Font = OsuFont.GetFont(size: text_size) }); + { + content.Add(new SpriteTextWithTooltip + { + Text = "-", + Font = OsuFont.GetFont(size: text_size), + TooltipText = ScoresStrings.StatusNoPp + }); + } else if (score.PP == null) - content.Add(new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(text_size) }); + { + content.Add(new SpriteIconWithTooltip + { + Icon = FontAwesome.Solid.Sync, + Size = new Vector2(text_size), + TooltipText = ScoresStrings.StatusProcessing, + }); + } else content.Add(new StatisticText(score.PP, format: @"N0")); } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 4aad3cf953..17704f63ee 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -22,7 +22,6 @@ using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osu.Game.Scoring.Drawables; using osuTK; namespace osu.Game.Overlays.BeatmapSet.Scores @@ -126,9 +125,23 @@ namespace osu.Game.Overlays.BeatmapSet.Scores ppColumn.Alpha = value.BeatmapInfo!.Status.GrantsPerformancePoints() ? 1 : 0; if (!value.Ranked) - ppColumn.Drawable = new UnrankedPerformancePointsPlaceholder(ScoresStrings.StatusNoPp) { Font = smallFont }; + { + ppColumn.Drawable = new SpriteTextWithTooltip + { + Text = "-", + Font = smallFont, + TooltipText = ScoresStrings.StatusNoPp + }; + } else if (value.PP is not double pp) - ppColumn.Drawable = new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(smallFont.Size) }; + { + ppColumn.Drawable = new SpriteIconWithTooltip + { + Icon = FontAwesome.Solid.Sync, + Size = new Vector2(smallFont.Size), + TooltipText = ScoresStrings.StatusProcessing, + }; + } else ppColumn.Text = pp.ToLocalisableString(@"N0"); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 1211d65816..63afca8b74 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -8,6 +8,7 @@ using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -18,7 +19,6 @@ using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; -using osu.Game.Scoring.Drawables; using osu.Game.Utils; using osuTK; @@ -214,6 +214,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks private Drawable createDrawablePerformance() { + var font = OsuFont.GetFont(weight: FontWeight.Bold); + if (Score.PP.HasValue) { return new FillFlowContainer @@ -226,7 +228,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(weight: FontWeight.Bold), + Font = font, Text = $"{Score.PP:0}", Colour = colourProvider.Highlight1 }, @@ -234,7 +236,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Font = font.With(size: 12), Text = "pp", Colour = colourProvider.Light3 } @@ -244,23 +246,44 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks if (Score.Beatmap?.Status.GrantsPerformancePoints() != true) { - return new UnrankedPerformancePointsPlaceholder(UsersStrings.ShowExtraTopRanksNotRanked) + if (Score.Beatmap?.Status == BeatmapOnlineStatus.Loved) { + return new SpriteIconWithTooltip + { + Icon = FontAwesome.Solid.Heart, + Size = new Vector2(font.Size), + TooltipText = UsersStrings.ShowExtraTopRanksNotRanked, + Colour = colourProvider.Highlight1 + }; + } + + return new SpriteTextWithTooltip + { + Text = "-", Font = OsuFont.GetFont(weight: FontWeight.Bold), - Colour = colourProvider.Highlight1, + TooltipText = UsersStrings.ShowExtraTopRanksNotRanked, + Colour = colourProvider.Highlight1 }; } if (!Score.Ranked) { - return new UnrankedPerformancePointsPlaceholder(ScoresStrings.StatusNoPp) + return new SpriteTextWithTooltip { + Text = "-", Font = OsuFont.GetFont(weight: FontWeight.Bold), - Colour = colourProvider.Highlight1, + TooltipText = ScoresStrings.StatusNoPp, + Colour = colourProvider.Highlight1 }; } - return new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(16), Colour = colourProvider.Highlight1 }; + return new SpriteIconWithTooltip + { + Icon = FontAwesome.Solid.Sync, + Size = new Vector2(font.Size), + TooltipText = ScoresStrings.StatusProcessing, + Colour = colourProvider.Highlight1 + }; } private partial class ScoreBeatmapMetadataContainer : BeatmapMetadataContainer diff --git a/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs b/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs deleted file mode 100644 index a2cb69062e..0000000000 --- a/osu.Game/Scoring/Drawables/UnprocessedPerformancePointsPlaceholder.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable -using osu.Framework.Graphics; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Localisation; -using osu.Game.Resources.Localisation.Web; - -namespace osu.Game.Scoring.Drawables -{ - /// - /// A placeholder used in PP columns for scores with unprocessed PP value. - /// - public partial class UnprocessedPerformancePointsPlaceholder : SpriteIcon, IHasTooltip - { - public LocalisableString TooltipText => ScoresStrings.StatusProcessing; - - public UnprocessedPerformancePointsPlaceholder() - { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - Icon = FontAwesome.Solid.Sync; - } - } -} diff --git a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs b/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs deleted file mode 100644 index 0097497ef1..0000000000 --- a/osu.Game/Scoring/Drawables/UnrankedPerformancePointsPlaceholder.cs +++ /dev/null @@ -1,26 +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 osu.Framework.Graphics; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Localisation; - -namespace osu.Game.Scoring.Drawables -{ - /// - /// A placeholder used in PP columns for scores that do not award PP due to a reason specified by . - /// - public partial class UnrankedPerformancePointsPlaceholder : SpriteText, IHasTooltip - { - public LocalisableString TooltipText { get; } - - public UnrankedPerformancePointsPlaceholder(LocalisableString tooltipText) - { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - Text = "-"; - TooltipText = tooltipText; - } - } -} From 5bebe9fe0d5c5a5110efd1cd145e5dcb93cd92af Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 12 Feb 2024 21:33:16 +0300 Subject: [PATCH 385/915] Add test case for profile scores made on loved beatmaps --- .../Online/TestSceneUserProfileScores.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs index f72980757b..56e4348b65 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs @@ -102,6 +102,24 @@ namespace osu.Game.Tests.Visual.Online Ranked = true, }; + var lovedScore = new SoloScoreInfo + { + Rank = ScoreRank.B, + Beatmap = new APIBeatmap + { + BeatmapSet = new APIBeatmapSet + { + Title = "C18H27NO3(extend)", + Artist = "Team Grimoire", + }, + DifficultyName = "[4K] Cataclysmic Hypernova", + Status = BeatmapOnlineStatus.Loved, + }, + EndedAt = DateTimeOffset.Now, + Accuracy = 0.55879, + Ranked = true, + }; + var unprocessedPPScore = new SoloScoreInfo { Rank = ScoreRank.B, @@ -151,6 +169,7 @@ namespace osu.Game.Tests.Visual.Online new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(firstScore)), new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(secondScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(noPPScore)), + new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(lovedScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(unprocessedPPScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(unrankedPPScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(firstScore, 0.97)), From 2d65dfbf09f1e2c139862a649d363e0c12d37030 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 12 Feb 2024 22:10:36 +0300 Subject: [PATCH 386/915] Fix Rider EAP whoopsie --- osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs | 3 +++ osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs b/osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs index 572a17571b..17f4bf53f9 100644 --- a/osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs +++ b/osu.Game/Graphics/Sprites/SpriteIconWithTooltip.cs @@ -1,3 +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 osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs b/osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs index db98e8ba57..446b621b81 100644 --- a/osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs +++ b/osu.Game/Graphics/Sprites/SpriteTextWithTooltip.cs @@ -1,3 +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 osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; From 5101979ac099b7e590e020020bf3b0a7bf134164 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Tue, 13 Feb 2024 00:34:06 +0000 Subject: [PATCH 387/915] only use `LegacyReplayPressHandler` on legacy replays --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index a5643e5b49..d2e4e0c669 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.Mods Debug.Assert(ruleset.ReplayScore != null); legacyReplay = ruleset.ReplayScore.ScoreInfo.IsLegacyScore; - pressHandler = new LegacyReplayPressHandler(this); + pressHandler = legacyReplay ? new LegacyReplayPressHandler(this) : new PressHandler(this); return; } From 22e9c4a3b59e414a881ceae5abc885389a0af5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 13 Feb 2024 10:19:55 +0100 Subject: [PATCH 388/915] Use private interface rather than weird inheritance --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 38 ++++++++++++++--------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index d2e4e0c669..31511c01b8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Mods private double lastStateChangeTime; private DrawableOsuRuleset ruleset = null!; - private PressHandler pressHandler = null!; + private IPressHandler pressHandler = null!; private bool hasReplay; private bool legacyReplay; @@ -155,44 +155,52 @@ namespace osu.Game.Rulesets.Osu.Mods } } - private class PressHandler + private interface IPressHandler { - protected readonly OsuModRelax Mod; + void HandlePress(bool wasLeft); + void HandleRelease(bool wasLeft); + } + + private class PressHandler : IPressHandler + { + private readonly OsuModRelax mod; public PressHandler(OsuModRelax mod) { - Mod = mod; + this.mod = mod; } - public virtual void HandlePress(bool wasLeft) + public void HandlePress(bool wasLeft) { - Mod.state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); - Mod.state.Apply(Mod.osuInputManager.CurrentState, Mod.osuInputManager); + mod.state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + mod.state.Apply(mod.osuInputManager.CurrentState, mod.osuInputManager); } - public virtual void HandleRelease(bool wasLeft) + public void HandleRelease(bool wasLeft) { - Mod.state.Apply(Mod.osuInputManager.CurrentState, Mod.osuInputManager); + mod.state.Apply(mod.osuInputManager.CurrentState, mod.osuInputManager); } } // legacy replays do not contain key-presses with Relax mod, so they need to be triggered by themselves. - private class LegacyReplayPressHandler : PressHandler + private class LegacyReplayPressHandler : IPressHandler { + private readonly OsuModRelax mod; + public LegacyReplayPressHandler(OsuModRelax mod) - : base(mod) { + this.mod = mod; } - public override void HandlePress(bool wasLeft) + public void HandlePress(bool wasLeft) { - Mod.osuInputManager.KeyBindingContainer.TriggerPressed(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + mod.osuInputManager.KeyBindingContainer.TriggerPressed(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); } - public override void HandleRelease(bool wasLeft) + public void HandleRelease(bool wasLeft) { // this intentionally releases right when `wasLeft` is true because `wasLeft` is set at point of press and not at point of release - Mod.osuInputManager.KeyBindingContainer.TriggerReleased(wasLeft ? OsuAction.RightButton : OsuAction.LeftButton); + mod.osuInputManager.KeyBindingContainer.TriggerReleased(wasLeft ? OsuAction.RightButton : OsuAction.LeftButton); } } } From 1eb04c5190220e97b901ab989985709f1553fa22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 13 Feb 2024 11:24:31 +0100 Subject: [PATCH 389/915] Add failing test coverage for catch --- .../CatchHealthProcessorTest.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs diff --git a/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs new file mode 100644 index 0000000000..8c2d1a91ab --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Catch.Beatmaps; +using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Scoring; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + public class CatchHealthProcessorTest + { + private static readonly object[][] test_cases = + [ + // hitobject, starting HP, fail expected after miss + [new Fruit(), 0.01, true], + [new Droplet(), 0.01, true], + [new TinyDroplet(), 0, true], + [new Banana(), 0, false], + ]; + + [TestCaseSource(nameof(test_cases))] + public void TestFailAfterMinResult(CatchHitObject hitObject, double startingHealth, bool failExpected) + { + var healthProcessor = new CatchHealthProcessor(0); + healthProcessor.ApplyBeatmap(new CatchBeatmap + { + HitObjects = { hitObject } + }); + healthProcessor.Health.Value = startingHealth; + + var result = new CatchJudgementResult(hitObject, hitObject.CreateJudgement()); + result.Type = result.Judgement.MinResult; + healthProcessor.ApplyResult(result); + + Assert.That(healthProcessor.HasFailed, Is.EqualTo(failExpected)); + } + + [TestCaseSource(nameof(test_cases))] + public void TestNoFailAfterMaxResult(CatchHitObject hitObject, double startingHealth, bool _) + { + var healthProcessor = new CatchHealthProcessor(0); + healthProcessor.ApplyBeatmap(new CatchBeatmap + { + HitObjects = { hitObject } + }); + healthProcessor.Health.Value = startingHealth; + + var result = new CatchJudgementResult(hitObject, hitObject.CreateJudgement()); + result.Type = result.Judgement.MaxResult; + healthProcessor.ApplyResult(result); + + Assert.That(healthProcessor.HasFailed, Is.False); + } + } +} From 86801aa51d9716228f24fb4728607f95f2ed8f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 13 Feb 2024 11:57:42 +0100 Subject: [PATCH 390/915] Add failing test coverage for osu! --- .../OsuHealthProcessorTest.cs | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/OsuHealthProcessorTest.cs diff --git a/osu.Game.Rulesets.Osu.Tests/OsuHealthProcessorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuHealthProcessorTest.cs new file mode 100644 index 0000000000..cf93e0ce7b --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/OsuHealthProcessorTest.cs @@ -0,0 +1,66 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Scoring; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class OsuHealthProcessorTest + { + private static readonly object[][] test_cases = + [ + // hitobject, starting HP, fail expected after miss + [new HitCircle(), 0.01, true], + [new SliderHeadCircle(), 0.01, true], + [new SliderHeadCircle { ClassicSliderBehaviour = true }, 0.01, true], + [new SliderTick(), 0.01, true], + [new SliderRepeat(new Slider()), 0.01, true], + [new SliderTailCircle(new Slider()), 0, true], + [new SliderTailCircle(new Slider()) { ClassicSliderBehaviour = true }, 0.01, true], + [new Slider(), 0, true], + [new Slider { ClassicSliderBehaviour = true }, 0.01, true], + [new SpinnerTick(), 0, false], + [new SpinnerBonusTick(), 0, false], + [new Spinner(), 0.01, true], + ]; + + [TestCaseSource(nameof(test_cases))] + public void TestFailAfterMinResult(OsuHitObject hitObject, double startingHealth, bool failExpected) + { + var healthProcessor = new OsuHealthProcessor(0); + healthProcessor.ApplyBeatmap(new OsuBeatmap + { + HitObjects = { hitObject } + }); + healthProcessor.Health.Value = startingHealth; + + var result = new OsuJudgementResult(hitObject, hitObject.CreateJudgement()); + result.Type = result.Judgement.MinResult; + healthProcessor.ApplyResult(result); + + Assert.That(healthProcessor.HasFailed, Is.EqualTo(failExpected)); + } + + [TestCaseSource(nameof(test_cases))] + public void TestNoFailAfterMaxResult(OsuHitObject hitObject, double startingHealth, bool _) + { + var healthProcessor = new OsuHealthProcessor(0); + healthProcessor.ApplyBeatmap(new OsuBeatmap + { + HitObjects = { hitObject } + }); + healthProcessor.Health.Value = startingHealth; + + var result = new OsuJudgementResult(hitObject, hitObject.CreateJudgement()); + result.Type = result.Judgement.MaxResult; + healthProcessor.ApplyResult(result); + + Assert.That(healthProcessor.HasFailed, Is.False); + } + } +} From 441a7b3c2ff68fc13fefb439698e4605f9adacc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 13 Feb 2024 12:07:40 +0100 Subject: [PATCH 391/915] Add precautionary taiko test coverage --- .../TaikoHealthProcessorTest.cs | 82 ++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs index f4a1e888c9..aba967cdd6 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs @@ -147,7 +147,7 @@ namespace osu.Game.Rulesets.Taiko.Tests { HitObjects = { - new DrumRoll { Duration = 2000 } + new Swell { Duration = 2000 } } }; @@ -172,5 +172,85 @@ namespace osu.Game.Rulesets.Taiko.Tests Assert.That(healthProcessor.HasFailed, Is.False); }); } + + [Test] + public void TestMissHitAndHitSwell() + { + var beatmap = new TaikoBeatmap + { + HitObjects = + { + new Hit(), + new Swell { Duration = 2000 } + } + }; + + foreach (var ho in beatmap.HitObjects) + ho.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty); + + var healthProcessor = new TaikoHealthProcessor(); + healthProcessor.ApplyBeatmap(beatmap); + + healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new TaikoJudgement()) { Type = HitResult.Miss }); + + foreach (var nested in beatmap.HitObjects[1].NestedHitObjects) + { + var nestedJudgement = nested.CreateJudgement(); + healthProcessor.ApplyResult(new JudgementResult(nested, nestedJudgement) { Type = nestedJudgement.MaxResult }); + } + + var judgement = beatmap.HitObjects[1].CreateJudgement(); + healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], judgement) { Type = judgement.MaxResult }); + + Assert.Multiple(() => + { + Assert.That(healthProcessor.Health.Value, Is.EqualTo(0)); + Assert.That(healthProcessor.HasFailed, Is.True); + }); + } + + private static readonly object[][] test_cases = + [ + // hitobject, fail expected after miss + [new Hit(), true], + [new Hit.StrongNestedHit(new Hit()), false], + [new DrumRollTick(new DrumRoll()), false], + [new DrumRollTick.StrongNestedHit(new DrumRollTick(new DrumRoll())), false], + [new DrumRoll(), false], + [new SwellTick(), false], + [new Swell(), false] + ]; + + [TestCaseSource(nameof(test_cases))] + public void TestFailAfterMinResult(TaikoHitObject hitObject, bool failExpected) + { + var healthProcessor = new TaikoHealthProcessor(); + healthProcessor.ApplyBeatmap(new TaikoBeatmap + { + HitObjects = { hitObject } + }); + + var result = new JudgementResult(hitObject, hitObject.CreateJudgement()); + result.Type = result.Judgement.MinResult; + healthProcessor.ApplyResult(result); + + Assert.That(healthProcessor.HasFailed, Is.EqualTo(failExpected)); + } + + [TestCaseSource(nameof(test_cases))] + public void TestNoFailAfterMaxResult(TaikoHitObject hitObject, bool _) + { + var healthProcessor = new TaikoHealthProcessor(); + healthProcessor.ApplyBeatmap(new TaikoBeatmap + { + HitObjects = { hitObject } + }); + + var result = new JudgementResult(hitObject, hitObject.CreateJudgement()); + result.Type = result.Judgement.MaxResult; + healthProcessor.ApplyResult(result); + + Assert.That(healthProcessor.HasFailed, Is.False); + } } } From d07ea8f5b12886883a60cf9c477fa9d632404ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 13 Feb 2024 12:17:38 +0100 Subject: [PATCH 392/915] Add failing test coverage for mania --- .../ManiaHealthProcessorTest.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaHealthProcessorTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaHealthProcessorTest.cs index 315849f7de..a9771a46f3 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaHealthProcessorTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaHealthProcessorTest.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Scoring; @@ -27,5 +28,49 @@ namespace osu.Game.Rulesets.Mania.Tests // No matter what, mania doesn't have passive HP drain. Assert.That(processor.DrainRate, Is.Zero); } + + private static readonly object[][] test_cases = + [ + // hitobject, starting HP, fail expected after miss + [new Note(), 0.01, true], + [new HeadNote(), 0.01, true], + [new TailNote(), 0.01, true], + [new HoldNoteBody(), 0, true], // hold note break + [new HoldNote(), 0, true], + ]; + + [TestCaseSource(nameof(test_cases))] + public void TestFailAfterMinResult(ManiaHitObject hitObject, double startingHealth, bool failExpected) + { + var healthProcessor = new ManiaHealthProcessor(0); + healthProcessor.ApplyBeatmap(new ManiaBeatmap(new StageDefinition(4)) + { + HitObjects = { hitObject } + }); + healthProcessor.Health.Value = startingHealth; + + var result = new JudgementResult(hitObject, hitObject.CreateJudgement()); + result.Type = result.Judgement.MinResult; + healthProcessor.ApplyResult(result); + + Assert.That(healthProcessor.HasFailed, Is.EqualTo(failExpected)); + } + + [TestCaseSource(nameof(test_cases))] + public void TestNoFailAfterMaxResult(ManiaHitObject hitObject, double startingHealth, bool _) + { + var healthProcessor = new ManiaHealthProcessor(0); + healthProcessor.ApplyBeatmap(new ManiaBeatmap(new StageDefinition(4)) + { + HitObjects = { hitObject } + }); + healthProcessor.Health.Value = startingHealth; + + var result = new JudgementResult(hitObject, hitObject.CreateJudgement()); + result.Type = result.Judgement.MaxResult; + healthProcessor.ApplyResult(result); + + Assert.That(healthProcessor.HasFailed, Is.False); + } } } From 16d893d40c10542a2502884df95d54773044ffb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 13 Feb 2024 12:26:37 +0100 Subject: [PATCH 393/915] Fix draining processor failing gameplay on bonus misses and ignore hits --- osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs | 5 +++++ osu.Game/Rulesets/Scoring/HealthProcessor.cs | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 629a84ea62..92a064385b 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -142,6 +142,11 @@ namespace osu.Game.Rulesets.Scoring } } + protected override bool CanFailOn(JudgementResult result) + { + return !result.Judgement.MaxResult.IsBonus() && result.Type != HitResult.IgnoreHit; + } + protected override void Reset(bool storeResults) { base.Reset(storeResults); diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index b5eb755650..ccf53f075a 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Scoring Health.Value += GetHealthIncreaseFor(result); - if (meetsAnyFailCondition(result)) + if (CanFailOn(result) && meetsAnyFailCondition(result)) TriggerFailure(); } @@ -68,6 +68,13 @@ namespace osu.Game.Rulesets.Scoring /// The health increase. protected virtual double GetHealthIncreaseFor(JudgementResult result) => result.HealthIncrease; + /// + /// Whether a failure can occur on a given . + /// If the return value of this method is , neither nor will be checked + /// after this . + /// + protected virtual bool CanFailOn(JudgementResult result) => true; + /// /// The default conditions for failing. /// From da4ebd0681e05318d7328fc5be587151233e8f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Feb 2024 10:41:36 +0100 Subject: [PATCH 394/915] Refactor `SoloStatisticsWatcher` to no longer require explicit subscription callbacks --- .../Online/TestSceneSoloStatisticsWatcher.cs | 41 ++++--------- osu.Game/Online/Solo/SoloStatisticsWatcher.cs | 59 +++++-------------- .../TransientUserStatisticsUpdateDisplay.cs | 10 ++++ osu.Game/Screens/Play/SubmittingPlayer.cs | 5 ++ osu.Game/Screens/Ranking/SoloResultsScreen.cs | 24 ++++---- 5 files changed, 56 insertions(+), 83 deletions(-) create mode 100644 osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs index 3607b37c7e..19121b7f58 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs @@ -35,8 +35,6 @@ namespace osu.Game.Tests.Visual.Online private Action? handleGetUsersRequest; private Action? handleGetUserRequest; - private IDisposable? subscription; - private readonly Dictionary<(int userId, string rulesetName), UserStatistics> serverSideStatistics = new Dictionary<(int userId, string rulesetName), UserStatistics>(); [SetUpSteps] @@ -252,26 +250,6 @@ namespace osu.Game.Tests.Visual.Online AddAssert("values after are correct", () => update!.After.TotalScore, () => Is.EqualTo(6_000_000)); } - [Test] - public void TestStatisticsUpdateNotFiredAfterSubscriptionDisposal() - { - int userId = getUserId(); - setUpUser(userId); - - long scoreId = getScoreId(); - var ruleset = new OsuRuleset().RulesetInfo; - - SoloStatisticsUpdate? update = null; - registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); - AddStep("unsubscribe", () => subscription!.Dispose()); - - feignScoreProcessing(userId, ruleset, 5_000_000); - - AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, scoreId)); - AddWaitStep("wait a bit", 5); - AddAssert("update not received", () => update == null); - } - [Test] public void TestGlobalStatisticsUpdatedAfterRegistrationAddedAndScoreProcessed() { @@ -312,13 +290,20 @@ namespace osu.Game.Tests.Visual.Online } private void registerForUpdates(long scoreId, RulesetInfo rulesetInfo, Action onUpdateReady) => - AddStep("register for updates", () => subscription = watcher.RegisterForStatisticsUpdateAfter( - new ScoreInfo(Beatmap.Value.BeatmapInfo, new OsuRuleset().RulesetInfo, new RealmUser()) + AddStep("register for updates", () => + { + watcher.RegisterForStatisticsUpdateAfter( + new ScoreInfo(Beatmap.Value.BeatmapInfo, new OsuRuleset().RulesetInfo, new RealmUser()) + { + Ruleset = rulesetInfo, + OnlineID = scoreId + }); + watcher.LatestUpdate.BindValueChanged(update => { - Ruleset = rulesetInfo, - OnlineID = scoreId - }, - onUpdateReady)); + if (update.NewValue?.Score.OnlineID == scoreId) + onUpdateReady.Invoke(update.NewValue); + }); + }); private void feignScoreProcessing(int userId, RulesetInfo rulesetInfo, long newTotalScore) => AddStep("feign score processing", () => serverSideStatistics[(userId, rulesetInfo.ShortName)] = new UserStatistics { TotalScore = newTotalScore }); diff --git a/osu.Game/Online/Solo/SoloStatisticsWatcher.cs b/osu.Game/Online/Solo/SoloStatisticsWatcher.cs index 55b27fb364..2072e8633f 100644 --- a/osu.Game/Online/Solo/SoloStatisticsWatcher.cs +++ b/osu.Game/Online/Solo/SoloStatisticsWatcher.cs @@ -1,10 +1,10 @@ // 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 osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Game.Extensions; @@ -22,14 +22,16 @@ namespace osu.Game.Online.Solo /// public partial class SoloStatisticsWatcher : Component { + public IBindable LatestUpdate => latestUpdate; + private readonly Bindable latestUpdate = new Bindable(); + [Resolved] private SpectatorClient spectatorClient { get; set; } = null!; [Resolved] private IAPIProvider api { get; set; } = null!; - private readonly Dictionary callbacks = new Dictionary(); - private long? lastProcessedScoreId; + private readonly Dictionary watchedScores = new Dictionary(); private Dictionary? latestStatistics; @@ -45,9 +47,7 @@ namespace osu.Game.Online.Solo /// Registers for a user statistics update after the given has been processed server-side. /// /// The score to listen for the statistics update for. - /// The callback to be invoked once the statistics update has been prepared. - /// An representing the subscription. Disposing it is equivalent to unsubscribing from future notifications. - public IDisposable RegisterForStatisticsUpdateAfter(ScoreInfo score, Action onUpdateReady) + public void RegisterForStatisticsUpdateAfter(ScoreInfo score) { Schedule(() => { @@ -57,24 +57,12 @@ namespace osu.Game.Online.Solo if (!score.Ruleset.IsLegacyRuleset() || score.OnlineID <= 0) return; - var callback = new StatisticsUpdateCallback(score, onUpdateReady); - - if (lastProcessedScoreId == score.OnlineID) - { - requestStatisticsUpdate(api.LocalUser.Value.Id, callback); - return; - } - - callbacks.Add(score.OnlineID, callback); + watchedScores.Add(score.OnlineID, score); }); - - return new InvokeOnDisposal(() => Schedule(() => callbacks.Remove(score.OnlineID))); } private void onUserChanged(APIUser? localUser) => Schedule(() => { - callbacks.Clear(); - lastProcessedScoreId = null; latestStatistics = null; if (localUser == null || localUser.OnlineID <= 1) @@ -107,25 +95,22 @@ namespace osu.Game.Online.Solo if (userId != api.LocalUser.Value?.OnlineID) return; - lastProcessedScoreId = scoreId; - - if (!callbacks.TryGetValue(scoreId, out var callback)) + if (!watchedScores.Remove(scoreId, out var scoreInfo)) return; - requestStatisticsUpdate(userId, callback); - callbacks.Remove(scoreId); + requestStatisticsUpdate(userId, scoreInfo); } - private void requestStatisticsUpdate(int userId, StatisticsUpdateCallback callback) + private void requestStatisticsUpdate(int userId, ScoreInfo scoreInfo) { - var request = new GetUserRequest(userId, callback.Score.Ruleset); - request.Success += user => Schedule(() => dispatchStatisticsUpdate(callback, user.Statistics)); + var request = new GetUserRequest(userId, scoreInfo.Ruleset); + request.Success += user => Schedule(() => dispatchStatisticsUpdate(scoreInfo, user.Statistics)); api.Queue(request); } - private void dispatchStatisticsUpdate(StatisticsUpdateCallback callback, UserStatistics updatedStatistics) + private void dispatchStatisticsUpdate(ScoreInfo scoreInfo, UserStatistics updatedStatistics) { - string rulesetName = callback.Score.Ruleset.ShortName; + string rulesetName = scoreInfo.Ruleset.ShortName; api.UpdateStatistics(updatedStatistics); @@ -135,9 +120,7 @@ namespace osu.Game.Online.Solo latestStatistics.TryGetValue(rulesetName, out UserStatistics? latestRulesetStatistics); latestRulesetStatistics ??= new UserStatistics(); - var update = new SoloStatisticsUpdate(callback.Score, latestRulesetStatistics, updatedStatistics); - callback.OnUpdateReady.Invoke(update); - + latestUpdate.Value = new SoloStatisticsUpdate(scoreInfo, latestRulesetStatistics, updatedStatistics); latestStatistics[rulesetName] = updatedStatistics; } @@ -148,17 +131,5 @@ namespace osu.Game.Online.Solo base.Dispose(isDisposing); } - - private class StatisticsUpdateCallback - { - public ScoreInfo Score { get; } - public Action OnUpdateReady { get; } - - public StatisticsUpdateCallback(ScoreInfo score, Action onUpdateReady) - { - Score = score; - OnUpdateReady = onUpdateReady; - } - } } } diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs new file mode 100644 index 0000000000..3917933958 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -0,0 +1,10 @@ +// 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.Overlays.Toolbar +{ + public class TransientUserStatisticsUpdateDisplay + { + + } +} diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index c8e84f1961..bbd36c05d8 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -17,6 +17,7 @@ using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; +using osu.Game.Online.Solo; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -42,6 +43,9 @@ namespace osu.Game.Screens.Play [Resolved] private SessionStatics statics { get; set; } + [Resolved] + private SoloStatisticsWatcher soloStatisticsWatcher { get; set; } + private readonly object scoreSubmissionLock = new object(); private TaskCompletionSource scoreSubmissionSource; @@ -175,6 +179,7 @@ namespace osu.Game.Screens.Play await submitScore(score).ConfigureAwait(false); spectatorClient.EndPlaying(GameplayState); + soloStatisticsWatcher.RegisterForStatisticsUpdateAfter(score.ScoreInfo); } [Resolved] diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index 22d631e137..cba2fa18c0 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -31,10 +31,7 @@ namespace osu.Game.Screens.Ranking [Resolved] private RulesetStore rulesets { get; set; } = null!; - [Resolved] - private SoloStatisticsWatcher soloStatisticsWatcher { get; set; } = null!; - - private IDisposable? statisticsSubscription; + private IBindable latestUpdate = null!; private readonly Bindable statisticsUpdate = new Bindable(); public SoloResultsScreen(ScoreInfo score, bool allowRetry) @@ -42,14 +39,20 @@ namespace osu.Game.Screens.Ranking { } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load(SoloStatisticsWatcher soloStatisticsWatcher) { - base.LoadComplete(); - - Debug.Assert(Score != null); - if (ShowUserStatistics) - statisticsSubscription = soloStatisticsWatcher.RegisterForStatisticsUpdateAfter(Score, update => statisticsUpdate.Value = update); + { + Debug.Assert(Score != null); + + latestUpdate = soloStatisticsWatcher.LatestUpdate.GetBoundCopy(); + latestUpdate.BindValueChanged(update => + { + if (update.NewValue?.Score.MatchesOnlineID(Score) == true) + statisticsUpdate.Value = update.NewValue; + }); + } } protected override StatisticsPanel CreateStatisticsPanel() @@ -84,7 +87,6 @@ namespace osu.Game.Screens.Ranking base.Dispose(isDisposing); getScoreRequest?.Cancel(); - statisticsSubscription?.Dispose(); } } } From 21b9fb95e28c6c4f7e27467ac301727a00469758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Feb 2024 15:19:38 +0100 Subject: [PATCH 395/915] Move `SoloStatisticsWatcher` to `OsuGame` Doesn't feel like it needs to be in base, and it being in base was causing problems elsewhere before. --- osu.Game/OsuGame.cs | 2 ++ osu.Game/OsuGameBase.cs | 4 ---- osu.Game/Screens/Play/SubmittingPlayer.cs | 5 +++-- osu.Game/Screens/Ranking/SoloResultsScreen.cs | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c244708385..640096a5a8 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -47,6 +47,7 @@ using osu.Game.Localisation; using osu.Game.Online; using osu.Game.Online.Chat; using osu.Game.Online.Rooms; +using osu.Game.Online.Solo; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; using osu.Game.Overlays.Music; @@ -1015,6 +1016,7 @@ namespace osu.Game ScreenStack.Push(CreateLoader().With(l => l.RelativeSizeAxes = Axes.Both)); }); + loadComponentSingleFile(new SoloStatisticsWatcher(), Add, true); loadComponentSingleFile(Toolbar = new Toolbar { OnHome = delegate diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index a2a6322665..81e3d8bed8 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -50,7 +50,6 @@ using osu.Game.Online.API; using osu.Game.Online.Chat; using osu.Game.Online.Metadata; using osu.Game.Online.Multiplayer; -using osu.Game.Online.Solo; using osu.Game.Online.Spectator; using osu.Game.Overlays; using osu.Game.Overlays.Settings; @@ -207,7 +206,6 @@ namespace osu.Game protected MultiplayerClient MultiplayerClient { get; private set; } private MetadataClient metadataClient; - private SoloStatisticsWatcher soloStatisticsWatcher; private RealmAccess realm; @@ -328,7 +326,6 @@ namespace osu.Game dependencies.CacheAs(SpectatorClient = new OnlineSpectatorClient(endpoints)); dependencies.CacheAs(MultiplayerClient = new OnlineMultiplayerClient(endpoints)); dependencies.CacheAs(metadataClient = new OnlineMetadataClient(endpoints)); - dependencies.CacheAs(soloStatisticsWatcher = new SoloStatisticsWatcher()); base.Content.Add(new BeatmapOnlineChangeIngest(beatmapUpdater, realm, metadataClient)); @@ -371,7 +368,6 @@ namespace osu.Game base.Content.Add(SpectatorClient); base.Content.Add(MultiplayerClient); base.Content.Add(metadataClient); - base.Content.Add(soloStatisticsWatcher); base.Content.Add(rulesetConfigCache); diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index bbd36c05d8..c45d46e993 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -43,7 +43,8 @@ namespace osu.Game.Screens.Play [Resolved] private SessionStatics statics { get; set; } - [Resolved] + [Resolved(canBeNull: true)] + [CanBeNull] private SoloStatisticsWatcher soloStatisticsWatcher { get; set; } private readonly object scoreSubmissionLock = new object(); @@ -179,7 +180,7 @@ namespace osu.Game.Screens.Play await submitScore(score).ConfigureAwait(false); spectatorClient.EndPlaying(GameplayState); - soloStatisticsWatcher.RegisterForStatisticsUpdateAfter(score.ScoreInfo); + soloStatisticsWatcher?.RegisterForStatisticsUpdateAfter(score.ScoreInfo); } [Resolved] diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index cba2fa18c0..866440bbd6 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -40,9 +40,9 @@ namespace osu.Game.Screens.Ranking } [BackgroundDependencyLoader] - private void load(SoloStatisticsWatcher soloStatisticsWatcher) + private void load(SoloStatisticsWatcher? soloStatisticsWatcher) { - if (ShowUserStatistics) + if (ShowUserStatistics && soloStatisticsWatcher != null) { Debug.Assert(Score != null); From 14052ae1cc15c45cb81f60fd20341dfcfea7d429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Feb 2024 17:14:15 +0100 Subject: [PATCH 396/915] Implement transient stats display on user toolbar button --- .../Menus/TestSceneToolbarUserButton.cs | 91 ++++++++ .../Overlays/Toolbar/ToolbarUserButton.cs | 7 + .../TransientUserStatisticsUpdateDisplay.cs | 215 +++++++++++++++++- 3 files changed, 311 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs index f0506ed35c..69fedf4a3a 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs @@ -2,12 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; using osu.Game.Online.API; +using osu.Game.Online.Solo; using osu.Game.Overlays.Toolbar; +using osu.Game.Scoring; +using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -87,5 +92,91 @@ namespace osu.Game.Tests.Visual.Menus AddStep($"Change state to {state}", () => dummyAPI.SetState(state)); } } + + [Test] + public void TestTransientUserStatisticsDisplay() + { + AddStep("Log in", () => dummyAPI.Login("wang", "jang")); + AddStep("Gain", () => + { + var transientUpdateDisplay = this.ChildrenOfType().Single(); + transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + new ScoreInfo(), + new UserStatistics + { + GlobalRank = 123_456, + PP = 1234 + }, + new UserStatistics + { + GlobalRank = 111_111, + PP = 1357 + }); + }); + AddStep("Loss", () => + { + var transientUpdateDisplay = this.ChildrenOfType().Single(); + transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + new ScoreInfo(), + new UserStatistics + { + GlobalRank = 111_111, + PP = 1357 + }, + new UserStatistics + { + GlobalRank = 123_456, + PP = 1234 + }); + }); + AddStep("No change", () => + { + var transientUpdateDisplay = this.ChildrenOfType().Single(); + transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + new ScoreInfo(), + new UserStatistics + { + GlobalRank = 111_111, + PP = 1357 + }, + new UserStatistics + { + GlobalRank = 111_111, + PP = 1357 + }); + }); + AddStep("Was null", () => + { + var transientUpdateDisplay = this.ChildrenOfType().Single(); + transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + new ScoreInfo(), + new UserStatistics + { + GlobalRank = null, + PP = null + }, + new UserStatistics + { + GlobalRank = 111_111, + PP = 1357 + }); + }); + AddStep("Became null", () => + { + var transientUpdateDisplay = this.ChildrenOfType().Single(); + transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + new ScoreInfo(), + new UserStatistics + { + GlobalRank = 111_111, + PP = 1357 + }, + new UserStatistics + { + GlobalRank = null, + PP = null + }); + }); + } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 2620e850c8..96c0b15c44 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -78,6 +78,13 @@ namespace osu.Game.Overlays.Toolbar } }); + Flow.Add(new TransientUserStatisticsUpdateDisplay + { + Alpha = 0 + }); + Flow.AutoSizeEasing = Easing.OutQuint; + Flow.AutoSizeDuration = 250; + apiState = api.State.GetBoundCopy(); apiState.BindValueChanged(onlineStateChanged, true); diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index 3917933958..9070ea9030 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -1,10 +1,221 @@ // 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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Solo; +using osu.Game.Resources.Localisation.Web; +using osuTK; + namespace osu.Game.Overlays.Toolbar { - public class TransientUserStatisticsUpdateDisplay + public partial class TransientUserStatisticsUpdateDisplay : CompositeDrawable { - + public Bindable LatestUpdate { get; } = new Bindable(); + + private Statistic globalRank = null!; + private Statistic pp = null!; + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; + Alpha = 0; + + InternalChild = new FillFlowContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Padding = new MarginPadding { Horizontal = 10 }, + Spacing = new Vector2(10), + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + globalRank = new Statistic(UsersStrings.ShowRankGlobalSimple, @"#", Comparer.Create((before, after) => before - after)), + pp = new Statistic(RankingsStrings.StatPerformance, string.Empty, Comparer.Create((before, after) => Math.Sign(after - before))), + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + LatestUpdate.BindValueChanged(val => + { + if (val.NewValue == null) + return; + + var update = val.NewValue; + + // null handling here is best effort because it is annoying. + + globalRank.Alpha = update.After.GlobalRank == null ? 0 : 1; + pp.Alpha = update.After.PP == null ? 0 : 1; + + if (globalRank.Alpha == 0 && pp.Alpha == 0) + return; + + FinishTransforms(true); + + this.FadeIn(500, Easing.OutQuint); + + if (update.After.GlobalRank != null) + { + globalRank.Display( + update.Before.GlobalRank ?? update.After.GlobalRank.Value, + Math.Abs((update.After.GlobalRank.Value - update.Before.GlobalRank) ?? 0), + update.After.GlobalRank.Value); + } + + if (update.After.PP != null) + pp.Display(update.Before.PP ?? update.After.PP.Value, Math.Abs((update.After.PP - update.Before.PP) ?? 0M), update.After.PP.Value); + + this.Delay(4000).FadeOut(500, Easing.OutQuint); + }); + } + + private partial class Statistic : CompositeDrawable + where T : struct, IEquatable, IFormattable + { + private readonly LocalisableString title; + private readonly string mainValuePrefix; + private readonly IComparer valueComparer; + + private Counter mainValue = null!; + private Counter deltaValue = null!; + private OsuSpriteText titleText = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + public Statistic(LocalisableString title, string mainValuePrefix, IComparer valueComparer) + { + this.title = title; + this.mainValuePrefix = mainValuePrefix; + this.valueComparer = valueComparer; + } + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + mainValue = new Counter + { + ValuePrefix = mainValuePrefix, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Font = OsuFont.GetFont(), + }, + new Container + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Children = new Drawable[] + { + deltaValue = new Counter + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Font = OsuFont.GetFont(size: 12, fixedWidth: false, weight: FontWeight.SemiBold), + AlwaysPresent = true, + }, + titleText = new OsuSpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Font = OsuFont.Default.With(size: 12, weight: FontWeight.SemiBold), + Text = title, + AlwaysPresent = true, + } + } + } + } + }; + } + + public void Display(T before, T delta, T after) + { + int comparison = valueComparer.Compare(before, after); + + if (comparison > 0) + { + deltaValue.Colour = colours.Lime1; + deltaValue.ValuePrefix = "+"; + } + else if (comparison < 0) + { + deltaValue.Colour = colours.Red1; + deltaValue.ValuePrefix = "-"; + } + else + { + deltaValue.Colour = Colour4.White; + deltaValue.ValuePrefix = string.Empty; + } + + mainValue.SetCountWithoutRolling(before); + deltaValue.SetCountWithoutRolling(delta); + + titleText.Alpha = 1; + deltaValue.Alpha = 0; + + using (BeginDelayedSequence(1000)) + { + titleText.FadeOut(250, Easing.OutQuint); + deltaValue.FadeIn(250, Easing.OutQuint) + .Then().Delay(1000) + .Then().OnComplete(_ => + { + mainValue.Current.Value = after; + deltaValue.Current.SetDefault(); + }); + } + } + } + + private partial class Counter : RollingCounter + where T : struct, IEquatable, IFormattable + { + public const double ROLLING_DURATION = 500; + + public FontUsage Font { get; init; } = OsuFont.Default; + + public string ValuePrefix + { + get => valuePrefix; + set + { + valuePrefix = value; + UpdateDisplay(); + } + } + + private string valuePrefix = string.Empty; + + protected override LocalisableString FormatCount(T count) => LocalisableString.Format(@"{0}{1:N0}", ValuePrefix, count); + protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = Font); + protected override double RollingDuration => ROLLING_DURATION; + } } } From eae43f5fd90b5aec6a698253c9f82cb6e3f878e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Feb 2024 17:15:52 +0100 Subject: [PATCH 397/915] Consume `SoloStatisticsWatcher` updates in toolbar button --- .../Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs | 5 ++++- osu.Game/Screens/Ranking/ResultsScreen.cs | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index 9070ea9030..e3c1746e14 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Toolbar private Statistic pp = null!; [BackgroundDependencyLoader] - private void load() + private void load(SoloStatisticsWatcher? soloStatisticsWatcher) { RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; @@ -45,6 +45,9 @@ namespace osu.Game.Overlays.Toolbar pp = new Statistic(RankingsStrings.StatPerformance, string.Empty, Comparer.Create((before, after) => Math.Sign(after - before))), } }; + + if (soloStatisticsWatcher != null) + ((IBindable)LatestUpdate).BindTo(soloStatisticsWatcher.LatestUpdate); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 82dade40eb..69cfbed8f2 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -41,9 +41,6 @@ namespace osu.Game.Screens.Ranking public override bool? AllowGlobalTrackControl => true; - // Temporary for now to stop dual transitions. Should respect the current toolbar mode, but there's no way to do so currently. - public override bool HideOverlaysOnEnter => true; - public readonly Bindable SelectedScore = new Bindable(); [CanBeNull] From 62f5251b6ef8eef5f0b1c638621aa0258379fb17 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 13 Feb 2024 11:51:21 +0300 Subject: [PATCH 398/915] Rewrite osu!catch playfield layout containers and apply masking around vertical boundaries --- .../UI/CatchPlayfieldAdjustmentContainer.cs | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs index 11531011ee..1bddd06d87 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs @@ -17,24 +17,29 @@ namespace osu.Game.Rulesets.Catch.UI public CatchPlayfieldAdjustmentContainer() { - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; - - // playfields in stable are positioned vertically at three fourths the difference between the playfield height and the window height in stable. - // we can match that in lazer by using relative coordinates for Y and considering window height to be 1, and playfield height to be 0.8. - RelativePositionAxes = Axes.Y; - Y = (1 - playfield_size_adjust) / 4 * 3; - - Size = new Vector2(playfield_size_adjust); + const float base_game_width = 1024f; + const float base_game_height = 768f; InternalChild = new Container { + // This container limits vertical visibility of the playfield to ensure fairness between wide and tall resolutions (i.e. tall resolutions should not see more fruits). + // Note that the container still extends across the screen horizontally, so that hit explosions at the sides of the playfield do not get cut off. + Name = "Visible area", Anchor = Anchor.Centre, Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - FillAspectRatio = 4f / 3, - Child = content = new ScalingContainer { RelativeSizeAxes = Axes.Both, } + RelativeSizeAxes = Axes.X, + Height = base_game_height, + Masking = true, + Child = new Container + { + Name = "Playable area", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + // playfields in stable are positioned vertically at three fourths the difference between the playfield height and the window height in stable. + Y = base_game_height * ((1 - playfield_size_adjust) / 4 * 3), + Size = new Vector2(base_game_width, base_game_height) * playfield_size_adjust, + Child = content = new ScalingContainer { RelativeSizeAxes = Axes.Both } + }, }; } From 9b17020707a5dd53e45211fd0e5de9a682abf16e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 01:03:21 +0300 Subject: [PATCH 399/915] Adjust "Floating Fruits" in line with layout changes --- osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs | 1 - .../UI/CatchPlayfieldAdjustmentContainer.cs | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs index 9d88c90576..f933b9a28f 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs @@ -21,7 +21,6 @@ namespace osu.Game.Rulesets.Catch.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { drawableRuleset.PlayfieldAdjustmentContainer.Scale = new Vector2(1, -1); - drawableRuleset.PlayfieldAdjustmentContainer.Y = 1 - drawableRuleset.PlayfieldAdjustmentContainer.Y; } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs index 1bddd06d87..64d17b08b6 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs @@ -20,6 +20,9 @@ namespace osu.Game.Rulesets.Catch.UI const float base_game_width = 1024f; const float base_game_height = 768f; + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + InternalChild = new Container { // This container limits vertical visibility of the playfield to ensure fairness between wide and tall resolutions (i.e. tall resolutions should not see more fruits). From a96a66bc9e071f0b8bc2771f194965a23cc62d95 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 02:04:19 +0300 Subject: [PATCH 400/915] Add failing test case --- .../Navigation/TestSceneScreenNavigation.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index f59fbc75ac..8ff4fd5ecf 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -986,6 +986,29 @@ namespace osu.Game.Tests.Visual.Navigation } } + [Test] + public void TestPresentBeatmapAfterDeletion() + { + BeatmapSetInfo beatmap = null; + + Screens.Select.SongSelect songSelect = null; + PushAndConfirm(() => songSelect = new TestPlaySongSelect()); + AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded); + + AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely()); + AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault); + + AddStep("delete selected beatmap", () => + { + beatmap = Game.Beatmap.Value.BeatmapSetInfo; + Game.BeatmapManager.Delete(Game.Beatmap.Value.BeatmapSetInfo); + }); + + AddUntilStep("nothing selected", () => Game.Beatmap.IsDefault); + AddStep("present deleted beatmap", () => Game.PresentBeatmap(beatmap)); + AddAssert("still nothing selected", () => Game.Beatmap.IsDefault); + } + private Func playToResults() { var player = playToCompletion(); From 35649d137ca9fea993c473b7b08d26f53ba13441 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 01:59:45 +0300 Subject: [PATCH 401/915] Ignore soft-deleted beatmaps when trying to present from notification --- osu.Game/OsuGame.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c244708385..11798c22ff 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -630,6 +630,12 @@ namespace osu.Game var detachedSet = databasedSet.PerformRead(s => s.Detach()); + if (detachedSet.DeletePending) + { + Logger.Log("The requested beatmap has since been deleted.", LoggingTarget.Information); + return; + } + PerformFromScreen(screen => { // Find beatmaps that match our predicate. From 5267e0abf788da62e6eaaa1fed1ac35be0fcb428 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 03:38:49 +0300 Subject: [PATCH 402/915] Move comment author line to separate component --- .../Overlays/Comments/CommentAuthorLine.cs | 135 ++++++++++++++++++ osu.Game/Overlays/Comments/DrawableComment.cs | 102 +------------ 2 files changed, 139 insertions(+), 98 deletions(-) create mode 100644 osu.Game/Overlays/Comments/CommentAuthorLine.cs diff --git a/osu.Game/Overlays/Comments/CommentAuthorLine.cs b/osu.Game/Overlays/Comments/CommentAuthorLine.cs new file mode 100644 index 0000000000..b6b5dc00e1 --- /dev/null +++ b/osu.Game/Overlays/Comments/CommentAuthorLine.cs @@ -0,0 +1,135 @@ +// 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.ObjectExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; +using osuTK; + +namespace osu.Game.Overlays.Comments +{ + public partial class CommentAuthorLine : FillFlowContainer + { + private readonly Comment comment; + + private OsuSpriteText deletedLabel = null!; + + public CommentAuthorLine(Comment comment) + { + this.comment = comment; + } + + [BackgroundDependencyLoader] + private void load() + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + Spacing = new Vector2(4, 0); + + Add(new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold)) + { + AutoSizeAxes = Axes.Both + }.With(username => + { + if (comment.UserId.HasValue) + username.AddUserLink(comment.User); + else + username.AddText(comment.LegacyName!); + })); + + if (comment.Pinned) + Add(new PinnedCommentNotice()); + + Add(new ParentUsername(comment)); + + Add(deletedLabel = new OsuSpriteText + { + Alpha = 0f, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), + Text = CommentsStrings.Deleted + }); + } + + public void MarkDeleted() + { + deletedLabel.Show(); + } + + private partial class PinnedCommentNotice : FillFlowContainer + { + public PinnedCommentNotice() + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + Spacing = new Vector2(2, 0); + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.Thumbtack, + Size = new Vector2(14), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), + Text = CommentsStrings.Pinned, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + } + }; + } + } + + private partial class ParentUsername : FillFlowContainer, IHasTooltip + { + public LocalisableString TooltipText => getParentMessage(); + + private readonly Comment? parentComment; + + public ParentUsername(Comment comment) + { + parentComment = comment.ParentComment; + + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + Spacing = new Vector2(3, 0); + Alpha = comment.ParentId == null ? 0 : 1; + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.Solid.Reply, + Size = new Vector2(14), + }, + new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), + Text = parentComment?.User?.Username ?? parentComment?.LegacyName! + } + }; + } + + private LocalisableString getParentMessage() + { + if (parentComment == null) + return string.Empty; + + return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? CommentsStrings.Deleted : string.Empty; + } + } + } +} diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index ceae17aa5d..70b1809c3e 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -4,12 +4,10 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Graphics; -using osu.Framework.Graphics.Sprites; using osuTK; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users.Drawables; using osu.Game.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; using System.Linq; using osu.Game.Graphics.Sprites; @@ -21,7 +19,6 @@ using osu.Framework.Extensions.IEnumerableExtensions; using System.Collections.Specialized; using System.Diagnostics; using osu.Framework.Extensions.LocalisationExtensions; -using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics.UserInterface; @@ -72,7 +69,7 @@ namespace osu.Game.Overlays.Comments private LinkFlowContainer actionsContainer = null!; private LoadingSpinner actionsLoading = null!; private DeletedCommentsCounter deletedCommentsCounter = null!; - private OsuSpriteText deletedLabel = null!; + private CommentAuthorLine author = null!; private GridContainer content = null!; private VotePill votePill = null!; private Container replyEditorContainer = null!; @@ -98,7 +95,6 @@ namespace osu.Game.Overlays.Comments [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider, DrawableComment? parentComment) { - LinkFlowContainer username; FillFlowContainer info; CommentMarkdownContainer message; @@ -174,27 +170,7 @@ namespace osu.Game.Overlays.Comments }, Children = new Drawable[] { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new[] - { - username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold)) - { - AutoSizeAxes = Axes.Both - }, - Comment.Pinned ? new PinnedCommentNotice() : Empty(), - new ParentUsername(Comment), - deletedLabel = new OsuSpriteText - { - Alpha = 0f, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), - Text = CommentsStrings.Deleted - } - } - }, + author = new CommentAuthorLine(Comment), message = new CommentMarkdownContainer { RelativeSizeAxes = Axes.X, @@ -218,7 +194,7 @@ namespace osu.Game.Overlays.Comments { new DrawableDate(Comment.CreatedAt, 12, false) { - Colour = colourProvider.Foreground1 + Colour = colourProvider.Foreground1, } } }, @@ -311,11 +287,6 @@ namespace osu.Game.Overlays.Comments } }; - if (Comment.UserId.HasValue) - username.AddUserLink(Comment.User); - else - username.AddText(Comment.LegacyName!); - if (Comment.EditedAt.HasValue && Comment.EditedUser != null) { var font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular); @@ -400,7 +371,7 @@ namespace osu.Game.Overlays.Comments /// private void makeDeleted() { - deletedLabel.Show(); + author.MarkDeleted(); content.FadeColour(OsuColour.Gray(0.5f)); votePill.Hide(); actionsContainer.Expire(); @@ -547,70 +518,5 @@ namespace osu.Game.Overlays.Comments Top = 10 }; } - - private partial class PinnedCommentNotice : FillFlowContainer - { - public PinnedCommentNotice() - { - AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - Spacing = new Vector2(2, 0); - Children = new Drawable[] - { - new SpriteIcon - { - Icon = FontAwesome.Solid.Thumbtack, - Size = new Vector2(14), - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), - Text = CommentsStrings.Pinned, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - } - }; - } - } - - private partial class ParentUsername : FillFlowContainer, IHasTooltip - { - public LocalisableString TooltipText => getParentMessage(); - - private readonly Comment? parentComment; - - public ParentUsername(Comment comment) - { - parentComment = comment.ParentComment; - - AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - Spacing = new Vector2(3, 0); - Alpha = comment.ParentId == null ? 0 : 1; - Children = new Drawable[] - { - new SpriteIcon - { - Icon = FontAwesome.Solid.Reply, - Size = new Vector2(14), - }, - new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = parentComment?.User?.Username ?? parentComment?.LegacyName! - } - }; - } - - private LocalisableString getParentMessage() - { - if (parentComment == null) - return string.Empty; - - return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? CommentsStrings.Deleted : string.Empty; - } - } } } From c4e358044a5f0478119c39309dd7525483847413 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 03:44:32 +0300 Subject: [PATCH 403/915] Add API models for comment page metadata --- .../API/Requests/Responses/CommentBundle.cs | 3 ++ .../API/Requests/Responses/CommentableMeta.cs | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 osu.Game/Online/API/Requests/Responses/CommentableMeta.cs diff --git a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs index ae8b850723..cbff8bf76c 100644 --- a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs +++ b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs @@ -11,6 +11,9 @@ namespace osu.Game.Online.API.Requests.Responses { public class CommentBundle { + [JsonProperty(@"commentable_meta")] + public List CommentableMeta { get; set; } = new List(); + [JsonProperty(@"comments")] public List Comments { get; set; } diff --git a/osu.Game/Online/API/Requests/Responses/CommentableMeta.cs b/osu.Game/Online/API/Requests/Responses/CommentableMeta.cs new file mode 100644 index 0000000000..1084f1c900 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/CommentableMeta.cs @@ -0,0 +1,28 @@ +// 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; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class CommentableMeta + { + [JsonProperty("id")] + public long Id { get; set; } + + [JsonProperty("owner_id")] + public long? OwnerId { get; set; } + + [JsonProperty("owner_title")] + public string? OwnerTitle { get; set; } + + [JsonProperty("title")] + public string Title { get; set; } = string.Empty; + + [JsonProperty("type")] + public string Type { get; set; } = string.Empty; + + [JsonProperty("url")] + public string Url { get; set; } = string.Empty; + } +} From 72c6134dbff17ba8a7a2ee82a741a61412bdfa1d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 03:46:19 +0300 Subject: [PATCH 404/915] Include commentable object metadata in comments --- osu.Game/Overlays/Comments/CommentsContainer.cs | 8 ++++---- osu.Game/Overlays/Comments/DrawableComment.cs | 4 +++- osu.Game/Overlays/Comments/ReplyCommentEditor.cs | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index b4e9a80ff1..2e5f13aa99 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -301,7 +301,7 @@ namespace osu.Game.Overlays.Comments void addNewComment(Comment comment) { - var drawableComment = GetDrawableComment(comment); + var drawableComment = GetDrawableComment(comment, bundle.CommentableMeta); if (comment.ParentId == null) { @@ -333,7 +333,7 @@ namespace osu.Game.Overlays.Comments if (CommentDictionary.ContainsKey(comment.Id)) continue; - topLevelComments.Add(GetDrawableComment(comment)); + topLevelComments.Add(GetDrawableComment(comment, bundle.CommentableMeta)); } if (topLevelComments.Any()) @@ -351,12 +351,12 @@ namespace osu.Game.Overlays.Comments } } - public DrawableComment GetDrawableComment(Comment comment) + public DrawableComment GetDrawableComment(Comment comment, IReadOnlyList meta) { if (CommentDictionary.TryGetValue(comment.Id, out var existing)) return existing; - return CommentDictionary[comment.Id] = new DrawableComment(comment) + return CommentDictionary[comment.Id] = new DrawableComment(comment, meta) { ShowDeleted = { BindTarget = ShowDeleted }, Sort = { BindTarget = Sort }, diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 70b1809c3e..afb8bdcc8b 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -39,6 +39,7 @@ namespace osu.Game.Overlays.Comments public Action RepliesRequested = null!; public readonly Comment Comment; + public readonly IReadOnlyList Meta; public readonly BindableBool ShowDeleted = new BindableBool(); public readonly Bindable Sort = new Bindable(); @@ -87,9 +88,10 @@ namespace osu.Game.Overlays.Comments [Resolved] private OnScreenDisplay? onScreenDisplay { get; set; } - public DrawableComment(Comment comment) + public DrawableComment(Comment comment, IReadOnlyList meta) { Comment = comment; + Meta = meta; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs index dd4c35ef20..8e9e82507d 100644 --- a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs +++ b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Comments foreach (var comment in cb.Comments) comment.ParentComment = parentComment; - var drawables = cb.Comments.Select(commentsContainer.GetDrawableComment).ToArray(); + var drawables = cb.Comments.Select(c => commentsContainer.GetDrawableComment(c, cb.CommentableMeta)).ToArray(); OnPost?.Invoke(drawables); OnCancel!.Invoke(); From 4d3b605e04d73ff69031d2d4c97ddcd937cb043f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 03:48:45 +0300 Subject: [PATCH 405/915] Add support for displaying "mapper" badges in comments --- .../Overlays/Comments/CommentAuthorLine.cs | 49 ++++++++++++++++++- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentAuthorLine.cs b/osu.Game/Overlays/Comments/CommentAuthorLine.cs index b6b5dc00e1..c269ab4c01 100644 --- a/osu.Game/Overlays/Comments/CommentAuthorLine.cs +++ b/osu.Game/Overlays/Comments/CommentAuthorLine.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -23,12 +22,14 @@ namespace osu.Game.Overlays.Comments public partial class CommentAuthorLine : FillFlowContainer { private readonly Comment comment; + private readonly IReadOnlyList meta; private OsuSpriteText deletedLabel = null!; - public CommentAuthorLine(Comment comment) + public CommentAuthorLine(Comment comment, IReadOnlyList meta) { this.comment = comment; + this.meta = meta; } [BackgroundDependencyLoader] @@ -49,6 +50,17 @@ namespace osu.Game.Overlays.Comments username.AddText(comment.LegacyName!); })); + var ownerMeta = meta.FirstOrDefault(m => m.Id == comment.CommentableId && m.Type == comment.CommentableType); + + if (ownerMeta?.OwnerId != null && ownerMeta.OwnerId == comment.UserId) + { + Add(new OwnerTitleBadge(ownerMeta.OwnerTitle ?? string.Empty) + { + // add top space to align with username + Margin = new MarginPadding { Top = 2f }, + }); + } + if (comment.Pinned) Add(new PinnedCommentNotice()); @@ -67,6 +79,39 @@ namespace osu.Game.Overlays.Comments deletedLabel.Show(); } + private partial class OwnerTitleBadge : CircularContainer + { + private readonly string title; + + public OwnerTitleBadge(string title) + { + this.title = title; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + AutoSizeAxes = Axes.Both; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Light1, + }, + new OsuSpriteText + { + Text = title, + Font = OsuFont.Default.With(size: 10, weight: FontWeight.Bold), + Margin = new MarginPadding { Vertical = 2, Horizontal = 5 }, + Colour = colourProvider.Background6, + }, + }; + } + } + private partial class PinnedCommentNotice : FillFlowContainer { public PinnedCommentNotice() diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index afb8bdcc8b..afd4b96c68 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -172,7 +172,7 @@ namespace osu.Game.Overlays.Comments }, Children = new Drawable[] { - author = new CommentAuthorLine(Comment), + author = new CommentAuthorLine(Comment, Meta), message = new CommentMarkdownContainer { RelativeSizeAxes = Axes.X, From c24af5bfeb65ea125ebdd1c37e8c3e0a296ef78e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 03:49:29 +0300 Subject: [PATCH 406/915] Add test coverage --- .../Online/TestSceneCommentsContainer.cs | 41 ++++++++- .../Visual/Online/TestSceneDrawableComment.cs | 88 ++++++++++--------- .../UserInterface/ThemeComparisonTestScene.cs | 30 ++++--- 3 files changed, 103 insertions(+), 56 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 3d8781d902..fd3552f675 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -170,6 +170,24 @@ namespace osu.Game.Tests.Visual.Online }); } + [Test] + public void TestPostAsOwner() + { + setUpCommentsResponse(getExampleComments()); + AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123)); + + setUpPostResponse(true); + AddStep("enter text", () => editorTextBox.Current.Value = "comm"); + AddStep("submit", () => commentsContainer.ChildrenOfType().Single().ChildrenOfType().First().TriggerClick()); + + AddUntilStep("comment sent", () => + { + string writtenText = editorTextBox.Current.Value; + var comment = commentsContainer.ChildrenOfType().LastOrDefault(); + return comment != null && comment.ChildrenOfType().Any(y => y.Text == writtenText) && comment.ChildrenOfType().Any(y => y.Text == "MAPPER"); + }); + } + private void setUpCommentsResponse(CommentBundle commentBundle) => AddStep("set up response", () => { @@ -183,7 +201,7 @@ namespace osu.Game.Tests.Visual.Online }; }); - private void setUpPostResponse() + private void setUpPostResponse(bool asOwner = false) => AddStep("set up response", () => { dummyAPI.HandleRequest = request => @@ -191,7 +209,7 @@ namespace osu.Game.Tests.Visual.Online if (!(request is CommentPostRequest req)) return false; - req.TriggerSuccess(new CommentBundle + var bundle = new CommentBundle { Comments = new List { @@ -202,9 +220,26 @@ namespace osu.Game.Tests.Visual.Online LegacyName = "FirstUser", CreatedAt = DateTimeOffset.Now, VotesCount = 98, + CommentableId = 2001, + CommentableType = "test", } } - }); + }; + + if (asOwner) + { + bundle.Comments[0].UserId = 1001; + bundle.Comments[0].User = new APIUser { Id = 1001, Username = "FirstUser" }; + bundle.CommentableMeta.Add(new CommentableMeta + { + Id = 2001, + OwnerId = 1001, + OwnerTitle = "MAPPER", + Type = "test", + }); + } + + req.TriggerSuccess(bundle); return true; }; }); diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index 5e83dd4fb3..6f09e4c1f6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -4,62 +4,66 @@ #nullable disable using System; -using NUnit.Framework; -using osu.Framework.Allocation; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Overlays; using osu.Game.Overlays.Comments; +using osu.Game.Tests.Visual.UserInterface; namespace osu.Game.Tests.Visual.Online { - public partial class TestSceneDrawableComment : OsuTestScene + public partial class TestSceneDrawableComment : ThemeComparisonTestScene { - [Cached] - private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); - - private Container container; - - [SetUp] - public void SetUp() => Schedule(() => + public TestSceneDrawableComment() + : base(false) { - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background4, - }, - container = new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - }; - }); - - [TestCaseSource(nameof(comments))] - public void TestComment(string description, string text) - { - AddStep(description, () => - { - comment.Pinned = description == "Pinned"; - comment.Message = text; - container.Add(new DrawableComment(comment)); - }); } - private static readonly Comment comment = new Comment + protected override Drawable CreateContent() => new OsuScrollContainer(Direction.Vertical) { - Id = 1, - LegacyName = "Test User", - CreatedAt = DateTimeOffset.Now, - VotesCount = 0, + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + ChildrenEnumerable = comments.Select(info => + { + var comment = new Comment + { + Id = 1, + UserId = 1000, + User = new APIUser { Id = 1000, Username = "Someone" }, + CreatedAt = DateTimeOffset.Now, + VotesCount = 0, + Pinned = info[0] == "Pinned", + Message = info[1], + CommentableId = 2001, + CommentableType = "test" + }; + + return new[] + { + new DrawableComment(comment, Array.Empty()), + new DrawableComment(comment, new[] + { + new CommentableMeta + { + Id = 2001, + OwnerId = comment.UserId, + OwnerTitle = "MAPPER", + Type = "test", + }, + new CommentableMeta { Title = "Other Meta" }, + }), + }; + }).SelectMany(c => c) + } }; - private static object[] comments = + private static readonly string[][] comments = { new[] { "Plain", "This is plain comment" }, new[] { "Pinned", "This is pinned comment" }, diff --git a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs index 2c894eacab..f0c4b5543f 100644 --- a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs +++ b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs @@ -14,31 +14,39 @@ namespace osu.Game.Tests.Visual.UserInterface { public abstract partial class ThemeComparisonTestScene : OsuGridTestScene { - protected ThemeComparisonTestScene() - : base(1, 2) + private readonly bool showNoColourProvider; + + protected ThemeComparisonTestScene(bool showNoColourProvider = true) + : base(1, showNoColourProvider ? 2 : 1) { + this.showNoColourProvider = showNoColourProvider; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - Cell(0, 0).AddRange(new[] + if (showNoColourProvider) { - new Box + Cell(0, 0).AddRange(new[] { - RelativeSizeAxes = Axes.Both, - Colour = colours.GreySeaFoam - }, - CreateContent() - }); + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.GreySeaFoam + }, + CreateContent() + }); + } } protected void CreateThemedContent(OverlayColourScheme colourScheme) { var colourProvider = new OverlayColourProvider(colourScheme); - Cell(0, 1).Clear(); - Cell(0, 1).Add(new DependencyProvidingContainer + int col = showNoColourProvider ? 1 : 0; + + Cell(0, col).Clear(); + Cell(0, col).Add(new DependencyProvidingContainer { RelativeSizeAxes = Axes.Both, CachedDependencies = new (Type, object)[] From 02de9122d4466d2a30a915bbbc19e5f143fec824 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Feb 2024 07:17:05 +0300 Subject: [PATCH 407/915] Remove behaviour of flipping catcher plate on direction change --- .../TestSceneCatchSkinConfiguration.cs | 111 ------------------ .../Skinning/CatchSkinConfiguration.cs | 13 -- .../Legacy/CatchLegacySkinTransformer.cs | 13 -- osu.Game.Rulesets.Catch/UI/Catcher.cs | 10 +- 4 files changed, 1 insertion(+), 146 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs delete mode 100644 osu.Game.Rulesets.Catch/Skinning/CatchSkinConfiguration.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs deleted file mode 100644 index e2fc31d869..0000000000 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using System.Linq; -using NUnit.Framework; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Testing; -using osu.Framework.Utils; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Catch.Judgements; -using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Catch.Objects.Drawables; -using osu.Game.Rulesets.Catch.Skinning; -using osu.Game.Rulesets.Catch.UI; -using osu.Game.Skinning; -using osu.Game.Tests.Visual; -using Direction = osu.Game.Rulesets.Catch.UI.Direction; - -namespace osu.Game.Rulesets.Catch.Tests -{ - public partial class TestSceneCatchSkinConfiguration : OsuTestScene - { - private Catcher catcher; - - private readonly Container container; - - public TestSceneCatchSkinConfiguration() - { - Add(container = new Container { RelativeSizeAxes = Axes.Both }); - } - - [TestCase(false)] - [TestCase(true)] - public void TestCatcherPlateFlipping(bool flip) - { - AddStep("setup catcher", () => - { - var skin = new TestSkin { FlipCatcherPlate = flip }; - container.Child = new SkinProvidingContainer(skin) - { - Child = catcher = new Catcher(new DroppedObjectContainer()) - { - Anchor = Anchor.Centre - } - }; - }); - - Fruit fruit = new Fruit(); - - AddStep("catch fruit", () => catchFruit(fruit, 20)); - - float position = 0; - - AddStep("record fruit position", () => position = getCaughtObjectPosition(fruit)); - - AddStep("face left", () => catcher.VisualDirection = Direction.Left); - - if (flip) - AddAssert("fruit position changed", () => !Precision.AlmostEquals(getCaughtObjectPosition(fruit), position)); - else - AddAssert("fruit position unchanged", () => Precision.AlmostEquals(getCaughtObjectPosition(fruit), position)); - - AddStep("face right", () => catcher.VisualDirection = Direction.Right); - - AddAssert("fruit position restored", () => Precision.AlmostEquals(getCaughtObjectPosition(fruit), position)); - } - - private float getCaughtObjectPosition(Fruit fruit) - { - var caughtObject = catcher.ChildrenOfType().Single(c => c.HitObject == fruit); - return caughtObject.Parent!.ToSpaceOfOtherDrawable(caughtObject.Position, catcher).X; - } - - private void catchFruit(Fruit fruit, float x) - { - fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - var drawableFruit = new DrawableFruit(fruit) { X = x }; - var judgement = fruit.CreateJudgement(); - catcher.OnNewResult(drawableFruit, new CatchJudgementResult(fruit, judgement) - { - Type = judgement.MaxResult - }); - } - - private class TestSkin : TrianglesSkin - { - public bool FlipCatcherPlate { get; set; } - - public TestSkin() - : base(null!) - { - } - - public override IBindable GetConfig(TLookup lookup) - { - if (lookup is CatchSkinConfiguration config) - { - if (config == CatchSkinConfiguration.FlipCatcherPlate) - return SkinUtils.As(new Bindable(FlipCatcherPlate)); - } - - return base.GetConfig(lookup); - } - } - } -} diff --git a/osu.Game.Rulesets.Catch/Skinning/CatchSkinConfiguration.cs b/osu.Game.Rulesets.Catch/Skinning/CatchSkinConfiguration.cs deleted file mode 100644 index ea8d742b1a..0000000000 --- a/osu.Game.Rulesets.Catch/Skinning/CatchSkinConfiguration.cs +++ /dev/null @@ -1,13 +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.Rulesets.Catch.Skinning -{ - public enum CatchSkinConfiguration - { - /// - /// Whether the contents of the catcher plate should be visually flipped when the catcher direction is changed. - /// - FlipCatcherPlate - } -} diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs index fb8af9bdb6..d1ef47cf17 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs @@ -122,19 +122,6 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy result.Value = LegacyColourCompatibility.DisallowZeroAlpha(result.Value); return (IBindable)result; - - case CatchSkinConfiguration config: - switch (config) - { - case CatchSkinConfiguration.FlipCatcherPlate: - // Don't flip catcher plate contents if the catcher is provided by this legacy skin. - if (GetDrawableComponent(new CatchSkinComponentLookup(CatchSkinComponents.Catcher)) != null) - return (IBindable)new Bindable(); - - break; - } - - break; } return base.GetConfig(lookup); diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 147850a9b7..dca01fc61a 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -112,11 +112,6 @@ namespace osu.Game.Rulesets.Catch.UI public Vector2 BodyScale => Scale * body.Scale; - /// - /// Whether the contents of the catcher plate should be visually flipped when the catcher direction is changed. - /// - private bool flipCatcherPlate; - /// /// Width of the area that can be used to attempt catches during gameplay. /// @@ -339,8 +334,6 @@ namespace osu.Game.Rulesets.Catch.UI skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? DEFAULT_HYPER_DASH_COLOUR; - flipCatcherPlate = skin.GetConfig(CatchSkinConfiguration.FlipCatcherPlate)?.Value ?? true; - runHyperDashStateTransition(HyperDashing); } @@ -352,8 +345,7 @@ namespace osu.Game.Rulesets.Catch.UI body.Scale = scaleFromDirection; // Inverse of catcher scale is applied here, as catcher gets scaled by circle size and so do the incoming fruit. - caughtObjectContainer.Scale = (1 / Scale.X) * (flipCatcherPlate ? scaleFromDirection : Vector2.One); - hitExplosionContainer.Scale = flipCatcherPlate ? scaleFromDirection : Vector2.One; + caughtObjectContainer.Scale = new Vector2(1 / Scale.X); // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || From 3d8d0f8430487c4c30e8964f11e52e1a6522f098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 08:37:20 +0100 Subject: [PATCH 408/915] Update test expectations for catch --- osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs index 8c2d1a91ab..d0a8ce4bbc 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests // hitobject, starting HP, fail expected after miss [new Fruit(), 0.01, true], [new Droplet(), 0.01, true], - [new TinyDroplet(), 0, true], + [new TinyDroplet(), 0, false], [new Banana(), 0, false], ]; From f53bce8ff785a1c52bcd1bffb365e43287ec8bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 08:38:39 +0100 Subject: [PATCH 409/915] Fix catch health processor allowing fail on tiny droplet Closes https://github.com/ppy/osu/issues/27159. In today's episode of "just stable things"... --- .../Scoring/CatchHealthProcessor.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs index c3cc488941..2e1aec0803 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; @@ -21,6 +22,19 @@ namespace osu.Game.Rulesets.Catch.Scoring protected override IEnumerable EnumerateNestedHitObjects(HitObject hitObject) => Enumerable.Empty(); + protected override bool CanFailOn(JudgementResult result) + { + // matches stable. + // see: https://github.com/peppy/osu-stable-reference/blob/46cd3a10af7cc6cc96f4eba92ef1812dc8c3a27e/osu!/GameModes/Play/Rulesets/Ruleset.cs#L967 + // the above early-return skips the failure check at the end of the same method: + // https://github.com/peppy/osu-stable-reference/blob/46cd3a10af7cc6cc96f4eba92ef1812dc8c3a27e/osu!/GameModes/Play/Rulesets/Ruleset.cs#L1232 + // making it impossible to fail on a tiny droplet regardless of result. + if (result.Type == HitResult.SmallTickMiss) + return false; + + return base.CanFailOn(result); + } + protected override double GetHealthIncreaseFor(HitObject hitObject, HitResult result) { double increase = 0; From 2981ebe3d5725e4e26ad2d7b9ec22b9afe87fdf5 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 14 Feb 2024 17:13:44 +0900 Subject: [PATCH 410/915] Fix inspection --- .../Rulesets/TestSceneRulesetSkinProvidingContainer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs index 11f3fe660d..981258e8d1 100644 --- a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs +++ b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs @@ -43,13 +43,13 @@ namespace osu.Game.Tests.Rulesets AddStep("setup provider", () => { - var rulesetSkinProvider = new RulesetSkinProvidingContainer(Ruleset.Value.CreateInstance(), Beatmap.Value.Beatmap, Beatmap.Value.Skin); - - rulesetSkinProvider.Add(requester = new SkinRequester()); - + requester = new SkinRequester(); requester.OnLoadAsync += () => textureOnLoad = requester.GetTexture("test-image"); - Child = rulesetSkinProvider; + Child = new RulesetSkinProvidingContainer(Ruleset.Value.CreateInstance(), Beatmap.Value.Beatmap, Beatmap.Value.Skin) + { + requester + }; }); AddAssert("requester got correct initial texture", () => textureOnLoad != null); From 6baa0999065adc10f3b61ee527fecc614f6fa1f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 10:12:01 +0100 Subject: [PATCH 411/915] Fix broken delay --- .../Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index e3c1746e14..bec5170377 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -188,7 +188,7 @@ namespace osu.Game.Overlays.Toolbar titleText.FadeOut(250, Easing.OutQuint); deltaValue.FadeIn(250, Easing.OutQuint) .Then().Delay(1000) - .Then().OnComplete(_ => + .Then().Schedule(() => { mainValue.Current.Value = after; deltaValue.Current.SetDefault(); From 153024e61b52dc60f7dba39ffc8b131db743fbf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 10:15:27 +0100 Subject: [PATCH 412/915] Increase transition durations slightly Maybe slightly better readability. Dunno. --- .../Toolbar/TransientUserStatisticsUpdateDisplay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index bec5170377..9960dd4411 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -84,7 +84,7 @@ namespace osu.Game.Overlays.Toolbar if (update.After.PP != null) pp.Display(update.Before.PP ?? update.After.PP.Value, Math.Abs((update.After.PP - update.Before.PP) ?? 0M), update.After.PP.Value); - this.Delay(4000).FadeOut(500, Easing.OutQuint); + this.Delay(5000).FadeOut(500, Easing.OutQuint); }); } @@ -183,11 +183,11 @@ namespace osu.Game.Overlays.Toolbar titleText.Alpha = 1; deltaValue.Alpha = 0; - using (BeginDelayedSequence(1000)) + using (BeginDelayedSequence(1500)) { titleText.FadeOut(250, Easing.OutQuint); deltaValue.FadeIn(250, Easing.OutQuint) - .Then().Delay(1000) + .Then().Delay(1500) .Then().Schedule(() => { mainValue.Current.Value = after; From d189fa0f6907afbe9f8a83a10c6a712e793a9efb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 11:53:41 +0100 Subject: [PATCH 413/915] Rename flag --- .../Visual/UserInterface/ThemeComparisonTestScene.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs index f0c4b5543f..3177695f44 100644 --- a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs +++ b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs @@ -14,18 +14,18 @@ namespace osu.Game.Tests.Visual.UserInterface { public abstract partial class ThemeComparisonTestScene : OsuGridTestScene { - private readonly bool showNoColourProvider; + private readonly bool showWithoutColourProvider; - protected ThemeComparisonTestScene(bool showNoColourProvider = true) - : base(1, showNoColourProvider ? 2 : 1) + protected ThemeComparisonTestScene(bool showWithoutColourProvider = true) + : base(1, showWithoutColourProvider ? 2 : 1) { - this.showNoColourProvider = showNoColourProvider; + this.showWithoutColourProvider = showWithoutColourProvider; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - if (showNoColourProvider) + if (showWithoutColourProvider) { Cell(0, 0).AddRange(new[] { @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.UserInterface { var colourProvider = new OverlayColourProvider(colourScheme); - int col = showNoColourProvider ? 1 : 0; + int col = showWithoutColourProvider ? 1 : 0; Cell(0, col).Clear(); Cell(0, col).Add(new DependencyProvidingContainer From 8312f92b4ea24a981b6916f5207aaaf747471546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 12:24:28 +0100 Subject: [PATCH 414/915] Use better value for alignment --- osu.Game/Overlays/Comments/CommentAuthorLine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/CommentAuthorLine.cs b/osu.Game/Overlays/Comments/CommentAuthorLine.cs index c269ab4c01..1f6fef4df3 100644 --- a/osu.Game/Overlays/Comments/CommentAuthorLine.cs +++ b/osu.Game/Overlays/Comments/CommentAuthorLine.cs @@ -57,7 +57,7 @@ namespace osu.Game.Overlays.Comments Add(new OwnerTitleBadge(ownerMeta.OwnerTitle ?? string.Empty) { // add top space to align with username - Margin = new MarginPadding { Top = 2f }, + Margin = new MarginPadding { Top = 1f }, }); } From 68247fa022c0ba3cbab5fe3c92457e11fb48c4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 13:21:37 +0100 Subject: [PATCH 415/915] Fix typo in json property name Would cause the mapper badge to never actually be shown in the real world. --- osu.Game/Online/API/Requests/Responses/Comment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 907632186c..e6a5559d1f 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -33,7 +33,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"votes_count")] public int VotesCount { get; set; } - [JsonProperty(@"commenatble_type")] + [JsonProperty(@"commentable_type")] public string CommentableType { get; set; } = null!; [JsonProperty(@"commentable_id")] From 2c0a5b7ef54169412c805ad4b05ea47cf131c012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 14:21:48 +0100 Subject: [PATCH 416/915] Fix missing tiny droplet not triggering fail with perfect on Stable does this: https://github.com/peppy/osu-stable-reference/blob/46cd3a10af7cc6cc96f4eba92ef1812dc8c3a27e/osu!/GameplayElements/HitObjectManagerFruits.cs#L98-L102 I'd rather not say what I think about it doing that, since it's likely to be unpublishable, but to approximate that, just make it so that only the "default fail condition" is beholden to the weird ebbs and flows of what the ruleset wants. This appears to fix the problem case and I'm hoping it doesn't break something else but I'm like 50/50 on it happening anyway at this point. Just gotta add tests add nauseam. --- .../Scoring/CatchHealthProcessor.cs | 4 ++-- .../Scoring/AccumulatingHealthProcessor.cs | 4 +++- .../Scoring/DrainingHealthProcessor.cs | 7 +++++-- osu.Game/Rulesets/Scoring/HealthProcessor.cs | 18 ++++++------------ 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs index 2e1aec0803..2f55f9a85f 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.Scoring protected override IEnumerable EnumerateNestedHitObjects(HitObject hitObject) => Enumerable.Empty(); - protected override bool CanFailOn(JudgementResult result) + protected override bool CheckDefaultFailCondition(JudgementResult result) { // matches stable. // see: https://github.com/peppy/osu-stable-reference/blob/46cd3a10af7cc6cc96f4eba92ef1812dc8c3a27e/osu!/GameModes/Play/Rulesets/Ruleset.cs#L967 @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.Scoring if (result.Type == HitResult.SmallTickMiss) return false; - return base.CanFailOn(result); + return base.CheckDefaultFailCondition(result); } protected override double GetHealthIncreaseFor(HitObject hitObject, HitResult result) diff --git a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs index 422bf8ea79..bb4c2463a7 100644 --- a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs @@ -1,6 +1,8 @@ // 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.Rulesets.Judgements; + namespace osu.Game.Rulesets.Scoring { /// @@ -9,7 +11,7 @@ namespace osu.Game.Rulesets.Scoring /// public partial class AccumulatingHealthProcessor : HealthProcessor { - protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value < requiredHealth; + protected override bool CheckDefaultFailCondition(JudgementResult _) => JudgedHits == MaxHits && Health.Value < requiredHealth; private readonly double requiredHealth; diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 92a064385b..e72a8aaf67 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -142,9 +142,12 @@ namespace osu.Game.Rulesets.Scoring } } - protected override bool CanFailOn(JudgementResult result) + protected override bool CheckDefaultFailCondition(JudgementResult result) { - return !result.Judgement.MaxResult.IsBonus() && result.Type != HitResult.IgnoreHit; + if (result.Judgement.MaxResult.IsBonus() || result.Type == HitResult.IgnoreHit) + return false; + + return base.CheckDefaultFailCondition(result); } protected override void Reset(bool storeResults) diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index ccf53f075a..9e4c06b783 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Scoring public event Func? Failed; /// - /// Additional conditions on top of that cause a failing state. + /// Additional conditions on top of that cause a failing state. /// public event Func? FailConditions; @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Scoring Health.Value += GetHealthIncreaseFor(result); - if (CanFailOn(result) && meetsAnyFailCondition(result)) + if (meetsAnyFailCondition(result)) TriggerFailure(); } @@ -69,16 +69,10 @@ namespace osu.Game.Rulesets.Scoring protected virtual double GetHealthIncreaseFor(JudgementResult result) => result.HealthIncrease; /// - /// Whether a failure can occur on a given . - /// If the return value of this method is , neither nor will be checked - /// after this . + /// Checks whether the default conditions for failing are met. /// - protected virtual bool CanFailOn(JudgementResult result) => true; - - /// - /// The default conditions for failing. - /// - protected virtual bool DefaultFailCondition => Precision.AlmostBigger(Health.MinValue, Health.Value); + /// if failure should be invoked. + protected virtual bool CheckDefaultFailCondition(JudgementResult result) => Precision.AlmostBigger(Health.MinValue, Health.Value); /// /// Whether the current state of or the provided meets any fail condition. @@ -86,7 +80,7 @@ namespace osu.Game.Rulesets.Scoring /// The judgement result. private bool meetsAnyFailCondition(JudgementResult result) { - if (DefaultFailCondition) + if (CheckDefaultFailCondition(result)) return true; if (FailConditions != null) From f0f37df67fea4f20cc117012457ffd2c9b3bfec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 15:27:17 +0100 Subject: [PATCH 417/915] Revert unnecessary change --- osu.Game/Screens/Select/FilterQueryParser.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 24580c9e96..5fb5859a3b 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -121,8 +121,7 @@ namespace osu.Game.Screens.Select value.EndsWith("ms", StringComparison.Ordinal) ? 1 : value.EndsWith('s') ? 1000 : value.EndsWith('m') ? 60000 : - value.EndsWith('h') ? 3600000 : - value.EndsWith('d') ? 86400000 : 1000; + value.EndsWith('h') ? 3600000 : 1000; private static bool tryParseFloatWithPoint(string value, out float result) => float.TryParse(value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result); From d7dfc8b88aa5081a6765898a94097050c8441c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 15:55:57 +0100 Subject: [PATCH 418/915] Add failing test coverage for empty date filter not parsing --- osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 81a73fc99f..814b26a231 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -488,7 +488,8 @@ namespace osu.Game.Tests.NonVisual.Filtering new object[] { "0:3:" }, new object[] { "\"three days\"" }, new object[] { "0.1y0.1M2d" }, - new object[] { "0.99y0.99M2d" } + new object[] { "0.99y0.99M2d" }, + new object[] { string.Empty } }; [Test] From c24328dda347f8cd2196267790e225bb3f038d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 15:56:32 +0100 Subject: [PATCH 419/915] Abandon date filter if no meaningful time bound found during parsing --- osu.Game/Screens/Select/FilterQueryParser.cs | 23 +++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 5fb5859a3b..3612a84ff9 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -394,7 +394,8 @@ namespace osu.Game.Screens.Select if (match == null) return false; - DateTimeOffset dateTimeOffset = DateTimeOffset.Now; + DateTimeOffset? dateTimeOffset = null; + DateTimeOffset now = DateTimeOffset.Now; try { @@ -410,27 +411,27 @@ namespace osu.Game.Screens.Select switch (key) { case "seconds": - dateTimeOffset = dateTimeOffset.AddSeconds(-length); + dateTimeOffset = (dateTimeOffset ?? now).AddSeconds(-length); break; case "minutes": - dateTimeOffset = dateTimeOffset.AddMinutes(-length); + dateTimeOffset = (dateTimeOffset ?? now).AddMinutes(-length); break; case "hours": - dateTimeOffset = dateTimeOffset.AddHours(-length); + dateTimeOffset = (dateTimeOffset ?? now).AddHours(-length); break; case "days": - dateTimeOffset = dateTimeOffset.AddDays(-length); + dateTimeOffset = (dateTimeOffset ?? now).AddDays(-length); break; case "months": - dateTimeOffset = dateTimeOffset.AddMonths(-(int)length); + dateTimeOffset = (dateTimeOffset ?? now).AddMonths(-(int)length); break; case "years": - dateTimeOffset = dateTimeOffset.AddYears(-(int)length); + dateTimeOffset = (dateTimeOffset ?? now).AddYears(-(int)length); break; } } @@ -438,11 +439,13 @@ namespace osu.Game.Screens.Select } catch (ArgumentOutOfRangeException) { - dateTimeOffset = DateTimeOffset.MinValue; - dateTimeOffset = dateTimeOffset.AddMilliseconds(1); + dateTimeOffset = DateTimeOffset.MinValue.AddMilliseconds(1); } - return tryUpdateCriteriaRange(ref dateRange, reverseInequalityOperator(op), dateTimeOffset); + if (!dateTimeOffset.HasValue) + return false; + + return tryUpdateCriteriaRange(ref dateRange, reverseInequalityOperator(op), dateTimeOffset.Value); } // Function to reverse an Operator From a8ae0a032f67900b8466263ac3ceb5f1b79b95d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 15:58:38 +0100 Subject: [PATCH 420/915] Simplify parsing --- osu.Game/Screens/Select/FilterQueryParser.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 3612a84ff9..17af0ee8ba 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -403,9 +403,12 @@ namespace osu.Game.Screens.Select foreach (string key in keys) { - if (match[key].Success) + if (!match.TryGetValue(key, out var group) || !group.Success) + continue; + + if (group.Success) { - if (!tryParseDoubleWithPoint(match[key].Value, out double length)) + if (!tryParseDoubleWithPoint(group.Value, out double length)) return false; switch (key) From f1d69abdc8d56502b23beccf62827518275cdc90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 15:59:07 +0100 Subject: [PATCH 421/915] Rename test --- osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 814b26a231..a5aac0a4ce 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -532,7 +532,7 @@ namespace osu.Game.Tests.NonVisual.Filtering } [Test] - public void TestOutofrangeDateQuery() + public void TestOutOfRangeDateQuery() { const string query = "played<10000y"; var filterCriteria = new FilterCriteria(); From 414066fd34f18db433fc4c3c2fc10f3624989924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 16:07:42 +0100 Subject: [PATCH 422/915] Inline problematic function (and rename things to make more sense) --- osu.Game/Screens/Select/FilterQueryParser.cs | 67 +++++++++++--------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 17af0ee8ba..278ca1ac5f 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Select case "played": case "lastplayed": - return tryUpdateDateRange(ref criteria.LastPlayed, op, value); + return tryUpdateDateAgoRange(ref criteria.LastPlayed, op, value); case "divisor": return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt); @@ -381,10 +381,42 @@ namespace osu.Game.Screens.Select return tryUpdateCriteriaRange(ref criteria.Length, op, totalLength, minScale / 2.0); } - private static bool tryUpdateDateRange(ref FilterCriteria.OptionalRange dateRange, Operator op, string val) + /// + /// This function is intended for parsing "days / months / years ago" type filters. + /// + private static bool tryUpdateDateAgoRange(ref FilterCriteria.OptionalRange dateRange, Operator op, string val) { - if (op == Operator.Equal) - return false; + switch (op) + { + case Operator.Equal: + // an equality filter is difficult to define for support here. + // if "3 months 2 days ago" means a single concrete time instant, such a filter is basically useless. + // if it means a range of 24 hours, then that is annoying to write and also comes with its own implications + // (does it mean "time instant 3 months 2 days ago, within 12 hours of tolerance either direction"? + // does it mean "the full calendar day, from midnight to midnight, 3 months 2 days ago"?) + // as such, for simplicity, just refuse to support this. + return false; + + // for the remaining operators, since the value provided to this function is an "ago" type value + // (as in, referring to some amount of time back), + // we'll want to flip the operator, such that `>5d` means "more than five days ago", as in "*before* five days ago", + // as intended by the user. + case Operator.Less: + op = Operator.Greater; + break; + + case Operator.LessOrEqual: + op = Operator.GreaterOrEqual; + break; + + case Operator.Greater: + op = Operator.Less; + break; + + case Operator.GreaterOrEqual: + op = Operator.LessOrEqual; + break; + } GroupCollection? match = null; @@ -448,32 +480,7 @@ namespace osu.Game.Screens.Select if (!dateTimeOffset.HasValue) return false; - return tryUpdateCriteriaRange(ref dateRange, reverseInequalityOperator(op), dateTimeOffset.Value); - } - - // Function to reverse an Operator - private static Operator reverseInequalityOperator(Operator ope) - { - switch (ope) - { - default: - throw new ArgumentOutOfRangeException(nameof(ope), $"Unsupported operator {ope}"); - - case Operator.Equal: - return Operator.Equal; - - case Operator.Greater: - return Operator.Less; - - case Operator.GreaterOrEqual: - return Operator.LessOrEqual; - - case Operator.Less: - return Operator.Greater; - - case Operator.LessOrEqual: - return Operator.GreaterOrEqual; - } + return tryUpdateCriteriaRange(ref dateRange, op, dateTimeOffset.Value); } } } From f7bea00564b7ac537b92a4eb9c4fe395bffb27d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 16:19:32 +0100 Subject: [PATCH 423/915] Improve test coverage --- .../Filtering/FilterQueryParserTest.cs | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index a5aac0a4ce..12d6060351 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -508,8 +508,11 @@ namespace osu.Game.Tests.NonVisual.Filtering const string query = "played>50"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); - Assert.AreEqual(false, filterCriteria.LastPlayed.Max == null); - Assert.AreEqual(true, filterCriteria.LastPlayed.Min == null); + Assert.That(filterCriteria.LastPlayed.Max, Is.Not.Null); + Assert.That(filterCriteria.LastPlayed.Min, Is.Null); + // the parser internally references `DateTimeOffset.Now`, so to not make things too annoying for tests, just assume some tolerance + // (irrelevant in proportion to the actual filter proscribed). + Assert.That(filterCriteria.LastPlayed.Max, Is.EqualTo(DateTimeOffset.Now.AddDays(-50)).Within(TimeSpan.FromSeconds(5))); } [Test] @@ -518,8 +521,25 @@ namespace osu.Game.Tests.NonVisual.Filtering const string query = "played<50"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); - Assert.AreEqual(true, filterCriteria.LastPlayed.Max == null); - Assert.AreEqual(false, filterCriteria.LastPlayed.Min == null); + Assert.That(filterCriteria.LastPlayed.Max, Is.Null); + Assert.That(filterCriteria.LastPlayed.Min, Is.Not.Null); + // the parser internally references `DateTimeOffset.Now`, so to not make things too annoying for tests, just assume some tolerance + // (irrelevant in proportion to the actual filter proscribed). + Assert.That(filterCriteria.LastPlayed.Min, Is.EqualTo(DateTimeOffset.Now.AddDays(-50)).Within(TimeSpan.FromSeconds(5))); + } + + [Test] + public void TestBothSidesDateQuery() + { + const string query = "played>3M played<1y6M"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.That(filterCriteria.LastPlayed.Min, Is.Not.Null); + Assert.That(filterCriteria.LastPlayed.Max, Is.Not.Null); + // the parser internally references `DateTimeOffset.Now`, so to not make things too annoying for tests, just assume some tolerance + // (irrelevant in proportion to the actual filter proscribed). + Assert.That(filterCriteria.LastPlayed.Min, Is.EqualTo(DateTimeOffset.Now.AddYears(-1).AddMonths(-6)).Within(TimeSpan.FromSeconds(5))); + Assert.That(filterCriteria.LastPlayed.Max, Is.EqualTo(DateTimeOffset.Now.AddMonths(-3)).Within(TimeSpan.FromSeconds(5))); } [Test] From ae9a2661ace43a96a4fbf26072ed3efd0dc0ba54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 16:20:47 +0100 Subject: [PATCH 424/915] Sprinkle some raw string prefixes --- osu.Game/Screens/Select/FilterQueryParser.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 278ca1ac5f..2c4077dacf 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -431,7 +431,7 @@ namespace osu.Game.Screens.Select try { - List keys = new List { "seconds", "minutes", "hours", "days", "months", "years" }; + List keys = new List { @"seconds", @"minutes", @"hours", @"days", @"months", @"years" }; foreach (string key in keys) { @@ -445,27 +445,27 @@ namespace osu.Game.Screens.Select switch (key) { - case "seconds": + case @"seconds": dateTimeOffset = (dateTimeOffset ?? now).AddSeconds(-length); break; - case "minutes": + case @"minutes": dateTimeOffset = (dateTimeOffset ?? now).AddMinutes(-length); break; - case "hours": + case @"hours": dateTimeOffset = (dateTimeOffset ?? now).AddHours(-length); break; - case "days": + case @"days": dateTimeOffset = (dateTimeOffset ?? now).AddDays(-length); break; - case "months": + case @"months": dateTimeOffset = (dateTimeOffset ?? now).AddMonths(-(int)length); break; - case "years": + case @"years": dateTimeOffset = (dateTimeOffset ?? now).AddYears(-(int)length); break; } From 53884f61c35a573273922ce3976af6b75c598a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 16:41:41 +0100 Subject: [PATCH 425/915] Apply suggested changes --- .../TransientUserStatisticsUpdateDisplay.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index 9960dd4411..52923ea178 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -127,7 +127,7 @@ namespace osu.Game.Overlays.Toolbar ValuePrefix = mainValuePrefix, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Font = OsuFont.GetFont(), + Font = OsuFont.GetFont().With(fixedWidth: true), }, new Container { @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Toolbar { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Font = OsuFont.GetFont(size: 12, fixedWidth: false, weight: FontWeight.SemiBold), + Font = OsuFont.GetFont(size: 12, fixedWidth: true, weight: FontWeight.SemiBold), AlwaysPresent = true, }, titleText = new OsuSpriteText @@ -183,11 +183,11 @@ namespace osu.Game.Overlays.Toolbar titleText.Alpha = 1; deltaValue.Alpha = 0; - using (BeginDelayedSequence(1500)) + using (BeginDelayedSequence(1200)) { - titleText.FadeOut(250, Easing.OutQuint); - deltaValue.FadeIn(250, Easing.OutQuint) - .Then().Delay(1500) + titleText.FadeOut(250, Easing.OutQuad); + deltaValue.FadeIn(250, Easing.OutQuad) + .Then().Delay(500) .Then().Schedule(() => { mainValue.Current.Value = after; @@ -200,9 +200,9 @@ namespace osu.Game.Overlays.Toolbar private partial class Counter : RollingCounter where T : struct, IEquatable, IFormattable { - public const double ROLLING_DURATION = 500; + public const double ROLLING_DURATION = 1500; - public FontUsage Font { get; init; } = OsuFont.Default; + public FontUsage Font { get; init; } = OsuFont.Default.With(fixedWidth: true); public string ValuePrefix { @@ -217,7 +217,13 @@ namespace osu.Game.Overlays.Toolbar private string valuePrefix = string.Empty; protected override LocalisableString FormatCount(T count) => LocalisableString.Format(@"{0}{1:N0}", ValuePrefix, count); - protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = Font); + + protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(t => + { + t.Font = Font; + t.Spacing = new Vector2(-1.5f, 0); + }); + protected override double RollingDuration => ROLLING_DURATION; } } From aae431e8f6f414abe1155f005d33cf111493220d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Feb 2024 16:48:31 +0100 Subject: [PATCH 426/915] Cancel rolling properly --- .../TransientUserStatisticsUpdateDisplay.cs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index 52923ea178..50fc54088f 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; +using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -98,6 +99,7 @@ namespace osu.Game.Overlays.Toolbar private Counter mainValue = null!; private Counter deltaValue = null!; private OsuSpriteText titleText = null!; + private ScheduledDelegate? valueUpdateSchedule; [Resolved] private OsuColour colours { get; set; } = null!; @@ -159,6 +161,9 @@ namespace osu.Game.Overlays.Toolbar public void Display(T before, T delta, T after) { + valueUpdateSchedule?.Cancel(); + valueUpdateSchedule = null; + int comparison = valueComparer.Compare(before, after); if (comparison > 0) @@ -186,13 +191,16 @@ namespace osu.Game.Overlays.Toolbar using (BeginDelayedSequence(1200)) { titleText.FadeOut(250, Easing.OutQuad); - deltaValue.FadeIn(250, Easing.OutQuad) - .Then().Delay(500) - .Then().Schedule(() => - { - mainValue.Current.Value = after; - deltaValue.Current.SetDefault(); - }); + deltaValue.FadeIn(250, Easing.OutQuad); + + using (BeginDelayedSequence(1250)) + { + valueUpdateSchedule = Schedule(() => + { + mainValue.Current.Value = after; + deltaValue.Current.SetDefault(); + }); + } } } } From c175e036007bf68e0ad131f7d01e31a6b5a7fea8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Feb 2024 02:53:38 +0800 Subject: [PATCH 427/915] Inline rolling duration variable --- .../Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index 50fc54088f..b77a4cfb94 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -208,8 +208,6 @@ namespace osu.Game.Overlays.Toolbar private partial class Counter : RollingCounter where T : struct, IEquatable, IFormattable { - public const double ROLLING_DURATION = 1500; - public FontUsage Font { get; init; } = OsuFont.Default.With(fixedWidth: true); public string ValuePrefix @@ -232,7 +230,7 @@ namespace osu.Game.Overlays.Toolbar t.Spacing = new Vector2(-1.5f, 0); }); - protected override double RollingDuration => ROLLING_DURATION; + protected override double RollingDuration => 1500; } } } From 9ec79755fb2e2e467439f7086e7f720b607aef77 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Feb 2024 02:54:28 +0800 Subject: [PATCH 428/915] Standardise font specs --- .../Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index b77a4cfb94..f56a1a3dd2 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -129,7 +129,6 @@ namespace osu.Game.Overlays.Toolbar ValuePrefix = mainValuePrefix, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Font = OsuFont.GetFont().With(fixedWidth: true), }, new Container { @@ -142,7 +141,7 @@ namespace osu.Game.Overlays.Toolbar { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Font = OsuFont.GetFont(size: 12, fixedWidth: true, weight: FontWeight.SemiBold), + Font = OsuFont.Default.With(size: 12, fixedWidth: true, weight: FontWeight.SemiBold), AlwaysPresent = true, }, titleText = new OsuSpriteText From 6e1b4152c07a250426e7e89e632db21043dd31cd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 15 Feb 2024 00:00:39 +0300 Subject: [PATCH 429/915] Redice allocations during aggregate beatmap sort --- .../Select/Carousel/CarouselBeatmapSet.cs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 6d2e938fb7..d2b71b1d5e 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -127,12 +127,40 @@ namespace osu.Game.Screens.Select.Carousel /// /// All beatmaps which are not filtered and valid for display. /// - protected IEnumerable ValidBeatmaps => Beatmaps.Where(b => !b.Filtered.Value || b.State.Value == CarouselItemState.Selected).Select(b => b.BeatmapInfo); + protected IEnumerable ValidBeatmaps + { + get + { + foreach (var item in Items) // iterating over Items directly to not allocate 2 enumerators + { + if (item is CarouselBeatmap b && (!b.Filtered.Value || b.State.Value == CarouselItemState.Selected)) + yield return b.BeatmapInfo; + } + } + } + + /// + /// Whether there are available beatmaps which are not filtered and valid for display. + /// Cheaper alternative to .Any() + /// + public bool HasValidBeatmaps + { + get + { + foreach (var item in Items) // iterating over Items directly to not allocate 2 enumerators + { + if (item is CarouselBeatmap b && (!b.Filtered.Value || b.State.Value == CarouselItemState.Selected)) + return true; + } + + return false; + } + } private int compareUsingAggregateMax(CarouselBeatmapSet other, Func func) { - bool ourBeatmaps = ValidBeatmaps.Any(); - bool otherBeatmaps = other.ValidBeatmaps.Any(); + bool ourBeatmaps = HasValidBeatmaps; + bool otherBeatmaps = other.HasValidBeatmaps; if (!ourBeatmaps && !otherBeatmaps) return 0; if (!ourBeatmaps) return -1; From 80abf6aab346b2f5eed5745c81a521547bf81c26 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Feb 2024 09:45:24 +0800 Subject: [PATCH 430/915] Avoid some further enumerator allocations --- osu.Game/Screens/Select/Carousel/CarouselGroup.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index b2ca117cec..62d694976f 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Extensions.ListExtensions; +using osu.Framework.Lists; namespace osu.Game.Screens.Select.Carousel { @@ -12,7 +14,7 @@ namespace osu.Game.Screens.Select.Carousel { public override DrawableCarouselItem? CreateDrawableRepresentation() => null; - public IReadOnlyList Items => items; + public SlimReadOnlyListWrapper Items => items.AsSlimReadOnly(); public int TotalItemsNotFiltered { get; private set; } From 674ee91bb5dd28d9f4f79a3f0c6d220274a8c3dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Feb 2024 11:40:50 +0800 Subject: [PATCH 431/915] Define aggregate max delegates as static to further reduce allocations --- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index d2b71b1d5e..cee68cf9a5 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -91,19 +91,19 @@ namespace osu.Game.Screens.Select.Carousel break; case SortMode.LastPlayed: - comparison = -compareUsingAggregateMax(otherSet, b => (b.LastPlayed ?? DateTimeOffset.MinValue).ToUnixTimeSeconds()); + comparison = -compareUsingAggregateMax(otherSet, static b => (b.LastPlayed ?? DateTimeOffset.MinValue).ToUnixTimeSeconds()); break; case SortMode.BPM: - comparison = compareUsingAggregateMax(otherSet, b => b.BPM); + comparison = compareUsingAggregateMax(otherSet, static b => b.BPM); break; case SortMode.Length: - comparison = compareUsingAggregateMax(otherSet, b => b.Length); + comparison = compareUsingAggregateMax(otherSet, static b => b.Length); break; case SortMode.Difficulty: - comparison = compareUsingAggregateMax(otherSet, b => b.StarRating); + comparison = compareUsingAggregateMax(otherSet, static b => b.StarRating); break; case SortMode.DateSubmitted: From a03835bf1c472a477dc992b7c2d05357e1b07da4 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 14 Feb 2024 20:13:27 -0800 Subject: [PATCH 432/915] Improve comments --- .../Overlays/Profile/Header/Components/GlobalRankDisplay.cs | 2 +- osu.Game/Users/UserRankPanel.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs b/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs index dcd4129b45..d32f56ab1b 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Profile.Header.Components Content = s.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; }, true); - // needed as statistics doesn't populate User + // needed as `UserStatistics` doesn't populate `User` User.BindValueChanged(u => { var rankHighest = u.NewValue?.RankHighest; diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index 4a00583094..0b8a5166e6 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -167,8 +167,8 @@ namespace osu.Game.Users new GlobalRankDisplay { UserStatistics = { BindTarget = statistics }, - // TODO: make highest rank update, as api.LocalUser doesn't update - // maybe move to statistics in api, so `SoloStatisticsWatcher` can update the value + // TODO: make highest rank update, as `api.LocalUser` doesn't update + // maybe move to `UserStatistics` in api, so `SoloStatisticsWatcher` can update the value User = { BindTarget = user }, }, countryRankDisplay = new ProfileValueDisplay(true) From 0c25a9a460a23740ebfd6f8c8969f0661b1e2cf6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 15 Feb 2024 07:31:01 +0300 Subject: [PATCH 433/915] Add extra bottom space for catcher to not look cut off on tall resolutions --- .../UI/CatchPlayfieldAdjustmentContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs index 64d17b08b6..74dfa6c1fd 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs @@ -20,6 +20,9 @@ namespace osu.Game.Rulesets.Catch.UI const float base_game_width = 1024f; const float base_game_height = 768f; + // extra bottom space for the catcher to not get cut off at tall resolutions lower than 4:3 (e.g. 5:4). number chosen based on testing with maximum catcher scale (i.e. CS 0). + const float extra_bottom_space = 200f; + Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -31,7 +34,8 @@ namespace osu.Game.Rulesets.Catch.UI Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, - Height = base_game_height, + Height = base_game_height + extra_bottom_space, + Y = extra_bottom_space / 2, Masking = true, Child = new Container { From 9e9297bfb3c06b816a8416cac44ad05f819e998a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Feb 2024 13:22:03 +0800 Subject: [PATCH 434/915] Add inline documentation as to why classic mod is not ranked See https://github.com/ppy/osu/pull/27149#issuecomment-1939509941. --- osu.Game/Rulesets/Mods/ModClassic.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Rulesets/Mods/ModClassic.cs b/osu.Game/Rulesets/Mods/ModClassic.cs index 16cb928bd4..b0f6ba9374 100644 --- a/osu.Game/Rulesets/Mods/ModClassic.cs +++ b/osu.Game/Rulesets/Mods/ModClassic.cs @@ -19,5 +19,16 @@ namespace osu.Game.Rulesets.Mods public override LocalisableString Description => "Feeling nostalgic?"; public override ModType Type => ModType.Conversion; + + /// + /// Classic mods are not to be ranked yet due to compatibility and multiplier concerns. + /// Right now classic mods are considered, for leaderboard purposes, to be equal as scores set on osu-stable. + /// But this is not the case. + /// + /// Some examples for things to resolve before even considering this: + /// - Hit windows differ (https://github.com/ppy/osu/issues/11311). + /// - Sliders always gives combo for slider end, even on miss (https://github.com/ppy/osu/issues/11769). + /// + public sealed override bool Ranked => false; } } From 401bd91dc4aefee2582055b798a471d240e17650 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 14 Feb 2024 22:57:38 -0800 Subject: [PATCH 435/915] Add visual test showing overflow on dropdown menu items --- .../Visual/UserInterface/TestSceneOsuDropdown.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs index 1678890b73..63f7a2f2cc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Framework.Testing; -using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; @@ -18,13 +17,22 @@ namespace osu.Game.Tests.Visual.UserInterface public partial class TestSceneOsuDropdown : ThemeComparisonTestScene { protected override Drawable CreateContent() => - new OsuEnumDropdown + new OsuEnumDropdown { Anchor = Anchor.Centre, Origin = Anchor.TopCentre, Width = 150 }; + private enum TestEnum + { + [System.ComponentModel.Description("Option")] + Option, + + [System.ComponentModel.Description("Really lonnnnnnng option")] + ReallyLongOption, + } + [Test] // todo: this can be written much better if ThemeComparisonTestScene has a manual input manager public void TestBackAction() @@ -43,7 +51,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("press back", () => dropdown().OnPressed(new KeyBindingPressEvent(new InputState(), GlobalAction.Back))); AddAssert("closed", () => dropdown().ChildrenOfType().Single().State == MenuState.Closed); - OsuEnumDropdown dropdown() => this.ChildrenOfType>().First(); + OsuEnumDropdown dropdown() => this.ChildrenOfType>().First(); } } } From 3d08bc5605242c097531eae2945a89abe7f80955 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 14 Feb 2024 23:00:30 -0800 Subject: [PATCH 436/915] Truncate long dropdown menu item text and show tooltip --- osu.Game/Graphics/UserInterface/OsuDropdown.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index 2dc701dc9d..38e90bf4ea 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -186,6 +186,8 @@ namespace osu.Game.Graphics.UserInterface : base(item) { Foreground.Padding = new MarginPadding(2); + Foreground.AutoSizeAxes = Axes.Y; + Foreground.RelativeSizeAxes = Axes.X; Masking = true; CornerRadius = corner_radius; @@ -247,11 +249,12 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, }, - Label = new OsuSpriteText + Label = new TruncatingSpriteText { - X = 15, + Padding = new MarginPadding { Left = 15 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, + RelativeSizeAxes = Axes.X, }, }; } From a037dbf8debe7bcecfa904d68c20875d3844236d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 15 Feb 2024 18:33:48 +0900 Subject: [PATCH 437/915] Update test to set Child in more canonical manner --- .../Rulesets/TestSceneRulesetSkinProvidingContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs index 981258e8d1..b089144233 100644 --- a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs +++ b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Rulesets Child = new RulesetSkinProvidingContainer(Ruleset.Value.CreateInstance(), Beatmap.Value.Beatmap, Beatmap.Value.Skin) { - requester + Child = requester }; }); From 95e745c6fbabce01dda192e567546185bfe62e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 15 Feb 2024 10:16:06 +0100 Subject: [PATCH 438/915] Use better messaging for selected submission failure reasons These have been cropping up rather often lately, mostly courtesy of linux users, but not only: https://github.com/ppy/osu/issues/26840 https://github.com/ppy/osu/issues/27008 https://github.com/ppy/osu/discussions/26962 so this is a proposal for slightly improved messaging for such cases to hopefully get users on the right track. The original error is still logged to network log, so there's no information loss. --- osu.Game/Screens/Play/SubmittingPlayer.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index c45d46e993..c759710aba 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -140,7 +140,13 @@ namespace osu.Game.Screens.Play { switch (exception.Message) { - case "expired token": + case @"missing token header": + case @"invalid client hash": + case @"invalid verification hash": + Logger.Log("You are not able to submit a score. Please ensure that you are using the latest version of the official game releases.", level: LogLevel.Important); + break; + + case @"expired token": Logger.Log("Score submission failed because your system clock is set incorrectly. Please check your system time, date and timezone.", level: LogLevel.Important); break; From 898d5ce88bd4d249f98b8fe7cc6dd5e7cdd635d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 15 Feb 2024 10:40:40 +0100 Subject: [PATCH 439/915] Show selected submission failure messages even in solo Previously, if a `SubmittingPlayer` instance deemed it okay to proceed with gameplay despite submission failure, it would silently log all errors and proceed, but the score would still not be submitted. This feels a bit anti-user in the cases wherein something is genuinely wrong with either the client or web, so things like token verification failures or API failures are now shown as notifications to give the user an indication that something went wrong at all. Selected cases (non-user-playable mod, logged out, beatmap is not online) are still logged silently because those are either known and expected, or someone is messing with things. --- osu.Game/Screens/Play/SoloPlayer.cs | 2 +- osu.Game/Screens/Play/SubmittingPlayer.cs | 33 ++++++++++++----------- osu.Game/Tests/Visual/TestPlayer.cs | 2 +- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index f7ae3eb62b..f4cf2da364 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Play Scores = { BindTarget = LeaderboardScores } }; - protected override bool HandleTokenRetrievalFailure(Exception exception) => false; + protected override bool ShouldExitOnTokenRetrievalFailure(Exception exception) => false; protected override Task ImportScore(Score score) { diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index c759710aba..0873f60791 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -118,7 +118,7 @@ namespace osu.Game.Screens.Play token = r.ID; tcs.SetResult(true); }; - req.Failure += handleTokenFailure; + req.Failure += ex => handleTokenFailure(ex, displayNotification: true); api.Queue(req); @@ -128,14 +128,20 @@ namespace osu.Game.Screens.Play return true; - void handleTokenFailure(Exception exception) + void handleTokenFailure(Exception exception, bool displayNotification = false) { tcs.SetResult(false); - if (HandleTokenRetrievalFailure(exception)) + bool shouldExit = ShouldExitOnTokenRetrievalFailure(exception); + + if (displayNotification || shouldExit) { + string whatWillHappen = shouldExit + ? "You are not able to submit a score." + : "The following score will not be submitted."; + if (string.IsNullOrEmpty(exception.Message)) - Logger.Error(exception, "Failed to retrieve a score submission token."); + Logger.Error(exception, $"{whatWillHappen} Failed to retrieve a score submission token."); else { switch (exception.Message) @@ -143,31 +149,28 @@ namespace osu.Game.Screens.Play case @"missing token header": case @"invalid client hash": case @"invalid verification hash": - Logger.Log("You are not able to submit a score. Please ensure that you are using the latest version of the official game releases.", level: LogLevel.Important); + Logger.Log($"{whatWillHappen} Please ensure that you are using the latest version of the official game releases.", level: LogLevel.Important); break; case @"expired token": - Logger.Log("Score submission failed because your system clock is set incorrectly. Please check your system time, date and timezone.", level: LogLevel.Important); + Logger.Log($"{whatWillHappen} Your system clock is set incorrectly. Please check your system time, date and timezone.", level: LogLevel.Important); break; default: - Logger.Log($"You are not able to submit a score: {exception.Message}", level: LogLevel.Important); + Logger.Log($"{whatWillHappen} {exception.Message}", level: LogLevel.Important); break; } } + } + if (shouldExit) + { Schedule(() => { ValidForResume = false; this.Exit(); }); } - else - { - // Gameplay is allowed to continue, but we still should keep track of the error. - // In the future, this should be visible to the user in some way. - Logger.Log($"Score submission token retrieval failed ({exception.Message})"); - } } } @@ -176,7 +179,7 @@ namespace osu.Game.Screens.Play /// /// The error causing the failure. /// Whether gameplay should be immediately exited as a result. Returning false allows the gameplay session to continue. Defaults to true. - protected virtual bool HandleTokenRetrievalFailure(Exception exception) => true; + protected virtual bool ShouldExitOnTokenRetrievalFailure(Exception exception) => true; protected override async Task PrepareScoreForResultsAsync(Score score) { @@ -237,7 +240,7 @@ namespace osu.Game.Screens.Play /// /// Construct a request to be used for retrieval of the score token. - /// Can return null, at which point will be fired. + /// Can return null, at which point will be fired. /// [CanBeNull] protected abstract APIRequest CreateTokenRequest(); diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index d9cae6b03b..579a1934e0 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tests.Visual PauseOnFocusLost = pauseOnFocusLost; } - protected override bool HandleTokenRetrievalFailure(Exception exception) => false; + protected override bool ShouldExitOnTokenRetrievalFailure(Exception exception) => false; protected override APIRequest CreateTokenRequest() { From e91d38872d99dc3904b3664331b94f097881a455 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Feb 2024 18:28:59 +0800 Subject: [PATCH 440/915] Update framework --- 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 d7f29beeb3..f61ff79b9f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index a4cd26a372..506bebfd47 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From 755bc7c0507f3ad7b3c8e5b7ed5592ad78497b43 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 15 Feb 2024 20:07:55 +0900 Subject: [PATCH 441/915] Fix resolution scaling --- .../Mods/ManiaModHidden.cs | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index 211f21513d..12f17c6c59 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -3,11 +3,14 @@ using System; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Game.Rulesets.Mania.UI; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Rulesets.Mania.Skinning; using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Mods { @@ -18,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Mods /// private const float reference_playfield_height = 768; - private const float min_coverage = 160 / reference_playfield_height; + private const float min_coverage = 160f / reference_playfield_height; private const float max_coverage = 400f / reference_playfield_height; private const float coverage_increase_per_combo = 0.5f / reference_playfield_height; @@ -49,17 +52,38 @@ namespace osu.Game.Rulesets.Mania.Mods private partial class LegacyPlayfieldCover : PlayfieldCoveringWrapper { + [Resolved] + private ISkinSource skin { get; set; } = null!; + + private IBindable? hitPosition; + public LegacyPlayfieldCover(Drawable content) : base(content) { } + protected override void LoadComplete() + { + base.LoadComplete(); + + skin.SourceChanged += onSkinChanged; + onSkinChanged(); + } + + private void onSkinChanged() + { + hitPosition = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.HitPosition); + } + protected override float GetHeight(float coverage) { - if (DrawHeight == 0) + // In osu!stable, the cover is applied in absolute (x768) coordinates from the hit position. + float availablePlayfieldHeight = Math.Abs(reference_playfield_height - (hitPosition?.Value ?? Stage.HIT_TARGET_POSITION)); + + if (availablePlayfieldHeight == 0) return base.GetHeight(coverage); - return base.GetHeight(coverage) * reference_playfield_height / DrawHeight; + return base.GetHeight(coverage) * reference_playfield_height / availablePlayfieldHeight; } } } From 9c22fa3a9fbae0fb568e5a7b36d4c688268add3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 15 Feb 2024 12:13:01 +0100 Subject: [PATCH 442/915] Fix android test project compile failures --- .../osu.Game.Tests.Android.csproj | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index 889f0a3583..b02425eadd 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -31,4 +31,22 @@ + + + + + XamarinJetbrainsAnnotations + + + From d1a51b474c2a4d8ebdd780cc42f0d5ff63a8ab9a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 15 Feb 2024 21:24:00 +0900 Subject: [PATCH 443/915] Adjust tests --- .../Mods/TestSceneManiaModFadeIn.cs | 70 +++++++++++++++++-- .../Mods/TestSceneManiaModHidden.cs | 70 +++++++++++++++++-- .../Mods/ManiaModHidden.cs | 15 ++-- 3 files changed, 142 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFadeIn.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFadeIn.cs index 2c8c151e7f..fc49dc528d 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFadeIn.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFadeIn.cs @@ -1,8 +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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Mods @@ -11,9 +17,65 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); - [TestCase(0.5f)] - [TestCase(0.1f)] - [TestCase(0.7f)] - public void TestCoverage(float coverage) => CreateModTest(new ModTestData { Mod = new ManiaModFadeIn { Coverage = { Value = coverage } }, PassCondition = () => true }); + [Test] + public void TestMinCoverageFullWidth() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + PassCondition = () => checkCoverage(ManiaModHidden.MIN_COVERAGE) + }); + } + + [Test] + public void TestMinCoverageHalfWidth() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + PassCondition = () => checkCoverage(ManiaModHidden.MIN_COVERAGE) + }); + + AddStep("set playfield width to 0.5", () => Player.Width = 0.5f); + } + + [Test] + public void TestMaxCoverageFullWidth() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + PassCondition = () => checkCoverage(ManiaModHidden.MAX_COVERAGE) + }); + + AddStep("set combo to 480", () => Player.ScoreProcessor.Combo.Value = 480); + } + + [Test] + public void TestMaxCoverageHalfWidth() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + PassCondition = () => checkCoverage(ManiaModHidden.MAX_COVERAGE) + }); + + AddStep("set combo to 480", () => Player.ScoreProcessor.Combo.Value = 480); + AddStep("set playfield width to 0.5", () => Player.Width = 0.5f); + } + + private bool checkCoverage(float expected) + { + Drawable? cover = this.ChildrenOfType().FirstOrDefault(); + Drawable? filledArea = cover?.ChildrenOfType().LastOrDefault(); + + if (filledArea == null) + return false; + + float scale = cover!.DrawHeight / (768 - Stage.HIT_TARGET_POSITION); + + // A bit of lenience because the test may end up hitting hitobjects before any assertions. + return Precision.AlmostEquals(filledArea.DrawHeight / scale, expected, 0.1); + } } } diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHidden.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHidden.cs index 204f26f151..581cc3b33a 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHidden.cs @@ -1,8 +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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Mods @@ -11,9 +17,65 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); - [TestCase(0.5f)] - [TestCase(0.2f)] - [TestCase(0.8f)] - public void TestCoverage(float coverage) => CreateModTest(new ModTestData { Mod = new ManiaModHidden { Coverage = { Value = coverage } }, PassCondition = () => true }); + [Test] + public void TestMinCoverageFullWidth() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + PassCondition = () => checkCoverage(ManiaModHidden.MIN_COVERAGE) + }); + } + + [Test] + public void TestMinCoverageHalfWidth() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + PassCondition = () => checkCoverage(ManiaModHidden.MIN_COVERAGE) + }); + + AddStep("set playfield width to 0.5", () => Player.Width = 0.5f); + } + + [Test] + public void TestMaxCoverageFullWidth() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + PassCondition = () => checkCoverage(ManiaModHidden.MAX_COVERAGE) + }); + + AddStep("set combo to 480", () => Player.ScoreProcessor.Combo.Value = 480); + } + + [Test] + public void TestMaxCoverageHalfWidth() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + PassCondition = () => checkCoverage(ManiaModHidden.MAX_COVERAGE) + }); + + AddStep("set combo to 480", () => Player.ScoreProcessor.Combo.Value = 480); + AddStep("set playfield width to 0.5", () => Player.Width = 0.5f); + } + + private bool checkCoverage(float expected) + { + Drawable? cover = this.ChildrenOfType().FirstOrDefault(); + Drawable? filledArea = cover?.ChildrenOfType().LastOrDefault(); + + if (filledArea == null) + return false; + + float scale = cover!.DrawHeight / (768 - Stage.HIT_TARGET_POSITION); + + // A bit of lenience because the test may end up hitting hitobjects before any assertions. + return Precision.AlmostEquals(filledArea.DrawHeight / scale, expected, 0.1); + } } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index 12f17c6c59..b2c6988319 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -21,9 +21,9 @@ namespace osu.Game.Rulesets.Mania.Mods /// private const float reference_playfield_height = 768; - private const float min_coverage = 160f / reference_playfield_height; - private const float max_coverage = 400f / reference_playfield_height; - private const float coverage_increase_per_combo = 0.5f / reference_playfield_height; + public const float MIN_COVERAGE = 160f; + public const float MAX_COVERAGE = 400f; + private const float coverage_increase_per_combo = 0.5f; public override LocalisableString Description => @"Keys fade out before you hit them!"; public override double ScoreMultiplier => 1; @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Mania.Mods typeof(ManiaModCover) }).ToArray(); - public override BindableNumber Coverage { get; } = new BindableFloat(min_coverage); + public override BindableNumber Coverage { get; } = new BindableFloat(MIN_COVERAGE); protected override CoverExpandDirection ExpandDirection => CoverExpandDirection.AgainstScroll; private readonly BindableInt combo = new BindableInt(); @@ -45,7 +45,12 @@ namespace osu.Game.Rulesets.Mania.Mods combo.UnbindAll(); combo.BindTo(scoreProcessor.Combo); - combo.BindValueChanged(c => Coverage.Value = Math.Min(max_coverage, min_coverage + c.NewValue * coverage_increase_per_combo), true); + combo.BindValueChanged(c => + { + Coverage.Value = Math.Min( + MAX_COVERAGE / reference_playfield_height, + MIN_COVERAGE / reference_playfield_height + c.NewValue * coverage_increase_per_combo / reference_playfield_height); + }, true); } protected override PlayfieldCoveringWrapper CreateCover(Drawable content) => new LegacyPlayfieldCover(content); From 878fb2d10d8edb3f559e786751941d8ac3f2d05d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 15 Feb 2024 22:05:25 +0900 Subject: [PATCH 444/915] Add break support --- .../Mods/TestSceneManiaModFadeIn.cs | 19 ++++++++++++ .../Mods/TestSceneManiaModHidden.cs | 19 ++++++++++++ .../Mods/ManiaModHidden.cs | 25 ++++++++++----- .../UI/PlayfieldCoveringWrapper.cs | 31 +++++++++++++------ 4 files changed, 78 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFadeIn.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFadeIn.cs index fc49dc528d..9620897983 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFadeIn.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModFadeIn.cs @@ -7,8 +7,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Objects; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Mods @@ -64,6 +68,21 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods AddStep("set playfield width to 0.5", () => Player.Width = 0.5f); } + [Test] + public void TestNoCoverageDuringBreak() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + Beatmap = new Beatmap + { + HitObjects = Enumerable.Range(1, 100).Select(i => (HitObject)new Note { StartTime = 1000 + 200 * i }).ToList(), + Breaks = { new BreakPeriod(2000, 28000) } + }, + PassCondition = () => Player.IsBreakTime.Value && checkCoverage(0) + }); + } + private bool checkCoverage(float expected) { Drawable? cover = this.ChildrenOfType().FirstOrDefault(); diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHidden.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHidden.cs index 581cc3b33a..ae23c4573c 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHidden.cs @@ -7,8 +7,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Objects; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests.Mods @@ -64,6 +68,21 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods AddStep("set playfield width to 0.5", () => Player.Width = 0.5f); } + [Test] + public void TestNoCoverageDuringBreak() + { + CreateModTest(new ModTestData + { + Mod = new ManiaModHidden(), + Beatmap = new Beatmap + { + HitObjects = Enumerable.Range(1, 100).Select(i => (HitObject)new Note { StartTime = 1000 + 200 * i }).ToList(), + Breaks = { new BreakPeriod(2000, 28000) } + }, + PassCondition = () => Player.IsBreakTime.Value && checkCoverage(0) + }); + } + private bool checkCoverage(float expected) { Drawable? cover = this.ChildrenOfType().FirstOrDefault(); diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index b2c6988319..5ddc627642 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -9,12 +9,15 @@ using osu.Game.Rulesets.Mania.UI; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Skinning; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Mods { - public partial class ManiaModHidden : ManiaModWithPlayfieldCover + public partial class ManiaModHidden : ManiaModWithPlayfieldCover, IApplicableToPlayer, IUpdatableByPlayfield { /// /// osu!stable is referenced to 768px. @@ -37,6 +40,7 @@ namespace osu.Game.Rulesets.Mania.Mods public override BindableNumber Coverage { get; } = new BindableFloat(MIN_COVERAGE); protected override CoverExpandDirection ExpandDirection => CoverExpandDirection.AgainstScroll; + private readonly IBindable isBreakTime = new Bindable(); private readonly BindableInt combo = new BindableInt(); public override void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) @@ -45,12 +49,19 @@ namespace osu.Game.Rulesets.Mania.Mods combo.UnbindAll(); combo.BindTo(scoreProcessor.Combo); - combo.BindValueChanged(c => - { - Coverage.Value = Math.Min( - MAX_COVERAGE / reference_playfield_height, - MIN_COVERAGE / reference_playfield_height + c.NewValue * coverage_increase_per_combo / reference_playfield_height); - }, true); + } + + public void ApplyToPlayer(Player player) + { + isBreakTime.UnbindAll(); + isBreakTime.BindTo(player.IsBreakTime); + } + + public void Update(Playfield playfield) + { + Coverage.Value = isBreakTime.Value + ? 0 + : Math.Min(MAX_COVERAGE, MIN_COVERAGE + combo.Value * coverage_increase_per_combo) / reference_playfield_height; } protected override PlayfieldCoveringWrapper CreateCover(Drawable content) => new LegacyPlayfieldCover(content); diff --git a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs index 2b70c527ae..1cf2be7b06 100644 --- a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs +++ b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly IBindable scrollDirection = new Bindable(); - private float currentCoverage; + private float currentCoverageHeight; public PlayfieldCoveringWrapper(Drawable content) { @@ -106,23 +106,36 @@ namespace osu.Game.Rulesets.Mania.UI protected override void LoadComplete() { base.LoadComplete(); - - updateHeight(Coverage.Value); + updateCoverSize(true); } protected override void Update() { base.Update(); - - updateHeight((float)Interpolation.DampContinuously(currentCoverage, Coverage.Value, 25, Math.Abs(Time.Elapsed))); + updateCoverSize(false); } - private void updateHeight(float coverage) + private void updateCoverSize(bool instant) { - filled.Height = GetHeight(coverage); - gradient.Y = -GetHeight(coverage); + float targetCoverage; + float targetAlpha; - currentCoverage = coverage; + if (instant) + { + targetCoverage = Coverage.Value; + targetAlpha = Coverage.Value > 0 ? 1 : 0; + } + else + { + targetCoverage = (float)Interpolation.DampContinuously(currentCoverageHeight, Coverage.Value, 25, Math.Abs(Time.Elapsed)); + targetAlpha = (float)Interpolation.DampContinuously(gradient.Alpha, Coverage.Value > 0 ? 1 : 0, 25, Math.Abs(Time.Elapsed)); + } + + filled.Height = GetHeight(targetCoverage); + gradient.Y = -GetHeight(targetCoverage); + gradient.Alpha = targetAlpha; + + currentCoverageHeight = targetCoverage; } protected virtual float GetHeight(float coverage) => coverage; From e705190664cee548c402eb2e67ecbaf742341b62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 15 Feb 2024 23:23:49 +0800 Subject: [PATCH 445/915] Update windows icon metrics to match previous icon --- osu.Desktop/lazer.ico | Bin 67391 -> 76552 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/osu.Desktop/lazer.ico b/osu.Desktop/lazer.ico index f84866b8e93b4c7a449371b71a99b1a8c5567df1..a3280f0de0b6a935309c84594e8b83cdb7d2e43f 100644 GIT binary patch literal 76552 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

X~%=`gEKj(Ksd$CM;}+tqLyrwl(h2dj8hG;X_w+ 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 `fTbt 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 Date: Thu, 15 Feb 2024 16:40:58 +0100 Subject: [PATCH 446/915] Make dropdown text nicer --- osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs index 1cf2be7b06..d8d9705530 100644 --- a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs +++ b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -13,11 +14,12 @@ using osu.Framework.Utils; using osu.Game.Rulesets.UI.Scrolling; using osuTK; using osuTK.Graphics; +using Container = osu.Framework.Graphics.Containers.Container; namespace osu.Game.Rulesets.Mania.UI { ///

- /// A that has its contents partially hidden by an adjustable "cover". This is intended to be used in a playfield. + /// A that has its contents partially hidden by an adjustable "cover". This is intended to be used in a playfield. /// public partial class PlayfieldCoveringWrapper : CompositeDrawable { @@ -157,11 +159,13 @@ namespace osu.Game.Rulesets.Mania.UI /// /// The cover expands along the scrolling direction. /// + [Description("Along scroll")] AlongScroll, /// /// The cover expands against the scrolling direction. /// + [Description("Against scroll")] AgainstScroll } } From c4bcae86ec02c59dfd0a795ddb9a7f828201b8ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Feb 2024 00:43:20 +0800 Subject: [PATCH 447/915] Update iOS icon metrics to match previous icon --- ...0-5cbe0121-ed68-414f-9ddc-dd993ac97e62.png | Bin 278451 -> 453879 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/300076680-5cbe0121-ed68-414f-9ddc-dd993ac97e62.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/300076680-5cbe0121-ed68-414f-9ddc-dd993ac97e62.png index 21f5f0f3a0901ed465ec468164bce1817fb4ea22..9287a71040091fb7a249018bff4133b91b12e1fc 100644 GIT binary patch literal 453879 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 K)~(TTivAB8ZcmZ` literal 278451 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

EM!on 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

b;UQhmR-aO6N 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�k+(fIDq7qxZKK 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�IQvA; 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

-2ku4wGs_zr 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 Date: Thu, 15 Feb 2024 23:05:13 +0100 Subject: [PATCH 448/915] Point launch.json to new build directory --- .vscode/launch.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d93fddf42d..7c5225cff7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Desktop/bin/Debug/net6.0/osu!.dll" + "${workspaceRoot}/osu.Desktop/bin/Debug/net8.0/osu!.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build osu! (Debug)", @@ -19,7 +19,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Desktop/bin/Release/net6.0/osu!.dll" + "${workspaceRoot}/osu.Desktop/bin/Release/net8.0/osu!.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build osu! (Release)", @@ -31,7 +31,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Game.Tests/bin/Debug/net6.0/osu.Game.Tests.dll" + "${workspaceRoot}/osu.Game.Tests/bin/Debug/net8.0/osu.Game.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build tests (Debug)", @@ -43,7 +43,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Game.Tests/bin/Release/net6.0/osu.Game.Tests.dll" + "${workspaceRoot}/osu.Game.Tests/bin/Release/net8.0/osu.Game.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build tests (Release)", @@ -55,7 +55,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Desktop/bin/Debug/net6.0/osu!.dll", + "${workspaceRoot}/osu.Desktop/bin/Debug/net8.0/osu!.dll", "--tournament" ], "cwd": "${workspaceRoot}", @@ -68,7 +68,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Desktop/bin/Release/net6.0/osu!.dll", + "${workspaceRoot}/osu.Desktop/bin/Release/net8.0/osu!.dll", "--tournament" ], "cwd": "${workspaceRoot}", @@ -81,7 +81,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net6.0/osu.Game.Tournament.Tests.dll", + "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll", "--tournament" ], "cwd": "${workspaceRoot}", @@ -94,7 +94,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net6.0/osu.Game.Tournament.Tests.dll", + "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll", "--tournament" ], "cwd": "${workspaceRoot}", @@ -105,7 +105,7 @@ "name": "Benchmark", "type": "coreclr", "request": "launch", - "program": "${workspaceRoot}/osu.Game.Benchmarks/bin/Release/net6.0/osu.Game.Benchmarks.dll", + "program": "${workspaceRoot}/osu.Game.Benchmarks/bin/Release/net8.0/osu.Game.Benchmarks.dll", "args": [ "--filter", "*" From a9eac5924de12073d39e8c9b2b57f83be6185de2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Feb 2024 01:18:13 +0300 Subject: [PATCH 449/915] Remove seemingly unnecessary float casts --- osu.Game/Screens/Play/PlayerLoader.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6154e443ef..fff1118622 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -550,8 +550,10 @@ namespace osu.Game.Screens.Play { if (!muteWarningShownOnce.Value) { + double aggregateVolumeTrack = audioManager.Volume.Value * audioManager.VolumeTrack.Value; + // Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - if (volumeOverlay?.IsMuted.Value == true || (float)(audioManager.Volume.Value * audioManager.VolumeTrack.Value) <= volume_requirement) + if (volumeOverlay?.IsMuted.Value == true || aggregateVolumeTrack <= volume_requirement) { notificationOverlay?.Post(new MutedNotification()); muteWarningShownOnce.Value = true; @@ -580,9 +582,11 @@ namespace osu.Game.Screens.Play volumeOverlay.IsMuted.Value = false; + double aggregateVolumeTrack = audioManager.Volume.Value * audioManager.VolumeTrack.Value; + // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. // Note that we only restore to -20 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. - if ((float)(audioManager.Volume.Value * audioManager.VolumeTrack.Value) <= volume_requirement) + if (aggregateVolumeTrack <= volume_requirement) { // Prioritize increasing music over master volume as to avoid also increasing effects volume. const double target = 0.1; From d81b148b099e56f1a9ff8d7a20d282e7b970d7a9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Feb 2024 01:23:18 +0300 Subject: [PATCH 450/915] Remove mention of decibel units in comment Decibels are irrelevant in the volume bindables, as mentioned in PR already. --- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index fff1118622..c755923ace 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -585,7 +585,7 @@ namespace osu.Game.Screens.Play double aggregateVolumeTrack = audioManager.Volume.Value * audioManager.VolumeTrack.Value; // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. - // Note that we only restore to -20 dB to ensure the user isn't suddenly overloaded by unexpectedly high volume. + // Note that we only restore to 10% to ensure the user isn't suddenly overloaded by unexpectedly high volume. if (aggregateVolumeTrack <= volume_requirement) { // Prioritize increasing music over master volume as to avoid also increasing effects volume. From 5431781f80692d8fc36a5a301126148b00ca916c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Feb 2024 01:23:26 +0300 Subject: [PATCH 451/915] Bring back target volume to 50% --- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index c755923ace..d3f75fe15e 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -589,7 +589,7 @@ namespace osu.Game.Screens.Play if (aggregateVolumeTrack <= volume_requirement) { // Prioritize increasing music over master volume as to avoid also increasing effects volume. - const double target = 0.1; + const double target = 0.5; double result = target / Math.Max(0.01, audioManager.Volume.Value); if (result > 1) From 6751f95eb648b42cdb55baa83efcb07a757ea9a7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Feb 2024 01:28:47 +0300 Subject: [PATCH 452/915] Adjust test cases and approximate equality --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 67e94a2960..02a0ae6e6c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -268,9 +268,9 @@ namespace osu.Game.Tests.Visual.Gameplay { addVolumeSteps("master and music volumes", () => { - audioManager.Volume.Value = 0.15; - audioManager.VolumeTrack.Value = 0.01; - }, () => audioManager.Volume.Value == 0.15 && audioManager.VolumeTrack.Value == 0.67); + audioManager.Volume.Value = 0.6; + audioManager.VolumeTrack.Value = 0.15; + }, () => Precision.AlmostEquals(audioManager.Volume.Value, 0.6) && Precision.AlmostEquals(audioManager.VolumeTrack.Value, 0.83)); } [Test] @@ -280,7 +280,7 @@ namespace osu.Game.Tests.Visual.Gameplay { audioManager.Volume.Value = 0.01; audioManager.VolumeTrack.Value = 0.15; - }, () => audioManager.Volume.Value == 0.1 && audioManager.VolumeTrack.Value == 1); + }, () => Precision.AlmostEquals(audioManager.Volume.Value, 0.5) && Precision.AlmostEquals(audioManager.VolumeTrack.Value, 1)); } [Test] From 7530b1f362451eb18e6fcfaceb5154f4bddddac6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Feb 2024 01:31:52 +0300 Subject: [PATCH 453/915] Adjust comment again --- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index d3f75fe15e..060074890c 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -585,7 +585,7 @@ namespace osu.Game.Screens.Play double aggregateVolumeTrack = audioManager.Volume.Value * audioManager.VolumeTrack.Value; // Check values before resetting, as the user may have only had mute enabled, in which case we might not need to adjust volumes. - // Note that we only restore to 10% to ensure the user isn't suddenly overloaded by unexpectedly high volume. + // Note that we only restore halfway to ensure the user isn't suddenly overloaded by unexpectedly high volume. if (aggregateVolumeTrack <= volume_requirement) { // Prioritize increasing music over master volume as to avoid also increasing effects volume. From ec85bf0ae66cf0127e5cfc7d0f231742dd87f8e9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Feb 2024 01:45:30 +0300 Subject: [PATCH 454/915] Update other VS code configuration files --- .../osu.Game.Rulesets.EmptyFreeform.Tests/.vscode/launch.json | 4 ++-- .../osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json | 4 ++-- .../.vscode/launch.json | 4 ++-- .../osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json | 4 ++-- osu.Game.Rulesets.Catch.Tests/.vscode/launch.json | 4 ++-- osu.Game.Rulesets.Mania.Tests/.vscode/launch.json | 4 ++-- osu.Game.Rulesets.Osu.Tests/.vscode/launch.json | 4 ++-- osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json | 4 ++-- osu.Game.Tournament.Tests/.vscode/launch.json | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/.vscode/launch.json b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/.vscode/launch.json index b433819346..0d72037393 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/.vscode/launch.json +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.EmptyFreeformRuleset.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.EmptyFreeformRuleset.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.EmptyFreeformRuleset.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.EmptyFreeformRuleset.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json index d60bc2571d..ec832d9a72 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Pippidon.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.Pippidon.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Pippidon.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.Pippidon.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/.vscode/launch.json b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/.vscode/launch.json index f1f37f6363..a60979073b 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/.vscode/launch.json +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.EmptyScrolling.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.EmptyScrolling.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.EmptyScrolling.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.EmptyScrolling.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json index d60bc2571d..ec832d9a72 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Pippidon.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.Pippidon.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Pippidon.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.Pippidon.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json b/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json index 201343a036..7b9291c870 100644 --- a/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json +++ b/osu.Game.Rulesets.Catch.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Catch.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.Catch.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Catch.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.Catch.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json b/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json index f6a067a831..b8dafda8b5 100644 --- a/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json +++ b/osu.Game.Rulesets.Mania.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Mania.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.Mania.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Mania.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.Mania.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json b/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json index 61be25b845..a68d6e12c0 100644 --- a/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json +++ b/osu.Game.Rulesets.Osu.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Osu.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.Osu.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Osu.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.Osu.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json b/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json index 56ec7d8d9c..5b192c795b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json +++ b/osu.Game.Rulesets.Taiko.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Taiko.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.Taiko.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Taiko.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.Taiko.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", diff --git a/osu.Game.Tournament.Tests/.vscode/launch.json b/osu.Game.Tournament.Tests/.vscode/launch.json index 51aa541811..07a0db448d 100644 --- a/osu.Game.Tournament.Tests/.vscode/launch.json +++ b/osu.Game.Tournament.Tests/.vscode/launch.json @@ -7,7 +7,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Debug/net6.0/osu.Game.Tournament.Tests.dll" + "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Debug)", @@ -20,7 +20,7 @@ "request": "launch", "program": "dotnet", "args": [ - "${workspaceRoot}/bin/Release/net6.0/osu.Game.Tournament.Tests.dll" + "${workspaceRoot}/bin/Release/net8.0/osu.Game.Tournament.Tests.dll" ], "cwd": "${workspaceRoot}", "preLaunchTask": "Build (Release)", From 22ffac1718f14f8509d46be93923a5837e80157e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 16 Feb 2024 01:45:38 +0300 Subject: [PATCH 455/915] Update Rider configuration files --- .../.idea/runConfigurations/Benchmarks.xml | 6 +++--- .../.idea/runConfigurations/CatchRuleset__Tests_.xml | 6 +++--- .../.idea/runConfigurations/ManiaRuleset__Tests_.xml | 6 +++--- .../.idea/runConfigurations/OsuRuleset__Tests_.xml | 6 +++--- .../.idea/runConfigurations/TaikoRuleset__Tests_.xml | 6 +++--- .../.idea/runConfigurations/Tournament.xml | 6 +++--- .../.idea/runConfigurations/Tournament__Tests_.xml | 6 +++--- .idea/.idea.osu.Desktop/.idea/runConfigurations/osu_.xml | 6 +++--- .../.idea/runConfigurations/osu___Tests_.xml | 6 +++--- .run/osu! (Second Client).run.xml | 6 +++--- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml index d500c595c0..a7a6649a4f 100644 --- a/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml +++ b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml @@ -1,8 +1,8 @@ -

e&FE%k)kw1nZ_Ituv@| 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

public interface IStatefulUserHubClient { + /// + /// Invoked when the server requests a client to disconnect. + /// + /// + /// When this request is received, the client must presume any and all further requests to the server + /// will either fail or be ignored. + /// This method is ONLY to be used for the purposes of: + /// + /// actually physically disconnecting from the server, + /// cleaning up / setting up any and all required local client state. + /// + /// Task DisconnectRequested(); } } From 060b01eee8d30d996858515829568feb827cc8b4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 16 Feb 2024 20:24:02 +0300 Subject: [PATCH 469/915] Make CreateJudgement public again and add remarks --- .../Objects/EmptyFreeformHitObject.cs | 2 +- .../osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs | 2 +- .../Objects/EmptyScrollingHitObject.cs | 2 +- .../osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Banana.cs | 2 +- osu.Game.Rulesets.Catch/Objects/BananaShower.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Droplet.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Fruit.cs | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs | 2 +- osu.Game.Rulesets.Mania/Objects/BarLine.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs | 2 +- osu.Game.Rulesets.Mania/Objects/Note.cs | 2 +- osu.Game.Rulesets.Mania/Objects/TailNote.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs | 2 +- osu.Game.Rulesets.Osu/Objects/HitCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/BarLine.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs | 2 +- osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs | 2 +- osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs | 2 +- osu.Game/Database/StandardisedScoreMigrationTools.cs | 2 +- osu.Game/Rulesets/Objects/HitObject.cs | 6 +++++- osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs | 2 +- 39 files changed, 44 insertions(+), 40 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/EmptyFreeformHitObject.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/EmptyFreeformHitObject.cs index e166d09f84..9cd18d2d9f 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/EmptyFreeformHitObject.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/EmptyFreeformHitObject.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Objects { public class EmptyFreeformHitObject : HitObject, IHasPosition { - protected override Judgement CreateJudgement() => new Judgement(); + public override Judgement CreateJudgement() => new Judgement(); public Vector2 Position { get; set; } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs index 748e6d3b53..0c22554e82 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Pippidon.Objects { public class PippidonHitObject : HitObject, IHasPosition { - protected override Judgement CreateJudgement() => new Judgement(); + public override Judgement CreateJudgement() => new Judgement(); public Vector2 Position { get; set; } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/EmptyScrollingHitObject.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/EmptyScrollingHitObject.cs index 4564bd1e09..9b469be496 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/EmptyScrollingHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/EmptyScrollingHitObject.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.EmptyScrolling.Objects { public class EmptyScrollingHitObject : HitObject { - protected override Judgement CreateJudgement() => new Judgement(); + public override Judgement CreateJudgement() => new Judgement(); } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs index ed16bce9f6..9dd135479f 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/PippidonHitObject.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Pippidon.Objects /// public int Lane; - protected override Judgement CreateJudgement() => new Judgement(); + public override Judgement CreateJudgement() => new Judgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 30bdb24b14..b80527f379 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Objects /// public int BananaIndex; - protected override Judgement CreateJudgement() => new CatchBananaJudgement(); + public override Judgement CreateJudgement() => new CatchBananaJudgement(); private static readonly IList default_banana_samples = new List { new BananaHitSampleInfo() }.AsReadOnly(); diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 86c41fce90..328cc2b52a 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Objects { public override bool LastInCombo => true; - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); protected override void CreateNestedHitObjects(CancellationToken cancellationToken) { diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index 107c6c3979..9c1004a04b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class Droplet : PalpableCatchHitObject { - protected override Judgement CreateJudgement() => new CatchDropletJudgement(); + public override Judgement CreateJudgement() => new CatchDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index 17270b803c..4818fe2cad 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Catch.Objects { public class Fruit : PalpableCatchHitObject { - protected override Judgement CreateJudgement() => new CatchJudgement(); + public override Judgement CreateJudgement() => new CatchJudgement(); public static FruitVisualRepresentation GetVisualRepresentation(int indexInBeatmap) => (FruitVisualRepresentation)(indexInBeatmap % 4); } diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 49c24df5b9..671291ef0e 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.Objects /// private const float base_scoring_distance = 100; - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); public int RepeatCount { get; set; } diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index ddcb92875f..1bf160b5a6 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class TinyDroplet : Droplet { - protected override Judgement CreateJudgement() => new CatchTinyDropletJudgement(); + public override Judgement CreateJudgement() => new CatchTinyDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs index 742b5e4b0d..cf576239ed 100644 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/BarLine.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Mania.Objects set => major.Value = value; } - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 4aac455bc5..3f930a310b 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.Objects }); } - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs index 92b649c174..47163d0d81 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteBody.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class HoldNoteBody : ManiaHitObject { - protected override Judgement CreateJudgement() => new HoldNoteBodyJudgement(); + public override Judgement CreateJudgement() => new HoldNoteBodyJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index b0f2991918..0035960c63 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class Note : ManiaHitObject { - protected override Judgement CreateJudgement() => new ManiaJudgement(); + public override Judgement CreateJudgement() => new ManiaJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index bddb4630cb..def32880f1 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// public const double RELEASE_WINDOW_LENIENCE = 1.5; - protected override Judgement CreateJudgement() => new ManiaJudgement(); + public override Judgement CreateJudgement() => new ManiaJudgement(); public override double MaximumJudgementOffset => base.MaximumJudgementOffset * RELEASE_WINDOW_LENIENCE; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs index f07a1e930b..2c9292c58b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Mods { } - protected override Judgement CreateJudgement() => new OsuJudgement(); + public override Judgement CreateJudgement() => new OsuJudgement(); } private partial class StrictTrackingDrawableSliderTail : DrawableSliderTail diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index 6336482ccc..d652db0fd4 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Osu.Objects { public class HitCircle : OsuHitObject { - protected override Judgement CreateJudgement() => new OsuJudgement(); + public override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index fc0248cbbd..506145568e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Osu.Objects TailSamples = this.GetNodeSamples(repeatCount + 1); } - protected override Judgement CreateJudgement() => ClassicSliderBehaviour + public override Judgement CreateJudgement() => ClassicSliderBehaviour // Final combo is provided by the slider itself - see logic in `DrawableSlider.CheckForResult()` ? new OsuJudgement() // Final combo is provided by the tail circle - see `SliderTailCircle` diff --git a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs index 8d60864f0b..2d5a5b7727 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Objects protected override HitWindows CreateHitWindows() => HitWindows.Empty; - protected override Judgement CreateJudgement() => new SliderEndJudgement(); + public override Judgement CreateJudgement() => new SliderEndJudgement(); public class SliderEndJudgement : OsuJudgement { diff --git a/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs index 4760135081..8305481788 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs @@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Osu.Objects /// public bool ClassicSliderBehaviour; - protected override Judgement CreateJudgement() => ClassicSliderBehaviour ? new SliderTickJudgement() : base.CreateJudgement(); + public override Judgement CreateJudgement() => ClassicSliderBehaviour ? new SliderTickJudgement() : base.CreateJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 42d8d895e4..ee2490439f 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Objects { } - protected override Judgement CreateJudgement() => ClassicSliderBehaviour ? new LegacyTailJudgement() : new TailJudgement(); + public override Judgement CreateJudgement() => ClassicSliderBehaviour ? new LegacyTailJudgement() : new TailJudgement(); public class LegacyTailJudgement : OsuJudgement { diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 1d7ba2fbaf..74ec4d6eb3 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -32,6 +32,6 @@ namespace osu.Game.Rulesets.Osu.Objects protected override HitWindows CreateHitWindows() => HitWindows.Empty; - protected override Judgement CreateJudgement() => new SliderTickJudgement(); + public override Judgement CreateJudgement() => new SliderTickJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 9baa645b3c..e3dfe8e69a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Osu.Objects } } - protected override Judgement CreateJudgement() => new OsuJudgement(); + public override Judgement CreateJudgement() => new OsuJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs index 57db29ef0c..8d53100529 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Osu.Objects { public class SpinnerBonusTick : SpinnerTick { - protected override Judgement CreateJudgement() => new OsuSpinnerBonusTickJudgement(); + public override Judgement CreateJudgement() => new OsuSpinnerBonusTickJudgement(); public class OsuSpinnerBonusTickJudgement : OsuSpinnerTickJudgement { diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs index cb59014909..7989c9b7ff 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects /// public double SpinnerDuration { get; set; } - protected override Judgement CreateJudgement() => new OsuSpinnerTickJudgement(); + public override Judgement CreateJudgement() => new OsuSpinnerTickJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs index d87f8b3232..46b3f13501 100644 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs @@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Taiko.Objects set => major.Value = value; } - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 50cd722a3f..f3143de345 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Taiko.Objects } } - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Taiko.Objects public class StrongNestedHit : StrongNestedHitObject { // The strong hit of the drum roll doesn't actually provide any score. - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); public StrongNestedHit(TaikoHitObject parent) : base(parent) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index c1d4102042..dc082ffd21 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Objects Parent = parent; } - protected override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); + public override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; diff --git a/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs b/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs index 44cd700faf..302f940ef4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs @@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class IgnoreHit : Hit { - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs index 227ab4ab52..14cbe338ed 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Objects Parent = parent; } - protected override Judgement CreateJudgement() => new TaikoStrongJudgement(); + public override Judgement CreateJudgement() => new TaikoStrongJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index 76d106f924..a8db8df021 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Taiko.Objects } } - protected override Judgement CreateJudgement() => new TaikoSwellJudgement(); + public override Judgement CreateJudgement() => new TaikoSwellJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index be1c1101de..41fb9cac7e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class SwellTick : TaikoHitObject { - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 697c23addf..1a1fde1990 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public const float DEFAULT_SIZE = 0.475f; - protected override Judgement CreateJudgement() => new TaikoJudgement(); + public override Judgement CreateJudgement() => new TaikoJudgement(); protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); } diff --git a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs index f0f93f59b5..584a9e09c0 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs @@ -358,7 +358,7 @@ namespace osu.Game.Tests.Gameplay this.maxResult = maxResult; } - protected override Judgement CreateJudgement() => new TestJudgement(maxResult); + public override Judgement CreateJudgement() => new TestJudgement(maxResult); protected override HitWindows CreateHitWindows() => new HitWindows(); private class TestJudgement : Judgement diff --git a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs index a428979015..8ec18377f4 100644 --- a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs @@ -196,7 +196,7 @@ namespace osu.Game.Tests.Gameplay this.maxResult = maxResult; } - protected override Judgement CreateJudgement() => new TestJudgement(maxResult); + public override Judgement CreateJudgement() => new TestJudgement(maxResult); } } } diff --git a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs index ea43a65825..1647fbee42 100644 --- a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs +++ b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs @@ -441,7 +441,7 @@ namespace osu.Game.Tests.Rulesets.Scoring private readonly HitResult maxResult; private readonly HitResult? minResult; - protected override Judgement CreateJudgement() => new TestJudgement(maxResult, minResult); + public override Judgement CreateJudgement() => new TestJudgement(maxResult, minResult); public TestHitObject(HitResult maxResult, HitResult? minResult = null) { diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index 576d08f491..403e73ab77 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -655,7 +655,7 @@ namespace osu.Game.Database { private readonly Judgement judgement; - protected override Judgement CreateJudgement() => judgement; + public override Judgement CreateJudgement() => judgement; public FakeHit(Judgement judgement) { diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index aed821332d..317dd35fef 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -173,8 +173,12 @@ namespace osu.Game.Rulesets.Objects /// /// Creates the that represents the scoring information for this . /// + /// + /// Use to avoid unnecessary allocations. + /// This method has been left public for compatibility reasons and eventually will be made protected. + /// [NotNull] - protected virtual Judgement CreateJudgement() => new Judgement(); + public virtual Judgement CreateJudgement() => new Judgement(); /// /// Creates the for this . diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs index 499953dab9..bb36aab0b3 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public int ComboOffset { get; set; } - protected override Judgement CreateJudgement() => new IgnoreJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } From b0f334c39e4ac1c3b587fa31b7c7759cfa5ec281 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 17 Feb 2024 00:45:30 +0300 Subject: [PATCH 470/915] Fix DrawableLinkCompiler allocations --- osu.Game/Online/Chat/DrawableLinkCompiler.cs | 32 ++++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index 883a2496f7..fa107a0e43 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.ListExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Lists; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -23,12 +25,21 @@ namespace osu.Game.Online.Chat /// /// Each word part of a chat link (split for word-wrap support). /// - public readonly List Parts; + public readonly SlimReadOnlyListWrapper Parts; [Resolved] private OverlayColourProvider? overlayColourProvider { get; set; } - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parts.Any(d => d.ReceivePositionalInputAt(screenSpacePos)); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + { + foreach (var part in Parts) + { + if (part.ReceivePositionalInputAt(screenSpacePos)) + return true; + } + + return false; + } protected override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new LinkHoverSounds(sampleSet, Parts); @@ -39,7 +50,7 @@ namespace osu.Game.Online.Chat public DrawableLinkCompiler(IEnumerable parts) { - Parts = parts.ToList(); + Parts = parts.ToList().AsSlimReadOnly(); } [BackgroundDependencyLoader] @@ -52,15 +63,24 @@ namespace osu.Game.Online.Chat private partial class LinkHoverSounds : HoverClickSounds { - private readonly List parts; + private readonly SlimReadOnlyListWrapper parts; - public LinkHoverSounds(HoverSampleSet sampleSet, List parts) + public LinkHoverSounds(HoverSampleSet sampleSet, SlimReadOnlyListWrapper parts) : base(sampleSet) { this.parts = parts; } - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => parts.Any(d => d.ReceivePositionalInputAt(screenSpacePos)); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + { + foreach (var part in parts) + { + if (part.ReceivePositionalInputAt(screenSpacePos)) + return true; + } + + return false; + } } } } From ce903987e7e71b22ac138b5985fc6ed37b3c5507 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Feb 2024 00:53:53 +0300 Subject: [PATCH 471/915] Fix cursor ripples being added on release positions in replays --- osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs index 4cb91aa103..d898f1a1a8 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -11,6 +11,7 @@ using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; +using osu.Game.Screens.Play; using osu.Game.Skinning; using osuTK; @@ -39,6 +40,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public bool OnPressed(KeyBindingPressEvent e) { + if ((Clock as IGameplayClock)?.IsRewinding == true) + return false; + if (showRipples.Value) { AddInternal(ripplePool.Get(r => From 8169d1ac80de9b5cf123c0c5540f4a760fce8f3e Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 21 Jan 2024 18:32:07 -0800 Subject: [PATCH 472/915] Add twenty star counter in visual test --- .../Visual/Gameplay/TestSceneStarCounter.cs | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs index b002e90bb0..fa17b77b55 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Utils; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -14,39 +15,47 @@ namespace osu.Game.Tests.Visual.Gameplay public partial class TestSceneStarCounter : OsuTestScene { private readonly StarCounter starCounter; + private readonly StarCounter twentyStarCounter; private readonly OsuSpriteText starsLabel; public TestSceneStarCounter() { - starCounter = new StarCounter + Add(new FillFlowContainer { - Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, - }; - - Add(starCounter); - - starsLabel = new OsuSpriteText - { Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Scale = new Vector2(2), - Y = 50, - }; - - Add(starsLabel); + Direction = FillDirection.Vertical, + Spacing = new Vector2(20), + Children = new Drawable[] + { + starCounter = new StarCounter(), + twentyStarCounter = new StarCounter(20), + starsLabel = new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Scale = new Vector2(2), + }, + } + }); setStars(5); - AddRepeatStep("random value", () => setStars(RNG.NextSingle() * (starCounter.StarCount + 1)), 10); - AddSliderStep("exact value", 0f, 10f, 5f, setStars); - AddStep("stop animation", () => starCounter.StopAnimation()); + AddRepeatStep("random value", () => setStars(RNG.NextSingle() * (twentyStarCounter.StarCount + 1)), 10); + AddSliderStep("exact value", 0f, 20f, 5f, setStars); + AddStep("stop animation", () => + { + starCounter.StopAnimation(); + twentyStarCounter.StopAnimation(); + }); AddStep("reset", () => setStars(0)); } private void setStars(float stars) { starCounter.Current = stars; + twentyStarCounter.Current = stars; starsLabel.Text = starCounter.Current.ToString("0.00"); } } From 6e8d8b977e000481ca0e769f514371a8bb188bdf Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 21 Jan 2024 18:34:55 -0800 Subject: [PATCH 473/915] Move ternary inside `Math.Max()` --- osu.Game/Graphics/UserInterface/StarCounter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index 720f479216..5fdc6a4904 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -115,7 +115,7 @@ namespace osu.Game.Graphics.UserInterface star.ClearTransforms(true); - double delay = (current <= newValue ? Math.Max(i - current, 0) : Math.Max(current - 1 - i, 0)) * AnimationDelay; + double delay = Math.Max(current <= newValue ? i - current : current - 1 - i, 0) * AnimationDelay; using (star.BeginDelayedSequence(delay)) star.DisplayAt(getStarScale(i, newValue)); From 7a74eaa2dec61e1342e9b3c8ca3f3eed1a0ce30f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 21 Jan 2024 18:47:24 -0800 Subject: [PATCH 474/915] Fix star counter decrease animation being delayed when current is over displayed star count --- osu.Game/Graphics/UserInterface/StarCounter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index 5fdc6a4904..4e9e34d840 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -115,7 +115,7 @@ namespace osu.Game.Graphics.UserInterface star.ClearTransforms(true); - double delay = Math.Max(current <= newValue ? i - current : current - 1 - i, 0) * AnimationDelay; + double delay = Math.Max(current <= newValue ? i - current : Math.Min(current, StarCount) - 1 - i, 0) * AnimationDelay; using (star.BeginDelayedSequence(delay)) star.DisplayAt(getStarScale(i, newValue)); From 22f5a66c029bed6b135cbb3c99b63363e4248ecd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 17 Feb 2024 15:46:38 +0300 Subject: [PATCH 475/915] Reduce allocations during beatmap selection --- .../Preprocessing/OsuDifficultyHitObject.cs | 8 ++++- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 8 +++-- osu.Game.Rulesets.Osu/Objects/Slider.cs | 36 +++++++++++++++---- osu.Game/Rulesets/Objects/SliderPath.cs | 15 ++++---- osu.Game/Screens/Select/BeatmapCarousel.cs | 19 ++++++++-- 5 files changed, 67 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 488d1e2e9f..0e537632b1 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -232,7 +232,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing IList nestedObjects = slider.NestedHitObjects; - SliderTick? lastRealTick = slider.NestedHitObjects.OfType().LastOrDefault(); + SliderTick? lastRealTick = null; + + foreach (var hitobject in slider.NestedHitObjects) + { + if (hitobject is SliderTick tick) + lastRealTick = tick; + } if (lastRealTick?.StartTime > trackingEndTime) { diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 74631400ca..6c77d9189c 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -149,8 +148,11 @@ namespace osu.Game.Rulesets.Osu.Objects { StackHeightBindable.BindValueChanged(height => { - foreach (var nested in NestedHitObjects.OfType()) - nested.StackHeight = height.NewValue; + foreach (var nested in NestedHitObjects) + { + if (nested is OsuHitObject osuHitObject) + osuHitObject.StackHeight = height.NewValue; + } }); } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 506145568e..8a87e17089 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -252,18 +252,42 @@ namespace osu.Game.Rulesets.Osu.Objects protected void UpdateNestedSamples() { - var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) - ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) + HitSampleInfo firstSample = null; + + for (int i = 0; i < Samples.Count; i++) + { + // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) + if (i == 0) + { + firstSample = Samples[i]; + continue; + } + + if (Samples[i].Name != HitSampleInfo.HIT_NORMAL) + continue; + + firstSample = Samples[i]; + break; + } + var sampleList = new List(); if (firstSample != null) sampleList.Add(firstSample.With("slidertick")); - foreach (var tick in NestedHitObjects.OfType()) - tick.Samples = sampleList; + foreach (var nested in NestedHitObjects) + { + switch (nested) + { + case SliderTick tick: + tick.Samples = sampleList; + break; - foreach (var repeat in NestedHitObjects.OfType()) - repeat.Samples = this.GetNodeSamples(repeat.RepeatIndex + 1); + case SliderRepeat repeat: + repeat.Samples = this.GetNodeSamples(repeat.RepeatIndex + 1); + break; + } + } if (HeadCircle != null) HeadCircle.Samples = this.GetNodeSamples(0); diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index dc71608132..f33a07f082 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -61,16 +61,17 @@ namespace osu.Game.Rulesets.Objects case NotifyCollectionChangedAction.Add: Debug.Assert(args.NewItems != null); - foreach (var c in args.NewItems.Cast()) - c.Changed += invalidate; + foreach (object? newItem in args.NewItems) + ((PathControlPoint)newItem).Changed += invalidate; + break; case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Remove: Debug.Assert(args.OldItems != null); - foreach (var c in args.OldItems.Cast()) - c.Changed -= invalidate; + foreach (object? oldItem in args.OldItems) + ((PathControlPoint)oldItem).Changed -= invalidate; break; } @@ -269,10 +270,10 @@ namespace osu.Game.Rulesets.Objects { List subPath = calculateSubPath(segmentVertices, segmentType); // Skip the first vertex if it is the same as the last vertex from the previous segment - int skipFirst = calculatedPath.Count > 0 && subPath.Count > 0 && calculatedPath.Last() == subPath[0] ? 1 : 0; + bool skipFirst = calculatedPath.Count > 0 && subPath.Count > 0 && calculatedPath.Last() == subPath[0]; - foreach (Vector2 t in subPath.Skip(skipFirst)) - calculatedPath.Add(t); + for (int j = skipFirst ? 1 : 0; j < subPath.Count; j++) + calculatedPath.Add(subPath[j]); } if (i > 0) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 70ecde3858..ae0f397d52 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -510,12 +510,27 @@ namespace osu.Game.Screens.Select if (beatmapInfo?.Hidden != false) return false; - foreach (CarouselBeatmapSet set in beatmapSets) + foreach (var carouselItem in root.Items) { + if (carouselItem is not CarouselBeatmapSet set) + continue; + if (!bypassFilters && set.Filtered.Value) continue; - var item = set.Beatmaps.FirstOrDefault(p => p.BeatmapInfo.Equals(beatmapInfo)); + CarouselBeatmap? item = null; + + foreach (var setCarouselItem in set.Items) + { + if (setCarouselItem is not CarouselBeatmap setCarouselBeatmap) + continue; + + if (!setCarouselBeatmap.BeatmapInfo.Equals(beatmapInfo)) + continue; + + item = setCarouselBeatmap; + break; + } if (item == null) // The beatmap that needs to be selected doesn't exist in this set From 62a7e315bf669fea52ea2bb153995f08f16e9661 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Feb 2024 03:11:29 +0800 Subject: [PATCH 476/915] Update framework --- 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 f61ff79b9f..85171cc0fa 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index 506bebfd47..f23debd38f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From 0714a4fc1e23a4a3e7672ff7a075fe86d6878194 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Feb 2024 03:18:50 +0800 Subject: [PATCH 477/915] Revert sample lookup logic that was not allocating anything --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 8a87e17089..900f42d96b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -252,23 +252,8 @@ namespace osu.Game.Rulesets.Osu.Objects protected void UpdateNestedSamples() { - HitSampleInfo firstSample = null; - - for (int i = 0; i < Samples.Count; i++) - { - // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) - if (i == 0) - { - firstSample = Samples[i]; - continue; - } - - if (Samples[i].Name != HitSampleInfo.HIT_NORMAL) - continue; - - firstSample = Samples[i]; - break; - } + var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) + ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) var sampleList = new List(); From 0df6e8f5950aaeac17ff1fefee6fb80b3f73d4f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Feb 2024 03:22:10 +0800 Subject: [PATCH 478/915] Remove list allocations in `UpdateNestedSamples` --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 900f42d96b..79bf91bcae 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -252,20 +252,16 @@ namespace osu.Game.Rulesets.Osu.Objects protected void UpdateNestedSamples() { - var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) - ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) - - var sampleList = new List(); - - if (firstSample != null) - sampleList.Add(firstSample.With("slidertick")); + // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) + HitSampleInfo tickSample = (Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) ?? Samples.First()).With("slidertick"); foreach (var nested in NestedHitObjects) { switch (nested) { case SliderTick tick: - tick.Samples = sampleList; + tick.SamplesBindable.Clear(); + tick.SamplesBindable.Add(tickSample); break; case SliderRepeat repeat: From dd82de473a1b42ad77d871ad7faeea6b5f1c718c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 17 Feb 2024 22:42:47 +0300 Subject: [PATCH 479/915] Revert BeatmapCarousel changes --- osu.Game/Screens/Select/BeatmapCarousel.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index ae0f397d52..70ecde3858 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -510,27 +510,12 @@ namespace osu.Game.Screens.Select if (beatmapInfo?.Hidden != false) return false; - foreach (var carouselItem in root.Items) + foreach (CarouselBeatmapSet set in beatmapSets) { - if (carouselItem is not CarouselBeatmapSet set) - continue; - if (!bypassFilters && set.Filtered.Value) continue; - CarouselBeatmap? item = null; - - foreach (var setCarouselItem in set.Items) - { - if (setCarouselItem is not CarouselBeatmap setCarouselBeatmap) - continue; - - if (!setCarouselBeatmap.BeatmapInfo.Equals(beatmapInfo)) - continue; - - item = setCarouselBeatmap; - break; - } + var item = set.Beatmaps.FirstOrDefault(p => p.BeatmapInfo.Equals(beatmapInfo)); if (item == null) // The beatmap that needs to be selected doesn't exist in this set From cd8ac6a722124e7827f2a8ee0ef39ef2ab41a932 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sat, 17 Feb 2024 22:12:15 +0200 Subject: [PATCH 480/915] Update BeatmapAttributesDisplay.cs --- .../Overlays/Mods/BeatmapAttributesDisplay.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index b9e4896b21..9312940001 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -19,6 +19,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Online.Rooms; using osuTK; namespace osu.Game.Overlays.Mods @@ -42,6 +43,9 @@ namespace osu.Game.Overlays.Mods [Resolved] private Bindable> mods { get; set; } = null!; + [Resolved(CanBeNull = true)] + private IBindable? selectedItem { get; set; } + public BindableBool Collapsed { get; } = new BindableBool(true); private ModSettingChangeTracker? modSettingChangeTracker; @@ -108,6 +112,8 @@ namespace osu.Game.Overlays.Mods updateValues(); }, true); + selectedItem?.BindValueChanged(_ => mods.TriggerChange()); + BeatmapInfo.BindValueChanged(_ => updateValues(), true); Collapsed.BindValueChanged(_ => @@ -164,10 +170,20 @@ namespace osu.Game.Overlays.Mods starRatingDisplay.FinishTransforms(true); }); + Ruleset ruleset = gameRuleset.Value.CreateInstance(); + double rate = 1; foreach (var mod in mods.Value.OfType()) rate = mod.ApplyToRate(0, rate); + if (selectedItem != null && selectedItem.Value != null) + { + var globalMods = selectedItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + + foreach (var mod in globalMods.OfType()) + rate = mod.ApplyToRate(0, rate); + } + bpmDisplay.Current.Value = BeatmapInfo.Value.BPM * rate; BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value.Difficulty); @@ -175,7 +191,6 @@ namespace osu.Game.Overlays.Mods foreach (var mod in mods.Value.OfType()) mod.ApplyToDifficulty(originalDifficulty); - Ruleset ruleset = gameRuleset.Value.CreateInstance(); BeatmapDifficulty adjustedDifficulty = ruleset.GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, adjustedDifficulty); From 572f693eec361a69d83dedc317fa9608bd816099 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 17 Feb 2024 23:28:35 +0300 Subject: [PATCH 481/915] Fix failing tests related to slider ticks --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 79bf91bcae..203e829180 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -253,7 +253,7 @@ namespace osu.Game.Rulesets.Osu.Objects protected void UpdateNestedSamples() { // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) - HitSampleInfo tickSample = (Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) ?? Samples.First()).With("slidertick"); + HitSampleInfo tickSample = (Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) ?? Samples.FirstOrDefault())?.With("slidertick"); foreach (var nested in NestedHitObjects) { @@ -261,7 +261,9 @@ namespace osu.Game.Rulesets.Osu.Objects { case SliderTick tick: tick.SamplesBindable.Clear(); - tick.SamplesBindable.Add(tickSample); + + if (tickSample != null) + tick.SamplesBindable.Add(tickSample); break; case SliderRepeat repeat: From ed819fde1589bc0cc6167b4610c5a115e49fc844 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sat, 17 Feb 2024 23:01:31 +0200 Subject: [PATCH 482/915] Fixed bugs and added ranked status update --- .../Overlays/Mods/BeatmapAttributesDisplay.cs | 32 ++++++++++++------- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 32 +++++++++++++++++-- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 3 +- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 9312940001..da14382175 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -40,11 +40,16 @@ namespace osu.Game.Overlays.Mods public Bindable BeatmapInfo { get; } = new Bindable(); + /// + /// Should attribute display account for the multiplayer room global mods. + /// + public bool AccountForMultiplayerMods = false; + [Resolved] private Bindable> mods { get; set; } = null!; [Resolved(CanBeNull = true)] - private IBindable? selectedItem { get; set; } + private IBindable? multiplayerRoomItem { get; set; } public BindableBool Collapsed { get; } = new BindableBool(true); @@ -112,7 +117,7 @@ namespace osu.Game.Overlays.Mods updateValues(); }, true); - selectedItem?.BindValueChanged(_ => mods.TriggerChange()); + multiplayerRoomItem?.BindValueChanged(_ => mods.TriggerChange()); BeatmapInfo.BindValueChanged(_ => updateValues(), true); @@ -176,23 +181,26 @@ namespace osu.Game.Overlays.Mods foreach (var mod in mods.Value.OfType()) rate = mod.ApplyToRate(0, rate); - if (selectedItem != null && selectedItem.Value != null) - { - var globalMods = selectedItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - - foreach (var mod in globalMods.OfType()) - rate = mod.ApplyToRate(0, rate); - } - - bpmDisplay.Current.Value = BeatmapInfo.Value.BPM * rate; - BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value.Difficulty); foreach (var mod in mods.Value.OfType()) mod.ApplyToDifficulty(originalDifficulty); + if (AccountForMultiplayerMods && multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + { + var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + + foreach (var mod in multiplayerRoomMods.OfType()) + rate = mod.ApplyToRate(0, rate); + + foreach (var mod in multiplayerRoomMods.OfType()) + mod.ApplyToDifficulty(originalDifficulty); + } + BeatmapDifficulty adjustedDifficulty = ruleset.GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); + bpmDisplay.Current.Value = BeatmapInfo.Value.BPM * rate; + TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, adjustedDifficulty); approachRateDisplay.AdjustType.Value = VerticalAttributeDisplay.CalculateEffect(originalDifficulty.ApproachRate, adjustedDifficulty.ApproachRate); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ddf96c1cb3..0804624ed8 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -25,7 +25,9 @@ using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Localisation; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Online.Rooms; using osu.Game.Utils; using osuTK; using osuTK.Input; @@ -42,6 +44,12 @@ namespace osu.Game.Overlays.Mods [Cached] public Bindable> SelectedMods { get; private set; } = new Bindable>(Array.Empty()); + [Resolved(CanBeNull = true)] + private IBindable? multiplayerRoomItem { get; set; } + + [Resolved] + private OsuGameBase game { get; set; } = null!; + /// /// Contains a dictionary with the current of all mods applicable for the current ruleset. /// @@ -92,6 +100,11 @@ namespace osu.Game.Overlays.Mods /// protected virtual bool ShowPresets => false; + /// + /// Should overlay account for the multiplayer room global mods. + /// + public bool AccountForMultiplayerMods = false; + protected virtual ModColumn CreateModColumn(ModType modType) => new ModColumn(modType, false); protected virtual IReadOnlyList ComputeNewModsFromSelection(IReadOnlyList oldSelection, IReadOnlyList newSelection) => newSelection; @@ -278,7 +291,8 @@ namespace osu.Game.Overlays.Mods { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, - BeatmapInfo = { Value = beatmap?.BeatmapInfo } + BeatmapInfo = { Value = beatmap?.BeatmapInfo }, + AccountForMultiplayerMods = AccountForMultiplayerMods }, } }); @@ -332,6 +346,8 @@ namespace osu.Game.Overlays.Mods } }, true); + multiplayerRoomItem?.BindValueChanged(_ => SelectedMods.TriggerChange()); + customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); SearchTextBox.Current.BindValueChanged(query => @@ -460,8 +476,20 @@ namespace osu.Game.Overlays.Mods foreach (var mod in SelectedMods.Value) multiplier *= mod.ScoreMultiplier; - rankingInformationDisplay.ModMultiplier.Value = multiplier; rankingInformationDisplay.Ranked.Value = SelectedMods.Value.All(m => m.Ranked); + + if (AccountForMultiplayerMods && multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + { + Ruleset ruleset = game.Ruleset.Value.CreateInstance(); + var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + + foreach (var mod in multiplayerRoomMods) + multiplier *= mod.ScoreMultiplier; + + rankingInformationDisplay.Ranked.Value = rankingInformationDisplay.Ranked.Value && multiplayerRoomMods.All(m => m.Ranked); + } + + rankingInformationDisplay.ModMultiplier.Value = multiplier; } private void updateCustomisation() diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 4c0219eff5..71f8bfa0f4 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -244,7 +244,8 @@ namespace osu.Game.Screens.OnlinePlay.Match LoadComponent(UserModsSelectOverlay = new UserModSelectOverlay(OverlayColourScheme.Plum) { SelectedMods = { BindTarget = UserMods }, - IsValidMod = _ => false + IsValidMod = _ => false, + AccountForMultiplayerMods = true }); } From 414e55c90e33d492988914f992f0684284209145 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Feb 2024 01:38:50 +0300 Subject: [PATCH 483/915] Add visual test case --- .../Visual/Online/TestSceneDrawableComment.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index 6f09e4c1f6..5cdf79160c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -81,16 +81,17 @@ namespace osu.Game.Tests.Visual.Online }, // Taken from https://github.com/ppy/osu/issues/13993#issuecomment-885994077 + new[] { "Problematic", @"My tablet doesn't work :( It's a Huion 420 and it's apparently incompatible with OpenTablet Driver. The warning I get is: ""DeviceInUseException: Device is currently in use by another kernel module. To fix this issue, please follow the instructions from https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ#arg umentoutofrangeexception-value-0-15"" and it repeats 4 times on the notification before logging subsequent warnings. Checking the logs, it looks for other Huion tablets before sending the notification (e.g. ""2021-07-23 03:52:33 [verbose]: Detect: Searching for tablet 'Huion WH1409 V2' 20 2021-07-23 03:52:33 [error]: DeviceInUseException: Device is currently in use by another kernel module. To fix this issue, please follow the instructions from https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ#arg umentoutofrangeexception-value-0-15"") I use an Arch based installation of Linux and the tablet runs perfectly with Digimend kernel driver, with area configuration, pen pressure, etc. On osu!lazer the cursor disappears until I set it to ""Borderless"" instead of ""Fullscreen"" and even after it shows up, it goes to the bottom left corner as soon as a map starts. I have honestly 0 idea of whats going on at this point.", }, new[] { - "Problematic", @"My tablet doesn't work :( -It's a Huion 420 and it's apparently incompatible with OpenTablet Driver. The warning I get is: ""DeviceInUseException: Device is currently in use by another kernel module. To fix this issue, please follow the instructions from https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ#arg umentoutofrangeexception-value-0-15"" and it repeats 4 times on the notification before logging subsequent warnings. -Checking the logs, it looks for other Huion tablets before sending the notification (e.g. - ""2021-07-23 03:52:33 [verbose]: Detect: Searching for tablet 'Huion WH1409 V2' - 20 2021-07-23 03:52:33 [error]: DeviceInUseException: Device is currently in use by another kernel module. To fix this issue, please follow the instructions from https://github.com/OpenTabletDriver/OpenTabletDriver/wiki/Linux-FAQ#arg umentoutofrangeexception-value-0-15"") -I use an Arch based installation of Linux and the tablet runs perfectly with Digimend kernel driver, with area configuration, pen pressure, etc. On osu!lazer the cursor disappears until I set it to ""Borderless"" instead of ""Fullscreen"" and even after it shows up, it goes to the bottom left corner as soon as a map starts. -I have honestly 0 idea of whats going on at this point." - } + "Code Block", @"User not found! ;_; + +There are a few possible reasons for this: + + They may have changed their username. + The account may be temporarily unavailable due to security or abuse issues. + You may have made a typo!" + }, }; } } From 91675e097033c249cf7b6947e1023ee2c719ef5f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 18 Feb 2024 02:00:55 +0300 Subject: [PATCH 484/915] Update markdown code block implementation in line with framework changes --- ...suMarkdownFencedCodeBlock.cs => OsuMarkdownCodeBlock.cs} | 6 +++--- .../Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Graphics/Containers/Markdown/{OsuMarkdownFencedCodeBlock.cs => OsuMarkdownCodeBlock.cs} (87%) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownCodeBlock.cs similarity index 87% rename from osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs rename to osu.Game/Graphics/Containers/Markdown/OsuMarkdownCodeBlock.cs index 7d84d368ad..27802f4c0e 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownCodeBlock.cs @@ -10,11 +10,11 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.Containers.Markdown { - public partial class OsuMarkdownFencedCodeBlock : MarkdownFencedCodeBlock + public partial class OsuMarkdownCodeBlock : MarkdownCodeBlock { // TODO : change to monospace font for this component - public OsuMarkdownFencedCodeBlock(FencedCodeBlock fencedCodeBlock) - : base(fencedCodeBlock) + public OsuMarkdownCodeBlock(CodeBlock codeBlock) + : base(codeBlock) { } diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index b4031752db..d465e53432 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -67,7 +67,7 @@ namespace osu.Game.Graphics.Containers.Markdown protected override MarkdownHeading CreateHeading(HeadingBlock headingBlock) => new OsuMarkdownHeading(headingBlock); - protected override MarkdownFencedCodeBlock CreateFencedCodeBlock(FencedCodeBlock fencedCodeBlock) => new OsuMarkdownFencedCodeBlock(fencedCodeBlock); + protected override MarkdownCodeBlock CreateCodeBlock(CodeBlock codeBlock) => new OsuMarkdownCodeBlock(codeBlock); protected override MarkdownSeparator CreateSeparator(ThematicBreakBlock thematicBlock) => new OsuMarkdownSeparator(); From 2df5787dc7e46ea573bbbd4c1608cf18564029d0 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 18 Feb 2024 03:13:57 +0200 Subject: [PATCH 485/915] Packed changes into separate class --- .../Overlays/Mods/BeatmapAttributesDisplay.cs | 58 ++++----- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 66 +++------- .../Mods/MultiplayerModSelectOverlay.cs | 118 ++++++++++++++++++ .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 5 +- 4 files changed, 166 insertions(+), 81 deletions(-) create mode 100644 osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index da14382175..93e7e0ae9c 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -46,10 +46,7 @@ namespace osu.Game.Overlays.Mods public bool AccountForMultiplayerMods = false; [Resolved] - private Bindable> mods { get; set; } = null!; - - [Resolved(CanBeNull = true)] - private IBindable? multiplayerRoomItem { get; set; } + protected Bindable> Mods { get; private set; } = null!; public BindableBool Collapsed { get; } = new BindableBool(true); @@ -61,7 +58,7 @@ namespace osu.Game.Overlays.Mods [Resolved] private OsuGameBase game { get; set; } = null!; - private IBindable gameRuleset = null!; + protected IBindable GameRuleset = null!; private CancellationTokenSource? cancellationSource; private IBindable starDifficulty = null!; @@ -109,16 +106,14 @@ namespace osu.Game.Overlays.Mods { base.LoadComplete(); - mods.BindValueChanged(_ => + Mods.BindValueChanged(_ => { modSettingChangeTracker?.Dispose(); - modSettingChangeTracker = new ModSettingChangeTracker(mods.Value); + modSettingChangeTracker = new ModSettingChangeTracker(Mods.Value); modSettingChangeTracker.SettingChanged += _ => updateValues(); updateValues(); }, true); - multiplayerRoomItem?.BindValueChanged(_ => mods.TriggerChange()); - BeatmapInfo.BindValueChanged(_ => updateValues(), true); Collapsed.BindValueChanged(_ => @@ -128,8 +123,8 @@ namespace osu.Game.Overlays.Mods updateCollapsedState(); }); - gameRuleset = game.Ruleset.GetBoundCopy(); - gameRuleset.BindValueChanged(_ => updateValues()); + GameRuleset = game.Ruleset.GetBoundCopy(); + GameRuleset.BindValueChanged(_ => updateValues()); BeatmapInfo.BindValueChanged(_ => updateValues(), true); @@ -159,6 +154,23 @@ namespace osu.Game.Overlays.Mods LeftContent.AutoSizeDuration = Content.AutoSizeDuration = transition_duration; } + protected virtual double GetRate() + { + double rate = 1; + foreach (var mod in Mods.Value.OfType()) + rate = mod.ApplyToRate(0, rate); + return rate; + } + + protected virtual BeatmapDifficulty GetDifficulty() + { + BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value!.Difficulty); + + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToDifficulty(originalDifficulty); + + return originalDifficulty; + } private void updateValues() => Scheduler.AddOnce(() => { if (BeatmapInfo.Value == null) @@ -175,28 +187,10 @@ namespace osu.Game.Overlays.Mods starRatingDisplay.FinishTransforms(true); }); - Ruleset ruleset = gameRuleset.Value.CreateInstance(); - - double rate = 1; - foreach (var mod in mods.Value.OfType()) - rate = mod.ApplyToRate(0, rate); - - BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value.Difficulty); - - foreach (var mod in mods.Value.OfType()) - mod.ApplyToDifficulty(originalDifficulty); - - if (AccountForMultiplayerMods && multiplayerRoomItem != null && multiplayerRoomItem.Value != null) - { - var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - - foreach (var mod in multiplayerRoomMods.OfType()) - rate = mod.ApplyToRate(0, rate); - - foreach (var mod in multiplayerRoomMods.OfType()) - mod.ApplyToDifficulty(originalDifficulty); - } + double rate = GetRate(); + BeatmapDifficulty originalDifficulty = GetDifficulty(); + Ruleset ruleset = GameRuleset.Value.CreateInstance(); BeatmapDifficulty adjustedDifficulty = ruleset.GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); bpmDisplay.Current.Value = BeatmapInfo.Value.BPM * rate; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 0804624ed8..12719475a8 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -25,9 +25,7 @@ using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Localisation; -using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; -using osu.Game.Online.Rooms; using osu.Game.Utils; using osuTK; using osuTK.Input; @@ -44,11 +42,6 @@ namespace osu.Game.Overlays.Mods [Cached] public Bindable> SelectedMods { get; private set; } = new Bindable>(Array.Empty()); - [Resolved(CanBeNull = true)] - private IBindable? multiplayerRoomItem { get; set; } - - [Resolved] - private OsuGameBase game { get; set; } = null!; /// /// Contains a dictionary with the current of all mods applicable for the current ruleset. @@ -100,11 +93,6 @@ namespace osu.Game.Overlays.Mods /// protected virtual bool ShowPresets => false; - /// - /// Should overlay account for the multiplayer room global mods. - /// - public bool AccountForMultiplayerMods = false; - protected virtual ModColumn CreateModColumn(ModType modType) => new ModColumn(modType, false); protected virtual IReadOnlyList ComputeNewModsFromSelection(IReadOnlyList oldSelection, IReadOnlyList newSelection) => newSelection; @@ -138,8 +126,14 @@ namespace osu.Game.Overlays.Mods private DeselectAllModsButton deselectAllModsButton = null!; private Container aboveColumnsContent = null!; - private RankingInformationDisplay? rankingInformationDisplay; - private BeatmapAttributesDisplay? beatmapAttributesDisplay; + protected RankingInformationDisplay? RankingInformationDisplay; + protected BeatmapAttributesDisplay? BeatmapAttributesDisplay; + protected virtual BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new BeatmapAttributesDisplay + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + BeatmapInfo = { Value = Beatmap?.BeatmapInfo } + }; protected ShearedButton BackButton { get; private set; } = null!; protected ShearedToggleButton? CustomisationButton { get; private set; } @@ -159,8 +153,8 @@ namespace osu.Game.Overlays.Mods if (beatmap == value) return; beatmap = value; - if (IsLoaded && beatmapAttributesDisplay != null) - beatmapAttributesDisplay.BeatmapInfo.Value = beatmap?.BeatmapInfo; + if (IsLoaded && BeatmapAttributesDisplay != null) + BeatmapAttributesDisplay.BeatmapInfo.Value = beatmap?.BeatmapInfo; } } @@ -282,18 +276,12 @@ namespace osu.Game.Overlays.Mods }, Children = new Drawable[] { - rankingInformationDisplay = new RankingInformationDisplay + RankingInformationDisplay = new RankingInformationDisplay { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight }, - beatmapAttributesDisplay = new BeatmapAttributesDisplay - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - BeatmapInfo = { Value = beatmap?.BeatmapInfo }, - AccountForMultiplayerMods = AccountForMultiplayerMods - }, + BeatmapAttributesDisplay = GetBeatmapAttributesDisplay } }); } @@ -329,7 +317,7 @@ namespace osu.Game.Overlays.Mods SelectedMods.BindValueChanged(_ => { - updateRankingInformation(); + UpdateRankingInformation(); updateFromExternalSelection(); updateCustomisation(); @@ -342,12 +330,10 @@ namespace osu.Game.Overlays.Mods // // See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988 modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); - modSettingChangeTracker.SettingChanged += _ => updateRankingInformation(); + modSettingChangeTracker.SettingChanged += _ => UpdateRankingInformation(); } }, true); - multiplayerRoomItem?.BindValueChanged(_ => SelectedMods.TriggerChange()); - customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); SearchTextBox.Current.BindValueChanged(query => @@ -371,7 +357,7 @@ namespace osu.Game.Overlays.Mods SearchTextBox.PlaceholderText = SearchTextBox.HasFocus ? Resources.Localisation.Web.CommonStrings.InputSearch : ModSelectOverlayStrings.TabToSearch; - if (beatmapAttributesDisplay != null) + if (BeatmapAttributesDisplay != null) { float rightEdgeOfLastButton = footerButtonFlow.Last().ScreenSpaceDrawQuad.TopRight.X; @@ -383,7 +369,7 @@ namespace osu.Game.Overlays.Mods // only update preview panel's collapsed state after we are fully visible, to ensure all the buttons are where we expect them to be. if (Alpha == 1) - beatmapAttributesDisplay.Collapsed.Value = screenIsntWideEnough; + BeatmapAttributesDisplay.Collapsed.Value = screenIsntWideEnough; footerContentFlow.LayoutDuration = 200; footerContentFlow.LayoutEasing = Easing.OutQuint; @@ -466,9 +452,9 @@ namespace osu.Game.Overlays.Mods modState.ValidForSelection.Value = modState.Mod.Type != ModType.System && modState.Mod.HasImplementation && IsValidMod.Invoke(modState.Mod); } - private void updateRankingInformation() + protected virtual void UpdateRankingInformation() { - if (rankingInformationDisplay == null) + if (RankingInformationDisplay == null) return; double multiplier = 1.0; @@ -476,20 +462,8 @@ namespace osu.Game.Overlays.Mods foreach (var mod in SelectedMods.Value) multiplier *= mod.ScoreMultiplier; - rankingInformationDisplay.Ranked.Value = SelectedMods.Value.All(m => m.Ranked); - - if (AccountForMultiplayerMods && multiplayerRoomItem != null && multiplayerRoomItem.Value != null) - { - Ruleset ruleset = game.Ruleset.Value.CreateInstance(); - var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - - foreach (var mod in multiplayerRoomMods) - multiplier *= mod.ScoreMultiplier; - - rankingInformationDisplay.Ranked.Value = rankingInformationDisplay.Ranked.Value && multiplayerRoomMods.All(m => m.Ranked); - } - - rankingInformationDisplay.ModMultiplier.Value = multiplier; + RankingInformationDisplay.Ranked.Value = SelectedMods.Value.All(m => m.Ranked); + RankingInformationDisplay.ModMultiplier.Value = multiplier; } private void updateCustomisation() diff --git a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs new file mode 100644 index 0000000000..ca1df31271 --- /dev/null +++ b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs @@ -0,0 +1,118 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Rulesets; +using osu.Game.Online.Rooms; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Overlays.Mods +{ + public partial class MultiplayerModSelectOverlay : UserModSelectOverlay + { + public MultiplayerModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Plum) + : base(colourScheme) + { + } + + [Resolved(CanBeNull = true)] + private IBindable? multiplayerRoomItem { get; set; } + + [Resolved] + private OsuGameBase game { get; set; } = null!; + + protected override BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new MultiplayerBeatmapAttributesDisplay + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + BeatmapInfo = { Value = Beatmap?.BeatmapInfo }, + AccountForMultiplayerMods = true + }; + + protected override void LoadComplete() + { + base.LoadComplete(); + + multiplayerRoomItem?.BindValueChanged(_ => SelectedMods.TriggerChange()); + } + + protected override void UpdateRankingInformation() + { + if (RankingInformationDisplay == null) + return; + + double multiplier = 1.0; + + foreach (var mod in SelectedMods.Value) + multiplier *= mod.ScoreMultiplier; + + RankingInformationDisplay.Ranked.Value = SelectedMods.Value.All(m => m.Ranked); + + if (multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + { + Ruleset ruleset = game.Ruleset.Value.CreateInstance(); + var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + + foreach (var mod in multiplayerRoomMods) + multiplier *= mod.ScoreMultiplier; + + RankingInformationDisplay.Ranked.Value = RankingInformationDisplay.Ranked.Value && multiplayerRoomMods.All(m => m.Ranked); + } + + RankingInformationDisplay.ModMultiplier.Value = multiplier; + } + } + + public partial class MultiplayerBeatmapAttributesDisplay : BeatmapAttributesDisplay + { + public MultiplayerBeatmapAttributesDisplay() + : base() + { + } + + [Resolved(CanBeNull = true)] + private IBindable? multiplayerRoomItem { get; set; } + + protected override void LoadComplete() + { + base.LoadComplete(); + multiplayerRoomItem?.BindValueChanged(_ => Mods.TriggerChange()); + } + + protected override double GetRate() + { + double rate = base.GetRate(); + Ruleset ruleset = GameRuleset.Value.CreateInstance(); + + if (AccountForMultiplayerMods && multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + { + var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + + foreach (var mod in multiplayerRoomMods.OfType()) + rate = mod.ApplyToRate(0, rate); + } + + return rate; + } + + protected override BeatmapDifficulty GetDifficulty() + { + BeatmapDifficulty originalDifficulty = base.GetDifficulty(); + Ruleset ruleset = GameRuleset.Value.CreateInstance(); + + if (multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + { + var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + + foreach (var mod in multiplayerRoomMods.OfType()) + mod.ApplyToDifficulty(originalDifficulty); + } + + return originalDifficulty; + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 71f8bfa0f4..fbc06cce9e 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -241,11 +241,10 @@ namespace osu.Game.Screens.OnlinePlay.Match } }; - LoadComponent(UserModsSelectOverlay = new UserModSelectOverlay(OverlayColourScheme.Plum) + LoadComponent(UserModsSelectOverlay = new MultiplayerModSelectOverlay() { SelectedMods = { BindTarget = UserMods }, - IsValidMod = _ => false, - AccountForMultiplayerMods = true + IsValidMod = _ => false }); } From 6fb3192648f723af818322021ac5cd5cc5743ad7 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 18 Feb 2024 03:14:36 +0200 Subject: [PATCH 486/915] Update BeatmapAttributesDisplay.cs --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 93e7e0ae9c..849444fa32 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -40,11 +40,6 @@ namespace osu.Game.Overlays.Mods public Bindable BeatmapInfo { get; } = new Bindable(); - /// - /// Should attribute display account for the multiplayer room global mods. - /// - public bool AccountForMultiplayerMods = false; - [Resolved] protected Bindable> Mods { get; private set; } = null!; From 4aaf016ee0ad4ff8eaebbbd207d7617e3d60a14b Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 18 Feb 2024 03:15:53 +0200 Subject: [PATCH 487/915] quality improvements --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 2 -- osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs | 11 ++--------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 849444fa32..7517a502c7 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -160,10 +160,8 @@ namespace osu.Game.Overlays.Mods protected virtual BeatmapDifficulty GetDifficulty() { BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value!.Difficulty); - foreach (var mod in Mods.Value.OfType()) mod.ApplyToDifficulty(originalDifficulty); - return originalDifficulty; } private void updateValues() => Scheduler.AddOnce(() => diff --git a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs index ca1df31271..ab20e9dc89 100644 --- a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs @@ -29,8 +29,7 @@ namespace osu.Game.Overlays.Mods { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, - BeatmapInfo = { Value = Beatmap?.BeatmapInfo }, - AccountForMultiplayerMods = true + BeatmapInfo = { Value = Beatmap?.BeatmapInfo } }; protected override void LoadComplete() @@ -87,15 +86,12 @@ namespace osu.Game.Overlays.Mods { double rate = base.GetRate(); Ruleset ruleset = GameRuleset.Value.CreateInstance(); - - if (AccountForMultiplayerMods && multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + if (multiplayerRoomItem != null && multiplayerRoomItem.Value != null) { var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - foreach (var mod in multiplayerRoomMods.OfType()) rate = mod.ApplyToRate(0, rate); } - return rate; } @@ -103,15 +99,12 @@ namespace osu.Game.Overlays.Mods { BeatmapDifficulty originalDifficulty = base.GetDifficulty(); Ruleset ruleset = GameRuleset.Value.CreateInstance(); - if (multiplayerRoomItem != null && multiplayerRoomItem.Value != null) { var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - foreach (var mod in multiplayerRoomMods.OfType()) mod.ApplyToDifficulty(originalDifficulty); } - return originalDifficulty; } } From 9070e973d3bf7a54dae89a8acd14acf16cdfe69c Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 18 Feb 2024 03:16:18 +0200 Subject: [PATCH 488/915] Update BeatmapAttributesDisplay.cs --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 7517a502c7..08e124d8ac 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -19,7 +19,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; -using osu.Game.Online.Rooms; using osuTK; namespace osu.Game.Overlays.Mods From a6b63efe7d695354e4ddddb6a7143667fe56e646 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 18 Feb 2024 03:28:24 +0200 Subject: [PATCH 489/915] Fixed NVika code quality errors --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 1 + osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs | 8 ++++++-- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 08e124d8ac..f010725c8b 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -163,6 +163,7 @@ namespace osu.Game.Overlays.Mods mod.ApplyToDifficulty(originalDifficulty); return originalDifficulty; } + private void updateValues() => Scheduler.AddOnce(() => { if (BeatmapInfo.Value == null) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 12719475a8..e29e685ece 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -42,7 +42,6 @@ namespace osu.Game.Overlays.Mods [Cached] public Bindable> SelectedMods { get; private set; } = new Bindable>(Array.Empty()); - /// /// Contains a dictionary with the current of all mods applicable for the current ruleset. /// @@ -128,6 +127,7 @@ namespace osu.Game.Overlays.Mods private Container aboveColumnsContent = null!; protected RankingInformationDisplay? RankingInformationDisplay; protected BeatmapAttributesDisplay? BeatmapAttributesDisplay; + protected virtual BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new BeatmapAttributesDisplay { Anchor = Anchor.BottomRight, diff --git a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs index ab20e9dc89..b399b6b878 100644 --- a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs @@ -86,12 +86,14 @@ namespace osu.Game.Overlays.Mods { double rate = base.GetRate(); Ruleset ruleset = GameRuleset.Value.CreateInstance(); - if (multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + + if (multiplayerRoomItem?.Value != null) { var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); foreach (var mod in multiplayerRoomMods.OfType()) rate = mod.ApplyToRate(0, rate); } + return rate; } @@ -99,12 +101,14 @@ namespace osu.Game.Overlays.Mods { BeatmapDifficulty originalDifficulty = base.GetDifficulty(); Ruleset ruleset = GameRuleset.Value.CreateInstance(); - if (multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + + if (multiplayerRoomItem?.Value != null) { var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); foreach (var mod in multiplayerRoomMods.OfType()) mod.ApplyToDifficulty(originalDifficulty); } + return originalDifficulty; } } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index fbc06cce9e..b20760b114 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -241,7 +241,7 @@ namespace osu.Game.Screens.OnlinePlay.Match } }; - LoadComponent(UserModsSelectOverlay = new MultiplayerModSelectOverlay() + LoadComponent(UserModsSelectOverlay = new MultiplayerModSelectOverlay { SelectedMods = { BindTarget = UserMods }, IsValidMod = _ => false From 24171bd02bf608fdee7b3c39dfecfba11968647e Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 18 Feb 2024 03:34:02 +0200 Subject: [PATCH 490/915] Update MultiplayerModSelectOverlay.cs --- osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs index b399b6b878..78978e25e7 100644 --- a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs @@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Mods RankingInformationDisplay.Ranked.Value = SelectedMods.Value.All(m => m.Ranked); - if (multiplayerRoomItem != null && multiplayerRoomItem.Value != null) + if (multiplayerRoomItem?.Value != null) { Ruleset ruleset = game.Ruleset.Value.CreateInstance(); var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); @@ -68,11 +68,6 @@ namespace osu.Game.Overlays.Mods public partial class MultiplayerBeatmapAttributesDisplay : BeatmapAttributesDisplay { - public MultiplayerBeatmapAttributesDisplay() - : base() - { - } - [Resolved(CanBeNull = true)] private IBindable? multiplayerRoomItem { get; set; } From 9655e8c48af03283ee323ee0d35fd6f354454119 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Feb 2024 17:54:29 +0800 Subject: [PATCH 491/915] Adjust xmldoc slightly --- osu.Game/Rulesets/Objects/HitObject.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 317dd35fef..04bdc35941 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -171,11 +171,10 @@ namespace osu.Game.Rulesets.Objects private Judgement judgement; /// - /// Creates the that represents the scoring information for this . + /// Should be overridden to create a that represents the scoring information for this . /// /// - /// Use to avoid unnecessary allocations. - /// This method has been left public for compatibility reasons and eventually will be made protected. + /// For read access, use to avoid unnecessary allocations. /// [NotNull] public virtual Judgement CreateJudgement() => new Judgement(); From 415a65bf59cdce4b8fab7d836fe3cdc4f7a2a168 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Feb 2024 19:00:30 +0800 Subject: [PATCH 492/915] Add failing tests for beatmap inconsistencies --- .../Navigation/TestSceneScreenNavigation.cs | 63 +++++++++++++++++++ osu.Game/Tests/Visual/OsuGameTestScene.cs | 4 +- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 8ff4fd5ecf..7e42d4781d 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using System.IO; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -18,6 +19,7 @@ using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Collections; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; @@ -221,6 +223,67 @@ namespace osu.Game.Tests.Visual.Navigation AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible); } + [Test] + public void TestAttemptPlayBeatmapWrongHashFails() + { + Screens.Select.SongSelect songSelect = null; + + AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).GetResultSafely()); + PushAndConfirm(() => songSelect = new TestPlaySongSelect()); + AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded); + + AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault); + + AddStep("change beatmap files", () => + { + foreach (var file in Game.Beatmap.Value.BeatmapSetInfo.Files.Where(f => Path.GetExtension(f.Filename) == ".osu")) + { + using (var stream = Game.Storage.GetStream(Path.Combine("files", file.File.GetStoragePath()), FileAccess.ReadWrite)) + stream.WriteByte(0); + } + }); + + AddStep("invalidate cache", () => + { + ((IWorkingBeatmapCache)Game.BeatmapManager).Invalidate(Game.Beatmap.Value.BeatmapSetInfo); + }); + + AddStep("select next difficulty", () => InputManager.Key(Key.Down)); + AddStep("press enter", () => InputManager.Key(Key.Enter)); + + AddUntilStep("wait for player loader", () => Game.ScreenStack.CurrentScreen is PlayerLoader); + AddUntilStep("wait for song select", () => songSelect.IsCurrentScreen()); + } + + [Test] + public void TestAttemptPlayBeatmapMissingFails() + { + Screens.Select.SongSelect songSelect = null; + + AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).GetResultSafely()); + PushAndConfirm(() => songSelect = new TestPlaySongSelect()); + AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded); + + AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault); + + AddStep("delete beatmap files", () => + { + foreach (var file in Game.Beatmap.Value.BeatmapSetInfo.Files.Where(f => Path.GetExtension(f.Filename) == ".osu")) + Game.Storage.Delete(Path.Combine("files", file.File.GetStoragePath())); + }); + + AddStep("invalidate cache", () => + { + ((IWorkingBeatmapCache)Game.BeatmapManager).Invalidate(Game.Beatmap.Value.BeatmapSetInfo); + }); + + AddStep("select next difficulty", () => InputManager.Key(Key.Down)); + AddStep("press enter", () => InputManager.Key(Key.Enter)); + + AddUntilStep("wait for player loader", () => Game.ScreenStack.CurrentScreen is PlayerLoader); + AddUntilStep("wait for song select", () => songSelect.IsCurrentScreen()); + } + [Test] public void TestRetryCountIncrements() { diff --git a/osu.Game/Tests/Visual/OsuGameTestScene.cs b/osu.Game/Tests/Visual/OsuGameTestScene.cs index 6069fe4fb0..b86273b4a3 100644 --- a/osu.Game/Tests/Visual/OsuGameTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGameTestScene.cs @@ -153,6 +153,8 @@ namespace osu.Game.Tests.Visual public new Bindable> SelectedMods => base.SelectedMods; + public new Storage Storage => base.Storage; + public new SpectatorClient SpectatorClient => base.SpectatorClient; // if we don't apply these changes, when running under nUnit the version that gets populated is that of nUnit. @@ -166,7 +168,7 @@ namespace osu.Game.Tests.Visual public TestOsuGame(Storage storage, IAPIProvider api, string[] args = null) : base(args) { - Storage = storage; + base.Storage = storage; API = api; } From 882f11bf79d0ce405fb865cd0a7a1d552f540513 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Feb 2024 23:19:57 +0800 Subject: [PATCH 493/915] Fix logo tracking container being off by one frame This was especially visible at the main menu when running in single thread mode. --- osu.Game/Graphics/Containers/LogoTrackingContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index 08eae25951..57f87b588a 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -82,9 +82,9 @@ namespace osu.Game.Graphics.Containers absolutePos.Y / Logo.Parent!.RelativeToAbsoluteFactor.Y); } - protected override void Update() + protected override void UpdateAfterChildren() { - base.Update(); + base.UpdateAfterChildren(); if (Logo == null) return; From 6b6a6aea54fadf4dd5b811629fd075fe1b7f5c34 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Feb 2024 23:35:26 +0800 Subject: [PATCH 494/915] Apply NRT to `LogoTrackingContainer` --- .../Visual/UserInterface/TestSceneLogoTrackingContainer.cs | 2 +- osu.Game/Graphics/Containers/LogoTrackingContainer.cs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs index 57ea4ee58e..8d5c961265 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs @@ -282,7 +282,7 @@ namespace osu.Game.Tests.Visual.UserInterface /// /// Check that the logo is tracking the position of the facade, with an acceptable precision lenience. /// - public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, ComputeLogoTrackingPosition()); + public bool IsLogoTracking => Precision.AlmostEquals(Logo!.Position, ComputeLogoTrackingPosition()); } } } diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index 57f87b588a..13c672cbd6 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,7 +17,7 @@ namespace osu.Game.Graphics.Containers { public Facade LogoFacade => facade; - protected OsuLogo Logo { get; private set; } + protected OsuLogo? Logo { get; private set; } private readonly InternalFacade facade = new InternalFacade(); @@ -76,7 +74,7 @@ namespace osu.Game.Graphics.Containers /// Will only be correct if the logo's are set to Axes.Both protected Vector2 ComputeLogoTrackingPosition() { - var absolutePos = Logo.Parent!.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre); + var absolutePos = Logo!.Parent!.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre); return new Vector2(absolutePos.X / Logo.Parent!.RelativeToAbsoluteFactor.X, absolutePos.Y / Logo.Parent!.RelativeToAbsoluteFactor.Y); From 998d8206668ba1733d7f7d6ff1afacde219f8a3a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Feb 2024 00:21:54 +0800 Subject: [PATCH 495/915] Ensure audio filters can't be attached before load (or post-disposal) Will probably fix https://github.com/ppy/osu/issues/27225? --- osu.Game/Audio/Effects/AudioFilter.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Audio/Effects/AudioFilter.cs b/osu.Game/Audio/Effects/AudioFilter.cs index 682ca4ca7b..c8673372d7 100644 --- a/osu.Game/Audio/Effects/AudioFilter.cs +++ b/osu.Game/Audio/Effects/AudioFilter.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using ManagedBass.Fx; using osu.Framework.Audio.Mixing; +using osu.Framework.Caching; using osu.Framework.Graphics; namespace osu.Game.Audio.Effects @@ -22,6 +23,8 @@ namespace osu.Game.Audio.Effects private bool isAttached; + private readonly Cached filterApplication = new Cached(); + private int cutoff; /// @@ -36,7 +39,7 @@ namespace osu.Game.Audio.Effects return; cutoff = value; - updateFilter(cutoff); + filterApplication.Invalidate(); } } @@ -61,6 +64,17 @@ namespace osu.Game.Audio.Effects Cutoff = getInitialCutoff(type); } + protected override void Update() + { + base.Update(); + + if (!filterApplication.IsValid) + { + updateFilter(cutoff); + filterApplication.Validate(); + } + } + private int getInitialCutoff(BQFType type) { switch (type) From 3059ddf3b2638a0c6c3c1520fd1e93b32c1dc24d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Feb 2024 01:08:40 +0300 Subject: [PATCH 496/915] Fix allocations in SliderInputManager --- osu.Game.Rulesets.Osu/OsuInputManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index e472de1dfe..ceac1989a6 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -1,13 +1,13 @@ // 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.ComponentModel; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Lists; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.UI; @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu { public partial class OsuInputManager : RulesetInputManager { - public IEnumerable PressedActions => KeyBindingContainer.PressedActions; + public SlimReadOnlyListWrapper PressedActions => KeyBindingContainer.PressedActions; /// /// Whether gameplay input buttons should be allowed. From 5a448ce02f5c65a40a57b4a3f51641d907a92de9 Mon Sep 17 00:00:00 2001 From: maromalo Date: Sun, 18 Feb 2024 19:59:56 -0300 Subject: [PATCH 497/915] Turn BPMDisplay to RollingCounter --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index b9e4896b21..1db02b7cf2 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.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 System.Threading; @@ -168,7 +169,7 @@ namespace osu.Game.Overlays.Mods foreach (var mod in mods.Value.OfType()) rate = mod.ApplyToRate(0, rate); - bpmDisplay.Current.Value = BeatmapInfo.Value.BPM * rate; + bpmDisplay.Current.Value = (int)Math.Round(Math.Round(BeatmapInfo.Value.BPM) * rate); BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value.Difficulty); @@ -194,11 +195,11 @@ namespace osu.Game.Overlays.Mods RightContent.FadeTo(Collapsed.Value && !IsHovered ? 0 : 1, transition_duration, Easing.OutQuint); } - private partial class BPMDisplay : RollingCounter + private partial class BPMDisplay : RollingCounter { protected override double RollingDuration => 250; - protected override LocalisableString FormatCount(double count) => count.ToLocalisableString("0 BPM"); + protected override LocalisableString FormatCount(int count) => count.ToLocalisableString("0 BPM"); protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText { From c6ca812ea07eb9fdfc24038e05f4b485e9501775 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sun, 18 Feb 2024 21:52:23 -0800 Subject: [PATCH 498/915] Add feedback to delete button even when no-op --- osu.Game/Beatmaps/BeatmapManager.cs | 11 +++++++++-- osu.Game/Database/ModelManager.cs | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 1f551f1218..3aed15029d 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -361,13 +361,20 @@ namespace osu.Game.Beatmaps /// public void DeleteVideos(List items, bool silent = false) { - if (items.Count == 0) return; + var noVideosMessage = "No videos found to delete!"; + + if (items.Count == 0) + { + if (!silent) + PostNotification?.Invoke(new ProgressCompletionNotification { Text = noVideosMessage }); + return; + } var notification = new ProgressNotification { Progress = 0, Text = $"Preparing to delete all {HumanisedModelName} videos...", - CompletionText = "No videos found to delete!", + CompletionText = noVideosMessage, State = ProgressNotificationState.Active, }; diff --git a/osu.Game/Database/ModelManager.cs b/osu.Game/Database/ModelManager.cs index 39dae61d36..7a5fb5efbf 100644 --- a/osu.Game/Database/ModelManager.cs +++ b/osu.Game/Database/ModelManager.cs @@ -105,7 +105,12 @@ namespace osu.Game.Database /// public void Delete(List items, bool silent = false) { - if (items.Count == 0) return; + if (items.Count == 0) + { + if (!silent) + PostNotification?.Invoke(new ProgressCompletionNotification { Text = $"No {HumanisedModelName}s found to delete!" }); + return; + } var notification = new ProgressNotification { @@ -142,7 +147,12 @@ namespace osu.Game.Database /// public void Undelete(List items, bool silent = false) { - if (!items.Any()) return; + if (!items.Any()) + { + if (!silent) + PostNotification?.Invoke(new ProgressCompletionNotification { Text = $"No {HumanisedModelName}s found to restore!" }); + return; + } var notification = new ProgressNotification { From 413b7aab602bcd6b4f60265fe893bc88c23b63e8 Mon Sep 17 00:00:00 2001 From: Brandon Date: Sun, 18 Feb 2024 22:12:03 -0800 Subject: [PATCH 499/915] Switch to const string --- osu.Game/Beatmaps/BeatmapManager.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 3aed15029d..0610f7f6fb 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -361,12 +361,12 @@ namespace osu.Game.Beatmaps /// public void DeleteVideos(List items, bool silent = false) { - var noVideosMessage = "No videos found to delete!"; + const string no_videos_message = "No videos found to delete!"; if (items.Count == 0) { if (!silent) - PostNotification?.Invoke(new ProgressCompletionNotification { Text = noVideosMessage }); + PostNotification?.Invoke(new ProgressCompletionNotification { Text = no_videos_message }); return; } @@ -374,7 +374,7 @@ namespace osu.Game.Beatmaps { Progress = 0, Text = $"Preparing to delete all {HumanisedModelName} videos...", - CompletionText = noVideosMessage, + CompletionText = no_videos_message, State = ProgressNotificationState.Active, }; From 444ac5ed4d312fc0914b79888c8a2d00f414a728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 19 Feb 2024 09:34:52 +0100 Subject: [PATCH 500/915] Add failing test coverage --- .../TestSceneSkinEditorNavigation.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs index 57f1b2fbe9..9c180d43da 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Framework.Threading; @@ -301,6 +302,25 @@ namespace osu.Game.Tests.Visual.Navigation switchToGameplayScene(); } + [Test] + public void TestRulesetInputDisabledWhenSkinEditorOpen() + { + advanceToSongSelect(); + openSkinEditor(); + + AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely()); + AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault); + + switchToGameplayScene(); + AddUntilStep("nested input disabled", () => ((Player)Game.ScreenStack.CurrentScreen).ChildrenOfType().All(manager => !manager.UseParentInput)); + + toggleSkinEditor(); + AddUntilStep("nested input enabled", () => ((Player)Game.ScreenStack.CurrentScreen).ChildrenOfType().Any(manager => manager.UseParentInput)); + + toggleSkinEditor(); + AddUntilStep("nested input disabled", () => ((Player)Game.ScreenStack.CurrentScreen).ChildrenOfType().All(manager => !manager.UseParentInput)); + } + private void advanceToSongSelect() { PushAndConfirm(() => songSelect = new TestPlaySongSelect()); From 7f82f103171223518fe34341f07dd07ab4be6c8f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Feb 2024 19:00:43 +0800 Subject: [PATCH 501/915] Fix beatmap potentially loading in a bad state Over-caching could mean that a beatmap could load and cause a late crash. Let's catch it early to avoid such a crash occurring. --- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index 74a85cde7c..8af74d11d8 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -9,6 +9,7 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Extensions; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Rendering.Dummy; using osu.Framework.Graphics.Textures; @@ -143,8 +144,6 @@ namespace osu.Game.Beatmaps { string fileStorePath = BeatmapSetInfo.GetPathForFile(BeatmapInfo.Path); - // TODO: check validity of file - var stream = GetStream(fileStorePath); if (stream == null) @@ -153,6 +152,12 @@ namespace osu.Game.Beatmaps return null; } + if (stream.ComputeMD5Hash() != BeatmapInfo.MD5Hash) + { + Logger.Log($"Beatmap failed to load (file {BeatmapInfo.Path} does not have the expected hash).", level: LogLevel.Error); + return null; + } + using (var reader = new LineBufferedReader(stream)) return Decoder.GetDecoder(reader).Decode(reader); } From 1ca566c6b0001dace3e3a3911c51f66cbf8536fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 19 Feb 2024 09:45:03 +0100 Subject: [PATCH 502/915] Disable nested input managers on edited screen when skin editor is open --- .../Overlays/SkinEditor/SkinEditorOverlay.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index 40cd31934f..93e2f92a1c 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -10,9 +10,11 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.Containers; @@ -66,6 +68,7 @@ namespace osu.Game.Overlays.SkinEditor private IBindable beatmap { get; set; } = null!; private OsuScreen? lastTargetScreen; + private InvokeOnDisposal? nestedInputManagerDisable; private Vector2 lastDrawSize; @@ -105,6 +108,7 @@ namespace osu.Game.Overlays.SkinEditor if (skinEditor != null) { + disableNestedInputManagers(); skinEditor.Show(); return; } @@ -132,6 +136,8 @@ namespace osu.Game.Overlays.SkinEditor { skinEditor?.Save(false); skinEditor?.Hide(); + nestedInputManagerDisable?.Dispose(); + nestedInputManagerDisable = null; globallyReenableBeatmapSkinSetting(); } @@ -243,6 +249,9 @@ namespace osu.Game.Overlays.SkinEditor /// public void SetTarget(OsuScreen screen) { + nestedInputManagerDisable?.Dispose(); + nestedInputManagerDisable = null; + lastTargetScreen = screen; if (skinEditor == null) return; @@ -271,6 +280,7 @@ namespace osu.Game.Overlays.SkinEditor { skinEditor.Save(false); skinEditor.UpdateTargetScreen(target); + disableNestedInputManagers(); } else { @@ -280,6 +290,21 @@ namespace osu.Game.Overlays.SkinEditor } } + private void disableNestedInputManagers() + { + if (lastTargetScreen == null) + return; + + var nestedInputManagers = lastTargetScreen.ChildrenOfType().Where(manager => manager.UseParentInput).ToArray(); + foreach (var inputManager in nestedInputManagers) + inputManager.UseParentInput = false; + nestedInputManagerDisable = new InvokeOnDisposal(() => + { + foreach (var inputManager in nestedInputManagers) + inputManager.UseParentInput = true; + }); + } + private readonly Bindable beatmapSkins = new Bindable(); private LeasedBindable? leasedBeatmapSkins; From ec26ab51d18d5e4e46ee30782ebc388461c4073f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 19 Feb 2024 13:56:21 +0100 Subject: [PATCH 503/915] Use different wording --- osu.Game/Screens/Play/SubmittingPlayer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index 0873f60791..ecb507f382 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -137,11 +137,11 @@ namespace osu.Game.Screens.Play if (displayNotification || shouldExit) { string whatWillHappen = shouldExit - ? "You are not able to submit a score." - : "The following score will not be submitted."; + ? "Play in this state is not permitted." + : "Your score will not be submitted."; if (string.IsNullOrEmpty(exception.Message)) - Logger.Error(exception, $"{whatWillHappen} Failed to retrieve a score submission token."); + Logger.Error(exception, $"Failed to retrieve a score submission token.\n\n{whatWillHappen}"); else { switch (exception.Message) @@ -149,11 +149,11 @@ namespace osu.Game.Screens.Play case @"missing token header": case @"invalid client hash": case @"invalid verification hash": - Logger.Log($"{whatWillHappen} Please ensure that you are using the latest version of the official game releases.", level: LogLevel.Important); + Logger.Log($"Please ensure that you are using the latest version of the official game releases.\n\n{whatWillHappen}", level: LogLevel.Important); break; case @"expired token": - Logger.Log($"{whatWillHappen} Your system clock is set incorrectly. Please check your system time, date and timezone.", level: LogLevel.Important); + Logger.Log($"Your system clock is set incorrectly. Please check your system time, date and timezone.\n\n{whatWillHappen}", level: LogLevel.Important); break; default: From 012d6b7fe1058696e92eaf3c2eee589da50e4f3c Mon Sep 17 00:00:00 2001 From: Mike Will Date: Sun, 18 Feb 2024 22:16:54 -0500 Subject: [PATCH 504/915] Change `userBeatmapOffsetClock` to a `FramedOffsetClock` Assuming that the global audio offset is set perfectly, such that any audio latency is fully accounted for, if a specific beatmap still sounds out of sync, that would no longer be a latency issue. Instead, it would indicate a misalignment between the beatmap's track and time codes, the correction for which should be a virtual-time offset, not a real-time offset. --- osu.Game/Beatmaps/FramedBeatmapClock.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/FramedBeatmapClock.cs b/osu.Game/Beatmaps/FramedBeatmapClock.cs index d0ffbdd459..49dff96ff1 100644 --- a/osu.Game/Beatmaps/FramedBeatmapClock.cs +++ b/osu.Game/Beatmaps/FramedBeatmapClock.cs @@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps private readonly OffsetCorrectionClock? userGlobalOffsetClock; private readonly OffsetCorrectionClock? platformOffsetClock; - private readonly OffsetCorrectionClock? userBeatmapOffsetClock; + private readonly FramedOffsetClock? userBeatmapOffsetClock; private readonly IFrameBasedClock finalClockSource; @@ -70,7 +70,7 @@ namespace osu.Game.Beatmaps userGlobalOffsetClock = new OffsetCorrectionClock(platformOffsetClock); // User per-beatmap offset will be applied to this final clock. - finalClockSource = userBeatmapOffsetClock = new OffsetCorrectionClock(userGlobalOffsetClock); + finalClockSource = userBeatmapOffsetClock = new FramedOffsetClock(userGlobalOffsetClock); } else { @@ -122,7 +122,7 @@ namespace osu.Game.Beatmaps Debug.Assert(userBeatmapOffsetClock != null); Debug.Assert(platformOffsetClock != null); - return userGlobalOffsetClock.RateAdjustedOffset + userBeatmapOffsetClock.RateAdjustedOffset + platformOffsetClock.RateAdjustedOffset; + return userGlobalOffsetClock.RateAdjustedOffset + userBeatmapOffsetClock.Offset + platformOffsetClock.RateAdjustedOffset; } } From 24e3fe79a4554b45b9176411402928c35214e172 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 19 Feb 2024 17:02:53 +0100 Subject: [PATCH 505/915] Log `GlobalStatistics` when exporting logs from settings --- osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index fe88413e6a..82cc952e53 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -10,6 +10,7 @@ using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Screens; +using osu.Framework.Statistics; using osu.Game.Configuration; using osu.Game.Localisation; using osu.Game.Overlays.Notifications; @@ -107,6 +108,9 @@ namespace osu.Game.Overlays.Settings.Sections.General try { + GlobalStatistics.OutputToLog(); + Logger.Flush(); + var logStorage = Logger.Storage; using (var outStream = storage.CreateFileSafely(archive_filename)) From 29900353d924e2dd2efc54f98df5b1fdd8bcd38b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Feb 2024 20:26:15 +0300 Subject: [PATCH 506/915] Reduce allocations in SliderSelectionBlueprint --- .../Sliders/SliderSelectionBlueprint.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index e421d497e7..4d2b980c23 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -416,8 +416,22 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders DrawableObject.SliderBody?.ToScreenSpace(DrawableObject.SliderBody.PathEndOffset) ?? BodyPiece.ToScreenSpace(BodyPiece.PathEndLocation) }; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => - BodyPiece.ReceivePositionalInputAt(screenSpacePos) || ControlPointVisualiser?.Pieces.Any(p => p.ReceivePositionalInputAt(screenSpacePos)) == true; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + { + if (BodyPiece.ReceivePositionalInputAt(screenSpacePos)) + return true; + + if (ControlPointVisualiser == null) + return false; + + foreach (var p in ControlPointVisualiser.Pieces) + { + if (p.ReceivePositionalInputAt(screenSpacePos)) + return true; + } + + return false; + } protected virtual SliderCircleOverlay CreateCircleOverlay(Slider slider, SliderPosition position) => new SliderCircleOverlay(slider, position); } From c7586403112e4616d12817e0dd3d52e7d8dea487 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Feb 2024 20:49:56 +0300 Subject: [PATCH 507/915] Reduce allocations in ComposerDistanceSnapProvider --- .../Edit/ComposerDistanceSnapProvider.cs | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs index b3ca59a5b0..b2f38662cc 100644 --- a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -124,12 +123,34 @@ namespace osu.Game.Rulesets.Edit private (HitObject before, HitObject after)? getObjectsOnEitherSideOfCurrentTime() { - HitObject? lastBefore = playfield.HitObjectContainer.AliveObjects.LastOrDefault(h => h.HitObject.StartTime < editorClock.CurrentTime)?.HitObject; + HitObject? lastBefore = null; + + foreach (var entry in playfield.HitObjectContainer.AliveEntries) + { + double objTime = entry.Value.HitObject.StartTime; + + if (objTime >= editorClock.CurrentTime) + continue; + + if (objTime > lastBefore?.StartTime) + lastBefore = entry.Value.HitObject; + } if (lastBefore == null) return null; - HitObject? firstAfter = playfield.HitObjectContainer.AliveObjects.FirstOrDefault(h => h.HitObject.StartTime >= editorClock.CurrentTime)?.HitObject; + HitObject? firstAfter = null; + + foreach (var entry in playfield.HitObjectContainer.AliveEntries) + { + double objTime = entry.Value.HitObject.StartTime; + + if (objTime < editorClock.CurrentTime) + continue; + + if (objTime < firstAfter?.StartTime) + firstAfter = entry.Value.HitObject; + } if (firstAfter == null) return null; From 3791ab30c44acaaa312f4180c4a82263d2b1aa7c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 19 Feb 2024 20:55:43 +0300 Subject: [PATCH 508/915] Reduce allocations in HitCircleOverlapMarker --- .../HitCircles/Components/HitCircleOverlapMarker.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs index 3cba0610a1..fe335a048d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs @@ -78,9 +78,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components Scale = new Vector2(hitObject.Scale); - if (hitObject is IHasComboInformation combo) - ring.BorderColour = combo.GetComboColour(skin); - double editorTime = editorClock.CurrentTime; double hitObjectTime = hitObject.StartTime; bool hasReachedObject = editorTime >= hitObjectTime; @@ -92,6 +89,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components ring.Scale = new Vector2(1 + 0.1f * ringScale); content.Alpha = 0.9f * (1 - alpha); + + // TODO: should only update colour on skin/combo/object change. + if (hitObject is IHasComboInformation combo && content.Alpha > 0) + ring.BorderColour = combo.GetComboColour(skin); } else content.Alpha = 0; From 2ff8667dd2e433fd7abb832cc8bb91def14c44d1 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 19 Feb 2024 12:11:12 -0800 Subject: [PATCH 509/915] Revert "Centralise global rank display logic to new class" Also don't show on `LoginOverlay` usage for now. --- .../Header/Components/GlobalRankDisplay.cs | 44 ------------------- .../Profile/Header/Components/MainDetails.cs | 17 +++++-- osu.Game/Users/UserRankPanel.cs | 13 +++--- 3 files changed, 19 insertions(+), 55 deletions(-) delete mode 100644 osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs diff --git a/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs b/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs deleted file mode 100644 index d32f56ab1b..0000000000 --- a/osu.Game/Overlays/Profile/Header/Components/GlobalRankDisplay.cs +++ /dev/null @@ -1,44 +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 osu.Framework.Bindables; -using osu.Framework.Extensions.LocalisationExtensions; -using osu.Framework.Localisation; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Resources.Localisation.Web; -using osu.Game.Users; - -namespace osu.Game.Overlays.Profile.Header.Components -{ - public partial class GlobalRankDisplay : ProfileValueDisplay - { - public readonly Bindable UserStatistics = new Bindable(); - public readonly Bindable User = new Bindable(); - - public GlobalRankDisplay() - : base(true) - { - Title = UsersStrings.ShowRankGlobalSimple; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - UserStatistics.BindValueChanged(s => - { - Content = s.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; - }, true); - - // needed as `UserStatistics` doesn't populate `User` - User.BindValueChanged(u => - { - var rankHighest = u.NewValue?.RankHighest; - - ContentTooltipText = rankHighest != null - ? UsersStrings.ShowRankHighest(rankHighest.Rank.ToLocalisableString("\\##,##0"), rankHighest.UpdatedAt.ToLocalisableString(@"d MMM yyyy")) - : string.Empty; - }, true); - } - } -} diff --git a/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs b/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs index ffdf8edc21..2505c1bc8c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MainDetails.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private readonly Dictionary scoreRankInfos = new Dictionary(); private ProfileValueDisplay medalInfo = null!; private ProfileValueDisplay ppInfo = null!; - private GlobalRankDisplay detailGlobalRank = null!; + private ProfileValueDisplay detailGlobalRank = null!; private ProfileValueDisplay detailCountryRank = null!; private RankGraph rankGraph = null!; @@ -52,7 +52,10 @@ namespace osu.Game.Overlays.Profile.Header.Components Spacing = new Vector2(20), Children = new Drawable[] { - detailGlobalRank = new GlobalRankDisplay(), + detailGlobalRank = new ProfileValueDisplay(true) + { + Title = UsersStrings.ShowRankGlobalSimple, + }, detailCountryRank = new ProfileValueDisplay(true) { Title = UsersStrings.ShowRankCountrySimple, @@ -139,8 +142,14 @@ namespace osu.Game.Overlays.Profile.Header.Components foreach (var scoreRankInfo in scoreRankInfos) scoreRankInfo.Value.RankCount = user?.Statistics?.GradesCount[scoreRankInfo.Key] ?? 0; - detailGlobalRank.UserStatistics.Value = user?.Statistics; - detailGlobalRank.User.Value = user; + detailGlobalRank.Content = user?.Statistics?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; + + var rankHighest = user?.RankHighest; + + detailGlobalRank.ContentTooltipText = rankHighest != null + ? UsersStrings.ShowRankHighest(rankHighest.Rank.ToLocalisableString("\\##,##0"), rankHighest.UpdatedAt.ToLocalisableString(@"d MMM yyyy")) + : string.Empty; + detailCountryRank.Content = user?.Statistics?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; rankGraph.Statistics.Value = user?.Statistics; diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index 0b8a5166e6..b440261a4c 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -27,10 +27,10 @@ namespace osu.Game.Users [Resolved] private IAPIProvider api { get; set; } = null!; + private ProfileValueDisplay globalRankDisplay = null!; private ProfileValueDisplay countryRankDisplay = null!; private readonly IBindable statistics = new Bindable(); - private readonly IBindable user = new Bindable(); public UserRankPanel(APIUser user) : base(user) @@ -47,10 +47,9 @@ namespace osu.Game.Users statistics.BindTo(api.Statistics); statistics.BindValueChanged(stats => { + globalRankDisplay.Content = stats.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? "-"; countryRankDisplay.Content = stats.NewValue?.CountryRank?.ToLocalisableString("\\##,##0") ?? "-"; }, true); - - user.BindTo(api.LocalUser!); } protected override Drawable CreateLayout() @@ -164,12 +163,12 @@ namespace osu.Game.Users { new Drawable[] { - new GlobalRankDisplay + globalRankDisplay = new ProfileValueDisplay(true) { - UserStatistics = { BindTarget = statistics }, - // TODO: make highest rank update, as `api.LocalUser` doesn't update + Title = UsersStrings.ShowRankGlobalSimple, + // TODO: implement highest rank tooltip + // `RankHighest` resides in `APIUser`, but `api.LocalUser` doesn't update // maybe move to `UserStatistics` in api, so `SoloStatisticsWatcher` can update the value - User = { BindTarget = user }, }, countryRankDisplay = new ProfileValueDisplay(true) { From 40d6e8ce85cbd516a75510299c230d4048fd5b25 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 20 Feb 2024 15:13:22 +0900 Subject: [PATCH 510/915] Remove legacy OpenGL renderer option, it's now just OpenGL --- .../Sections/Graphics/RendererSettings.cs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index fc5dd34971..a8b127d522 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions; @@ -28,15 +27,16 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics var renderer = config.GetBindable(FrameworkSetting.Renderer); automaticRendererInUse = renderer.Value == RendererType.Automatic; - SettingsEnumDropdown rendererDropdown; - Children = new Drawable[] { - rendererDropdown = new RendererSettingsDropdown + new RendererSettingsDropdown { LabelText = GraphicsSettingsStrings.Renderer, Current = renderer, - Items = host.GetPreferredRenderersForCurrentPlatform().Order().Where(t => t != RendererType.Vulkan), + Items = host.GetPreferredRenderersForCurrentPlatform().Order() +#pragma warning disable CS0612 // Type or member is obsolete + .Where(t => t != RendererType.Vulkan && t != RendererType.OpenGLLegacy), +#pragma warning restore CS0612 // Type or member is obsolete Keywords = new[] { @"compatibility", @"directx" }, }, // TODO: this needs to be a custom dropdown at some point @@ -79,13 +79,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics })); } }); - - // TODO: remove this once we support SDL+android. - if (RuntimeInfo.OS == RuntimeInfo.Platform.Android) - { - rendererDropdown.Items = new[] { RendererType.Automatic, RendererType.OpenGLLegacy }; - rendererDropdown.SetNoticeText("New renderer support for android is coming soon!", true); - } } private partial class RendererSettingsDropdown : SettingsEnumDropdown From 54ef397d56c0499ceb568b2b867978a94b6b98bd Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Tue, 20 Feb 2024 12:57:28 +0200 Subject: [PATCH 511/915] Changed override method now it overrides mods getter instead of calculate fuctions --- .../Overlays/Mods/BeatmapAttributesDisplay.cs | 31 +++------ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 12 ++-- .../Mods/MultiplayerModSelectOverlay.cs | 68 +++++++------------ 3 files changed, 41 insertions(+), 70 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index f010725c8b..21b3a7faa9 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -41,6 +41,7 @@ namespace osu.Game.Overlays.Mods [Resolved] protected Bindable> Mods { get; private set; } = null!; + protected virtual IEnumerable SelectedMods => Mods.Value; public BindableBool Collapsed { get; } = new BindableBool(true); @@ -148,22 +149,6 @@ namespace osu.Game.Overlays.Mods LeftContent.AutoSizeDuration = Content.AutoSizeDuration = transition_duration; } - protected virtual double GetRate() - { - double rate = 1; - foreach (var mod in Mods.Value.OfType()) - rate = mod.ApplyToRate(0, rate); - return rate; - } - - protected virtual BeatmapDifficulty GetDifficulty() - { - BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value!.Difficulty); - foreach (var mod in Mods.Value.OfType()) - mod.ApplyToDifficulty(originalDifficulty); - return originalDifficulty; - } - private void updateValues() => Scheduler.AddOnce(() => { if (BeatmapInfo.Value == null) @@ -180,14 +165,20 @@ namespace osu.Game.Overlays.Mods starRatingDisplay.FinishTransforms(true); }); - double rate = GetRate(); - BeatmapDifficulty originalDifficulty = GetDifficulty(); + double rate = 1; + foreach (var mod in SelectedMods.OfType()) + rate = mod.ApplyToRate(0, rate); + + bpmDisplay.Current.Value = BeatmapInfo.Value.BPM * rate; + + BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value.Difficulty); + + foreach (var mod in SelectedMods.OfType()) + mod.ApplyToDifficulty(originalDifficulty); Ruleset ruleset = GameRuleset.Value.CreateInstance(); BeatmapDifficulty adjustedDifficulty = ruleset.GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); - bpmDisplay.Current.Value = BeatmapInfo.Value.BPM * rate; - TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, adjustedDifficulty); approachRateDisplay.AdjustType.Value = VerticalAttributeDisplay.CalculateEffect(originalDifficulty.ApproachRate, adjustedDifficulty.ApproachRate); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index e29e685ece..f374828a4a 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -114,6 +114,8 @@ namespace osu.Game.Overlays.Mods public IEnumerable AllAvailableMods => AvailableMods.Value.SelectMany(pair => pair.Value); + protected virtual IEnumerable AllSelectedMods => SelectedMods.Value; + private readonly BindableBool customisationVisible = new BindableBool(); private Bindable textSearchStartsActive = null!; @@ -317,7 +319,7 @@ namespace osu.Game.Overlays.Mods SelectedMods.BindValueChanged(_ => { - UpdateRankingInformation(); + updateRankingInformation(); updateFromExternalSelection(); updateCustomisation(); @@ -330,7 +332,7 @@ namespace osu.Game.Overlays.Mods // // See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988 modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); - modSettingChangeTracker.SettingChanged += _ => UpdateRankingInformation(); + modSettingChangeTracker.SettingChanged += _ => updateRankingInformation(); } }, true); @@ -452,17 +454,17 @@ namespace osu.Game.Overlays.Mods modState.ValidForSelection.Value = modState.Mod.Type != ModType.System && modState.Mod.HasImplementation && IsValidMod.Invoke(modState.Mod); } - protected virtual void UpdateRankingInformation() + private void updateRankingInformation() { if (RankingInformationDisplay == null) return; double multiplier = 1.0; - foreach (var mod in SelectedMods.Value) + foreach (var mod in AllSelectedMods) multiplier *= mod.ScoreMultiplier; - RankingInformationDisplay.Ranked.Value = SelectedMods.Value.All(m => m.Ranked); + RankingInformationDisplay.Ranked.Value = AllSelectedMods.All(m => m.Ranked); RankingInformationDisplay.ModMultiplier.Value = multiplier; } diff --git a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs index 78978e25e7..d546392650 100644 --- a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs @@ -1,13 +1,13 @@ // 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.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets; using osu.Game.Online.Rooms; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods @@ -39,30 +39,21 @@ namespace osu.Game.Overlays.Mods multiplayerRoomItem?.BindValueChanged(_ => SelectedMods.TriggerChange()); } - protected override void UpdateRankingInformation() + protected override IEnumerable AllSelectedMods { - if (RankingInformationDisplay == null) - return; - - double multiplier = 1.0; - - foreach (var mod in SelectedMods.Value) - multiplier *= mod.ScoreMultiplier; - - RankingInformationDisplay.Ranked.Value = SelectedMods.Value.All(m => m.Ranked); - - if (multiplayerRoomItem?.Value != null) + get { - Ruleset ruleset = game.Ruleset.Value.CreateInstance(); - var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + IEnumerable allMods = SelectedMods.Value; - foreach (var mod in multiplayerRoomMods) - multiplier *= mod.ScoreMultiplier; + if (multiplayerRoomItem?.Value != null) + { + Ruleset ruleset = game.Ruleset.Value.CreateInstance(); + var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + allMods = allMods.Concat(multiplayerRoomMods); + } - RankingInformationDisplay.Ranked.Value = RankingInformationDisplay.Ranked.Value && multiplayerRoomMods.All(m => m.Ranked); + return allMods; } - - RankingInformationDisplay.ModMultiplier.Value = multiplier; } } @@ -77,34 +68,21 @@ namespace osu.Game.Overlays.Mods multiplayerRoomItem?.BindValueChanged(_ => Mods.TriggerChange()); } - protected override double GetRate() + protected override IEnumerable SelectedMods { - double rate = base.GetRate(); - Ruleset ruleset = GameRuleset.Value.CreateInstance(); - - if (multiplayerRoomItem?.Value != null) + get { - var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - foreach (var mod in multiplayerRoomMods.OfType()) - rate = mod.ApplyToRate(0, rate); + IEnumerable selectedMods = Mods.Value; + + if (multiplayerRoomItem?.Value != null) + { + Ruleset ruleset = GameRuleset.Value.CreateInstance(); + var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + selectedMods = selectedMods.Concat(multiplayerRoomMods); + } + + return selectedMods; } - - return rate; - } - - protected override BeatmapDifficulty GetDifficulty() - { - BeatmapDifficulty originalDifficulty = base.GetDifficulty(); - Ruleset ruleset = GameRuleset.Value.CreateInstance(); - - if (multiplayerRoomItem?.Value != null) - { - var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - foreach (var mod in multiplayerRoomMods.OfType()) - mod.ApplyToDifficulty(originalDifficulty); - } - - return originalDifficulty; } } } From a4288e7ecc8e3b631b8f8a2d43ddbc83c787f033 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Tue, 20 Feb 2024 13:00:59 +0200 Subject: [PATCH 512/915] removed unnecessary changes --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index f374828a4a..5b3bafae45 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -127,8 +127,8 @@ namespace osu.Game.Overlays.Mods private DeselectAllModsButton deselectAllModsButton = null!; private Container aboveColumnsContent = null!; - protected RankingInformationDisplay? RankingInformationDisplay; - protected BeatmapAttributesDisplay? BeatmapAttributesDisplay; + private RankingInformationDisplay? rankingInformationDisplay; + private BeatmapAttributesDisplay? beatmapAttributesDisplay; protected virtual BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new BeatmapAttributesDisplay { @@ -155,8 +155,8 @@ namespace osu.Game.Overlays.Mods if (beatmap == value) return; beatmap = value; - if (IsLoaded && BeatmapAttributesDisplay != null) - BeatmapAttributesDisplay.BeatmapInfo.Value = beatmap?.BeatmapInfo; + if (IsLoaded && beatmapAttributesDisplay != null) + beatmapAttributesDisplay.BeatmapInfo.Value = beatmap?.BeatmapInfo; } } @@ -278,12 +278,12 @@ namespace osu.Game.Overlays.Mods }, Children = new Drawable[] { - RankingInformationDisplay = new RankingInformationDisplay + rankingInformationDisplay = new RankingInformationDisplay { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight }, - BeatmapAttributesDisplay = GetBeatmapAttributesDisplay + beatmapAttributesDisplay = GetBeatmapAttributesDisplay } }); } @@ -359,7 +359,7 @@ namespace osu.Game.Overlays.Mods SearchTextBox.PlaceholderText = SearchTextBox.HasFocus ? Resources.Localisation.Web.CommonStrings.InputSearch : ModSelectOverlayStrings.TabToSearch; - if (BeatmapAttributesDisplay != null) + if (beatmapAttributesDisplay != null) { float rightEdgeOfLastButton = footerButtonFlow.Last().ScreenSpaceDrawQuad.TopRight.X; @@ -371,7 +371,7 @@ namespace osu.Game.Overlays.Mods // only update preview panel's collapsed state after we are fully visible, to ensure all the buttons are where we expect them to be. if (Alpha == 1) - BeatmapAttributesDisplay.Collapsed.Value = screenIsntWideEnough; + beatmapAttributesDisplay.Collapsed.Value = screenIsntWideEnough; footerContentFlow.LayoutDuration = 200; footerContentFlow.LayoutEasing = Easing.OutQuint; @@ -456,7 +456,7 @@ namespace osu.Game.Overlays.Mods private void updateRankingInformation() { - if (RankingInformationDisplay == null) + if (rankingInformationDisplay == null) return; double multiplier = 1.0; @@ -464,8 +464,8 @@ namespace osu.Game.Overlays.Mods foreach (var mod in AllSelectedMods) multiplier *= mod.ScoreMultiplier; - RankingInformationDisplay.Ranked.Value = AllSelectedMods.All(m => m.Ranked); - RankingInformationDisplay.ModMultiplier.Value = multiplier; + rankingInformationDisplay.Ranked.Value = AllSelectedMods.All(m => m.Ranked); + rankingInformationDisplay.ModMultiplier.Value = multiplier; } private void updateCustomisation() From 8199a49ee23f12e729a78658a6decd95df56fbc5 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Tue, 20 Feb 2024 13:11:19 +0200 Subject: [PATCH 513/915] minor look changes --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 1 + osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 21b3a7faa9..7c3c971d76 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -41,6 +41,7 @@ namespace osu.Game.Overlays.Mods [Resolved] protected Bindable> Mods { get; private set; } = null!; + protected virtual IEnumerable SelectedMods => Mods.Value; public BindableBool Collapsed { get; } = new BindableBool(true); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 5b3bafae45..8a3b1954ed 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -464,8 +464,8 @@ namespace osu.Game.Overlays.Mods foreach (var mod in AllSelectedMods) multiplier *= mod.ScoreMultiplier; - rankingInformationDisplay.Ranked.Value = AllSelectedMods.All(m => m.Ranked); rankingInformationDisplay.ModMultiplier.Value = multiplier; + rankingInformationDisplay.Ranked.Value = AllSelectedMods.All(m => m.Ranked); } private void updateCustomisation() From ed028e8d260854fc800a3331bef952682d5e811f Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Tue, 20 Feb 2024 13:13:13 +0200 Subject: [PATCH 514/915] Update MultiplayerModSelectOverlay.cs --- osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs index d546392650..ee087bb149 100644 --- a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs @@ -35,7 +35,6 @@ namespace osu.Game.Overlays.Mods protected override void LoadComplete() { base.LoadComplete(); - multiplayerRoomItem?.BindValueChanged(_ => SelectedMods.TriggerChange()); } From 4a314a8e316273ff1f23b4003ea232d413b31ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 11:17:18 +0100 Subject: [PATCH 515/915] Namespacify data structures used in websocket communications --- osu.Game/Online/Chat/WebSocketChatClient.cs | 2 ++ .../Notifications/WebSocket/{ => Events}/NewChatMessageData.cs | 2 +- .../Notifications/WebSocket/{ => Requests}/EndChatRequest.cs | 2 +- .../Notifications/WebSocket/{ => Requests}/StartChatRequest.cs | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) rename osu.Game/Online/Notifications/WebSocket/{ => Events}/NewChatMessageData.cs (94%) rename osu.Game/Online/Notifications/WebSocket/{ => Requests}/EndChatRequest.cs (89%) rename osu.Game/Online/Notifications/WebSocket/{ => Requests}/StartChatRequest.cs (89%) diff --git a/osu.Game/Online/Chat/WebSocketChatClient.cs b/osu.Game/Online/Chat/WebSocketChatClient.cs index 8e1b501b25..37774a1f5d 100644 --- a/osu.Game/Online/Chat/WebSocketChatClient.cs +++ b/osu.Game/Online/Chat/WebSocketChatClient.cs @@ -13,6 +13,8 @@ using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Notifications.WebSocket; +using osu.Game.Online.Notifications.WebSocket.Events; +using osu.Game.Online.Notifications.WebSocket.Requests; namespace osu.Game.Online.Chat { diff --git a/osu.Game/Online/Notifications/WebSocket/NewChatMessageData.cs b/osu.Game/Online/Notifications/WebSocket/Events/NewChatMessageData.cs similarity index 94% rename from osu.Game/Online/Notifications/WebSocket/NewChatMessageData.cs rename to osu.Game/Online/Notifications/WebSocket/Events/NewChatMessageData.cs index 850fbd226b..ff9f5ee9f7 100644 --- a/osu.Game/Online/Notifications/WebSocket/NewChatMessageData.cs +++ b/osu.Game/Online/Notifications/WebSocket/Events/NewChatMessageData.cs @@ -8,7 +8,7 @@ using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; -namespace osu.Game.Online.Notifications.WebSocket +namespace osu.Game.Online.Notifications.WebSocket.Events { /// /// A websocket message sent from the server when new messages arrive. diff --git a/osu.Game/Online/Notifications/WebSocket/EndChatRequest.cs b/osu.Game/Online/Notifications/WebSocket/Requests/EndChatRequest.cs similarity index 89% rename from osu.Game/Online/Notifications/WebSocket/EndChatRequest.cs rename to osu.Game/Online/Notifications/WebSocket/Requests/EndChatRequest.cs index 7f67587f5d..9058fea815 100644 --- a/osu.Game/Online/Notifications/WebSocket/EndChatRequest.cs +++ b/osu.Game/Online/Notifications/WebSocket/Requests/EndChatRequest.cs @@ -3,7 +3,7 @@ using Newtonsoft.Json; -namespace osu.Game.Online.Notifications.WebSocket +namespace osu.Game.Online.Notifications.WebSocket.Requests { /// /// A websocket message notifying the server that the client no longer wants to receive chat messages. diff --git a/osu.Game/Online/Notifications/WebSocket/StartChatRequest.cs b/osu.Game/Online/Notifications/WebSocket/Requests/StartChatRequest.cs similarity index 89% rename from osu.Game/Online/Notifications/WebSocket/StartChatRequest.cs rename to osu.Game/Online/Notifications/WebSocket/Requests/StartChatRequest.cs index 9dd69a7377..bc96415642 100644 --- a/osu.Game/Online/Notifications/WebSocket/StartChatRequest.cs +++ b/osu.Game/Online/Notifications/WebSocket/Requests/StartChatRequest.cs @@ -3,7 +3,7 @@ using Newtonsoft.Json; -namespace osu.Game.Online.Notifications.WebSocket +namespace osu.Game.Online.Notifications.WebSocket.Requests { /// /// A websocket message notifying the server that the client wants to receive chat messages. From 48bf9680e135d1ca528828d411047d338cc07c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 11:29:59 +0100 Subject: [PATCH 516/915] Add new structures for receiving new medal data --- .../Events/NewPrivateNotificationEvent.cs | 39 +++++++++++++++++++ .../WebSocket/Events/UserAchievementUnlock.cs | 34 ++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 osu.Game/Online/Notifications/WebSocket/Events/NewPrivateNotificationEvent.cs create mode 100644 osu.Game/Online/Notifications/WebSocket/Events/UserAchievementUnlock.cs diff --git a/osu.Game/Online/Notifications/WebSocket/Events/NewPrivateNotificationEvent.cs b/osu.Game/Online/Notifications/WebSocket/Events/NewPrivateNotificationEvent.cs new file mode 100644 index 0000000000..1fc9636136 --- /dev/null +++ b/osu.Game/Online/Notifications/WebSocket/Events/NewPrivateNotificationEvent.cs @@ -0,0 +1,39 @@ +// 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; +using Newtonsoft.Json.Linq; + +namespace osu.Game.Online.Notifications.WebSocket.Events +{ + /// + /// Reference: https://github.com/ppy/osu-web/blob/master/app/Events/NewPrivateNotificationEvent.php + /// + public class NewPrivateNotificationEvent + { + [JsonProperty("id")] + public ulong ID { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } = string.Empty; + + [JsonProperty("created_at")] + public DateTimeOffset CreatedAt { get; set; } + + [JsonProperty("object_type")] + public string ObjectType { get; set; } = string.Empty; + + [JsonProperty("object_id")] + public ulong ObjectId { get; set; } + + [JsonProperty("source_user_id")] + public uint SourceUserID { get; set; } + + [JsonProperty("is_read")] + public bool IsRead { get; set; } + + [JsonProperty("details")] + public JObject? Details { get; set; } + } +} diff --git a/osu.Game/Online/Notifications/WebSocket/Events/UserAchievementUnlock.cs b/osu.Game/Online/Notifications/WebSocket/Events/UserAchievementUnlock.cs new file mode 100644 index 0000000000..6c7c8af4f4 --- /dev/null +++ b/osu.Game/Online/Notifications/WebSocket/Events/UserAchievementUnlock.cs @@ -0,0 +1,34 @@ +// 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; + +namespace osu.Game.Online.Notifications.WebSocket.Events +{ + /// + /// Reference: https://github.com/ppy/osu-web/blob/master/app/Jobs/Notifications/UserAchievementUnlock.php + /// + public class UserAchievementUnlock + { + [JsonProperty("achievement_id")] + public uint AchievementId { get; set; } + + [JsonProperty("achievement_mode")] + public ushort? AchievementMode { get; set; } + + [JsonProperty("cover_url")] + public string CoverUrl { get; set; } = string.Empty; + + [JsonProperty("slug")] + public string Slug { get; set; } = string.Empty; + + [JsonProperty("title")] + public string Title { get; set; } = string.Empty; + + [JsonProperty("description")] + public string Description { get; set; } = string.Empty; + + [JsonProperty("user_id")] + public uint UserId { get; set; } + } +} From 4911f5208b2ba6903aa3ec807ba246238bf501d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 12:03:12 +0100 Subject: [PATCH 517/915] Demote medal "overlay" to animation I need the actual overlay to be doing way more things (receiving the actual websocket events, queueing the medals for display, handling activation mode), so the pre-existing API design of the overlay just will not fly. --- osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs | 2 +- osu.Game/Overlays/{MedalOverlay.cs => MedalAnimation.cs} | 4 ++-- osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename osu.Game/Overlays/{MedalOverlay.cs => MedalAnimation.cs} (99%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index 71ed0a14a2..afd4427629 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep(@"display", () => { - LoadComponentAsync(new MedalOverlay(new Medal + LoadComponentAsync(new MedalAnimation(new Medal { Name = @"Animations", InternalName = @"all-intro-doubletime", diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalAnimation.cs similarity index 99% rename from osu.Game/Overlays/MedalOverlay.cs rename to osu.Game/Overlays/MedalAnimation.cs index eba35ec6f9..80c06be87c 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalAnimation.cs @@ -27,7 +27,7 @@ using osu.Framework.Utils; namespace osu.Game.Overlays { - public partial class MedalOverlay : FocusedOverlayContainer + public partial class MedalAnimation : VisibilityContainer { public const float DISC_SIZE = 400; @@ -45,7 +45,7 @@ namespace osu.Game.Overlays private readonly Container content; - public MedalOverlay(Medal medal) + public MedalAnimation(Medal medal) { this.medal = medal; RelativeSizeAxes = Axes.Both; diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index f4f6fd2bc1..2beed6645a 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.MedalSplash public DrawableMedal(Medal medal) { this.medal = medal; - Position = new Vector2(0f, MedalOverlay.DISC_SIZE / 2); + Position = new Vector2(0f, MedalAnimation.DISC_SIZE / 2); FillFlowContainer infoFlow; Children = new Drawable[] @@ -174,7 +174,7 @@ namespace osu.Game.Overlays.MedalSplash .ScaleTo(1); this.ScaleTo(scale_when_unlocked, duration, Easing.OutExpo); - this.MoveToY(MedalOverlay.DISC_SIZE / 2 - 30, duration, Easing.OutExpo); + this.MoveToY(MedalAnimation.DISC_SIZE / 2 - 30, duration, Easing.OutExpo); unlocked.FadeInFromZero(duration); break; @@ -184,7 +184,7 @@ namespace osu.Game.Overlays.MedalSplash .ScaleTo(1); this.ScaleTo(scale_when_full, duration, Easing.OutExpo); - this.MoveToY(MedalOverlay.DISC_SIZE / 2 - 60, duration, Easing.OutExpo); + this.MoveToY(MedalAnimation.DISC_SIZE / 2 - 60, duration, Easing.OutExpo); unlocked.Show(); name.FadeInFromZero(duration + 100); description.FadeInFromZero(duration * 2); From 4f321e242bd7650c0bfe9afec4d3746188df3cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 12:05:25 +0100 Subject: [PATCH 518/915] Enable NRT in `OsuFocusedOverlayContainer` --- .../Containers/OsuFocusedOverlayContainer.cs | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 162c4b6a59..16539a812d 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -20,10 +18,10 @@ namespace osu.Game.Graphics.Containers [Cached(typeof(IPreviewTrackOwner))] public abstract partial class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrackOwner, IKeyBindingHandler { - private Sample samplePopIn; - private Sample samplePopOut; - protected virtual string PopInSampleName => "UI/overlay-pop-in"; - protected virtual string PopOutSampleName => "UI/overlay-pop-out"; + protected readonly IBindable OverlayActivationMode = new Bindable(OverlayActivation.All); + + protected virtual string PopInSampleName => @"UI/overlay-pop-in"; + protected virtual string PopOutSampleName => @"UI/overlay-pop-out"; protected virtual double PopInOutSampleBalance => 0; protected override bool BlockNonPositionalInput => true; @@ -34,19 +32,20 @@ namespace osu.Game.Graphics.Containers /// protected virtual bool DimMainContent => true; - [Resolved(CanBeNull = true)] - private IOverlayManager overlayManager { get; set; } + [Resolved] + private IOverlayManager? overlayManager { get; set; } [Resolved] - private PreviewTrackManager previewTrackManager { get; set; } + private PreviewTrackManager previewTrackManager { get; set; } = null!; - protected readonly IBindable OverlayActivationMode = new Bindable(OverlayActivation.All); + private Sample? samplePopIn; + private Sample? samplePopOut; - [BackgroundDependencyLoader(true)] - private void load(AudioManager audio) + [BackgroundDependencyLoader] + private void load(AudioManager? audio) { - samplePopIn = audio.Samples.Get(PopInSampleName); - samplePopOut = audio.Samples.Get(PopOutSampleName); + samplePopIn = audio?.Samples.Get(PopInSampleName); + samplePopOut = audio?.Samples.Get(PopOutSampleName); } protected override void LoadComplete() From 2e5b61302ab2652b09ac8fe57e48d76315b0d85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 12:53:46 +0100 Subject: [PATCH 519/915] Implement basic medal display flow --- .../Visual/Gameplay/TestSceneMedalOverlay.cs | 45 +++++-- .../Containers/OsuFocusedOverlayContainer.cs | 11 +- osu.Game/Overlays/MedalAnimation.cs | 15 +-- osu.Game/Overlays/MedalOverlay.cs | 112 ++++++++++++++++++ 4 files changed, 155 insertions(+), 28 deletions(-) create mode 100644 osu.Game/Overlays/MedalOverlay.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index afd4427629..ead5c5b418 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs @@ -1,26 +1,51 @@ // 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.Linq; using NUnit.Framework; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Online.API; +using osu.Game.Online.Notifications.WebSocket; +using osu.Game.Online.Notifications.WebSocket.Events; using osu.Game.Overlays; -using osu.Game.Users; +using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public partial class TestSceneMedalOverlay : OsuTestScene + public partial class TestSceneMedalOverlay : OsuManualInputManagerTestScene { - public TestSceneMedalOverlay() + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + + private MedalOverlay overlay = null!; + + [SetUpSteps] + public void SetUpSteps() { - AddStep(@"display", () => + AddStep("create overlay", () => Child = overlay = new MedalOverlay()); + } + + [Test] + public void TestBasicAward() + { + AddStep("award medal", () => dummyAPI.NotificationsClient.Receive(new SocketMessage { - LoadComponentAsync(new MedalAnimation(new Medal + Event = @"new", + Data = JObject.FromObject(new NewPrivateNotificationEvent { - Name = @"Animations", - InternalName = @"all-intro-doubletime", - Description = @"More complex than you think.", - }), Add); - }); + Name = @"user_achievement_unlock", + Details = JObject.FromObject(new UserAchievementUnlock + { + Title = "Time And A Half", + Description = "Having a right ol' time. One and a half of them, almost.", + Slug = @"all-intro-doubletime" + }) + }) + })); + AddUntilStep("overlay shown", () => overlay.State.Value, () => Is.EqualTo(Visibility.Visible)); + AddRepeatStep("dismiss", () => InputManager.Key(Key.Escape), 2); + AddUntilStep("overlay hidden", () => overlay.State.Value, () => Is.EqualTo(Visibility.Hidden)); } } } diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 16539a812d..1945b2f0dd 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -20,8 +20,8 @@ namespace osu.Game.Graphics.Containers { protected readonly IBindable OverlayActivationMode = new Bindable(OverlayActivation.All); - protected virtual string PopInSampleName => @"UI/overlay-pop-in"; - protected virtual string PopOutSampleName => @"UI/overlay-pop-out"; + protected virtual string? PopInSampleName => @"UI/overlay-pop-in"; + protected virtual string? PopOutSampleName => @"UI/overlay-pop-out"; protected virtual double PopInOutSampleBalance => 0; protected override bool BlockNonPositionalInput => true; @@ -44,8 +44,11 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader] private void load(AudioManager? audio) { - samplePopIn = audio?.Samples.Get(PopInSampleName); - samplePopOut = audio?.Samples.Get(PopOutSampleName); + if (!string.IsNullOrEmpty(PopInSampleName)) + samplePopIn = audio?.Samples.Get(PopInSampleName); + + if (!string.IsNullOrEmpty(PopOutSampleName)) + samplePopOut = audio?.Samples.Get(PopOutSampleName); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/MedalAnimation.cs b/osu.Game/Overlays/MedalAnimation.cs index 80c06be87c..041929be67 100644 --- a/osu.Game/Overlays/MedalAnimation.cs +++ b/osu.Game/Overlays/MedalAnimation.cs @@ -18,11 +18,9 @@ using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Audio; using osu.Framework.Graphics.Textures; -using osuTK.Input; using osu.Framework.Graphics.Shapes; using System; using osu.Framework.Graphics.Effects; -using osu.Framework.Input.Events; using osu.Framework.Utils; namespace osu.Game.Overlays @@ -190,17 +188,6 @@ namespace osu.Game.Overlays particleContainer.Add(new MedalParticle(RNG.Next(0, 359))); } - protected override bool OnClick(ClickEvent e) - { - dismiss(); - return true; - } - - protected override void OnFocusLost(FocusLostEvent e) - { - if (e.CurrentState.Keyboard.Keys.IsPressed(Key.Escape)) dismiss(); - } - private const double initial_duration = 400; private const double step_duration = 900; @@ -256,7 +243,7 @@ namespace osu.Game.Overlays this.FadeOut(200); } - private void dismiss() + public void Dismiss() { if (drawableMedal.State != DisplayState.Full) { diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs new file mode 100644 index 0000000000..c3d7b4b9fc --- /dev/null +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -0,0 +1,112 @@ +// 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.ObjectExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; +using osu.Game.Online.API; +using osu.Game.Online.Notifications.WebSocket; +using osu.Game.Online.Notifications.WebSocket.Events; +using osu.Game.Users; + +namespace osu.Game.Overlays +{ + public partial class MedalOverlay : OsuFocusedOverlayContainer + { + protected override string? PopInSampleName => null; + protected override string? PopOutSampleName => null; + + protected override void PopIn() => this.FadeIn(); + + protected override void PopOut() + { + showingMedals = false; + this.FadeOut(); + } + + [Resolved] + private IAPIProvider api { get; set; } = null!; + + private Container medalContainer = null!; + private bool showingMedals; + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Both; + + api.NotificationsClient.MessageReceived += handleMedalMessages; + + Add(medalContainer = new Container + { + RelativeSizeAxes = Axes.Both + }); + } + + private void handleMedalMessages(SocketMessage obj) + { + if (obj.Event != @"new") + return; + + var data = obj.Data?.ToObject(); + if (data == null || data.Name != @"user_achievement_unlock") + return; + + var details = data.Details?.ToObject(); + if (details == null) + return; + + var medal = new Medal + { + Name = details.Title, + InternalName = details.Slug, + Description = details.Description, + }; + + Show(); + LoadComponentAsync(new MedalAnimation(medal), animation => + { + medalContainer.Add(animation); + showingMedals = true; + }); + } + + protected override void Update() + { + base.Update(); + + if (showingMedals && !medalContainer.Any()) + Hide(); + } + + protected override bool OnClick(ClickEvent e) + { + (medalContainer.FirstOrDefault(anim => anim.IsAlive) as MedalAnimation)?.Dismiss(); + return true; + } + + public override bool OnPressed(KeyBindingPressEvent e) + { + if (e.Action == GlobalAction.Back) + { + (medalContainer.FirstOrDefault(anim => anim.IsAlive) as MedalAnimation)?.Dismiss(); + return true; + } + + return base.OnPressed(e); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (api.IsNotNull()) + api.NotificationsClient.MessageReceived -= handleMedalMessages; + } + } +} From e4971ae121cf6078cf7e1150cf5176e26d093250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 13:08:02 +0100 Subject: [PATCH 520/915] Add display queueing when multiple medals are granted in quick succession --- .../Visual/Gameplay/TestSceneMedalOverlay.cs | 51 ++++++++++++++----- osu.Game/Overlays/MedalOverlay.cs | 12 ++++- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index ead5c5b418..a33c7e662f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs @@ -29,23 +29,48 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestBasicAward() { - AddStep("award medal", () => dummyAPI.NotificationsClient.Receive(new SocketMessage + awardMedal(new UserAchievementUnlock { - Event = @"new", - Data = JObject.FromObject(new NewPrivateNotificationEvent - { - Name = @"user_achievement_unlock", - Details = JObject.FromObject(new UserAchievementUnlock - { - Title = "Time And A Half", - Description = "Having a right ol' time. One and a half of them, almost.", - Slug = @"all-intro-doubletime" - }) - }) - })); + Title = "Time And A Half", + Description = "Having a right ol' time. One and a half of them, almost.", + Slug = @"all-intro-doubletime" + }); AddUntilStep("overlay shown", () => overlay.State.Value, () => Is.EqualTo(Visibility.Visible)); AddRepeatStep("dismiss", () => InputManager.Key(Key.Escape), 2); AddUntilStep("overlay hidden", () => overlay.State.Value, () => Is.EqualTo(Visibility.Hidden)); } + + [Test] + public void TestMultipleMedalsInQuickSuccession() + { + awardMedal(new UserAchievementUnlock + { + Title = "Time And A Half", + Description = "Having a right ol' time. One and a half of them, almost.", + Slug = @"all-intro-doubletime" + }); + awardMedal(new UserAchievementUnlock + { + Title = "S-Ranker", + Description = "Accuracy is really underrated.", + Slug = @"all-secret-rank-s" + }); + awardMedal(new UserAchievementUnlock + { + Title = "500 Combo", + Description = "500 big ones! You're moving up in the world!", + Slug = @"osu-combo-500" + }); + } + + private void awardMedal(UserAchievementUnlock unlock) => AddStep("award medal", () => dummyAPI.NotificationsClient.Receive(new SocketMessage + { + Event = @"new", + Data = JObject.FromObject(new NewPrivateNotificationEvent + { + Name = @"user_achievement_unlock", + Details = JObject.FromObject(unlock) + }) + })); } } diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index c3d7b4b9fc..70cde43924 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.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.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; @@ -29,6 +30,8 @@ namespace osu.Game.Overlays this.FadeOut(); } + private readonly Queue queuedMedals = new Queue(); + [Resolved] private IAPIProvider api { get; set; } = null!; @@ -71,7 +74,7 @@ namespace osu.Game.Overlays Show(); LoadComponentAsync(new MedalAnimation(medal), animation => { - medalContainer.Add(animation); + queuedMedals.Enqueue(animation); showingMedals = true; }); } @@ -80,7 +83,12 @@ namespace osu.Game.Overlays { base.Update(); - if (showingMedals && !medalContainer.Any()) + if (!showingMedals || medalContainer.Any()) + return; + + if (queuedMedals.TryDequeue(out var nextMedal)) + medalContainer.Add(nextMedal); + else Hide(); } From b334b78b636a7d4504f3509c88fbf2542d8f4f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 13:44:25 +0100 Subject: [PATCH 521/915] Make medal overlay respect overlay disable via activation mode --- .../Visual/Gameplay/TestSceneMedalOverlay.cs | 35 ++++++++++++++++-- osu.Game/Overlays/MedalOverlay.cs | 36 +++++++++++-------- osu.Game/Properties/AssemblyInfo.cs | 3 ++ 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index a33c7e662f..fe9c524285 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using Moq; using Newtonsoft.Json.Linq; using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Online.API; @@ -16,14 +19,26 @@ namespace osu.Game.Tests.Visual.Gameplay [TestFixture] public partial class TestSceneMedalOverlay : OsuManualInputManagerTestScene { - private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + private readonly Bindable overlayActivationMode = new Bindable(OverlayActivation.All); + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; private MedalOverlay overlay = null!; [SetUpSteps] public void SetUpSteps() { - AddStep("create overlay", () => Child = overlay = new MedalOverlay()); + var overlayManagerMock = new Mock(); + overlayManagerMock.Setup(mock => mock.OverlayActivationMode).Returns(overlayActivationMode); + + AddStep("create overlay", () => Child = new DependencyProvidingContainer + { + Child = overlay = new MedalOverlay(), + RelativeSizeAxes = Axes.Both, + CachedDependencies = + [ + (typeof(IOverlayManager), overlayManagerMock.Object) + ] + }); } [Test] @@ -63,6 +78,22 @@ namespace osu.Game.Tests.Visual.Gameplay }); } + [Test] + public void TestDelayMedalDisplayUntilActivationModeAllowsIt() + { + AddStep("disable overlay activation", () => overlayActivationMode.Value = OverlayActivation.Disabled); + awardMedal(new UserAchievementUnlock + { + Title = "Time And A Half", + Description = "Having a right ol' time. One and a half of them, almost.", + Slug = @"all-intro-doubletime" + }); + AddUntilStep("overlay hidden", () => overlay.State.Value, () => Is.EqualTo(Visibility.Hidden)); + + AddStep("re-enable overlay activation", () => overlayActivationMode.Value = OverlayActivation.All); + AddUntilStep("overlay shown", () => overlay.State.Value, () => Is.EqualTo(Visibility.Visible)); + } + private void awardMedal(UserAchievementUnlock unlock) => AddStep("award medal", () => dummyAPI.NotificationsClient.Receive(new SocketMessage { Event = @"new", diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 70cde43924..03beba2d3b 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -24,11 +24,7 @@ namespace osu.Game.Overlays protected override void PopIn() => this.FadeIn(); - protected override void PopOut() - { - showingMedals = false; - this.FadeOut(); - } + protected override void PopOut() => this.FadeOut(); private readonly Queue queuedMedals = new Queue(); @@ -36,7 +32,6 @@ namespace osu.Game.Overlays private IAPIProvider api { get; set; } = null!; private Container medalContainer = null!; - private bool showingMedals; [BackgroundDependencyLoader] private void load() @@ -51,6 +46,17 @@ namespace osu.Game.Overlays }); } + protected override void LoadComplete() + { + base.LoadComplete(); + + OverlayActivationMode.BindValueChanged(val => + { + if (val.NewValue != OverlayActivation.Disabled && queuedMedals.Any()) + Show(); + }, true); + } + private void handleMedalMessages(SocketMessage obj) { if (obj.Event != @"new") @@ -71,25 +77,25 @@ namespace osu.Game.Overlays Description = details.Description, }; + var medalAnimation = new MedalAnimation(medal); + queuedMedals.Enqueue(medalAnimation); Show(); - LoadComponentAsync(new MedalAnimation(medal), animation => - { - queuedMedals.Enqueue(animation); - showingMedals = true; - }); } protected override void Update() { base.Update(); - if (!showingMedals || medalContainer.Any()) + if (medalContainer.Any()) return; - if (queuedMedals.TryDequeue(out var nextMedal)) - medalContainer.Add(nextMedal); - else + if (!queuedMedals.TryDequeue(out var medal)) + { Hide(); + return; + } + + LoadComponentAsync(medal, medalContainer.Add); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Properties/AssemblyInfo.cs b/osu.Game/Properties/AssemblyInfo.cs index 1b77e45891..be430a0fe4 100644 --- a/osu.Game/Properties/AssemblyInfo.cs +++ b/osu.Game/Properties/AssemblyInfo.cs @@ -11,3 +11,6 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Tests.Dynamic")] [assembly: InternalsVisibleTo("osu.Game.Tests.iOS")] [assembly: InternalsVisibleTo("osu.Game.Tests.Android")] + +// intended for Moq usage +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] From 8abcc70b938c1ba6d23c1d61ac15cf7cad31b02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 14:33:08 +0100 Subject: [PATCH 522/915] Add medal overlay to game --- .../Navigation/TestSceneScreenNavigation.cs | 25 +++++++++++++++++++ osu.Game/OsuGame.cs | 1 + 2 files changed, 26 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 7e42d4781d..0fa2fd4b0b 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -6,6 +6,7 @@ using System; using System.IO; using System.Linq; +using Newtonsoft.Json.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -24,6 +25,8 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Leaderboards; +using osu.Game.Online.Notifications.WebSocket; +using osu.Game.Online.Notifications.WebSocket.Events; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; using osu.Game.Overlays.Mods; @@ -340,6 +343,28 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for results", () => Game.ScreenStack.CurrentScreen is ResultsScreen); } + [Test] + public void TestShowMedalAtResults() + { + playToResults(); + + AddStep("award medal", () => ((DummyAPIAccess)API).NotificationsClient.Receive(new SocketMessage + { + Event = @"new", + Data = JObject.FromObject(new NewPrivateNotificationEvent + { + Name = @"user_achievement_unlock", + Details = JObject.FromObject(new UserAchievementUnlock + { + Title = "Time And A Half", + Description = "Having a right ol' time. One and a half of them, almost.", + Slug = @"all-intro-doubletime" + }) + }) + })); + AddUntilStep("medal overlay shown", () => Game.ChildrenOfType().Single().State.Value, () => Is.EqualTo(Visibility.Visible)); + } + [Test] public void TestRetryFromResults() { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9ffa88947b..a829758f0e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1072,6 +1072,7 @@ namespace osu.Game loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); loadComponentSingleFile(wikiOverlay = new WikiOverlay(), overlayContent.Add, true); loadComponentSingleFile(skinEditor = new SkinEditorOverlay(ScreenContainer), overlayContent.Add, true); + loadComponentSingleFile(new MedalOverlay(), overlayContent.Add); loadComponentSingleFile(new LoginOverlay { From 96825915f73c558265f736472e95d7e6c68fa19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 15:02:30 +0100 Subject: [PATCH 523/915] Fix threading failure Implicitly showing the medal overlay fires off some transforms, and the websocket listener runs on a TPL thread. That's a recipe for disaster, so schedule the show call. --- osu.Game/Overlays/MedalOverlay.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 03beba2d3b..76936e0f5a 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -22,6 +22,8 @@ namespace osu.Game.Overlays protected override string? PopInSampleName => null; protected override string? PopOutSampleName => null; + public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; + protected override void PopIn() => this.FadeIn(); protected override void PopOut() => this.FadeOut(); @@ -52,7 +54,7 @@ namespace osu.Game.Overlays OverlayActivationMode.BindValueChanged(val => { - if (val.NewValue != OverlayActivation.Disabled && queuedMedals.Any()) + if (val.NewValue != OverlayActivation.Disabled && (queuedMedals.Any() || medalContainer.Any())) Show(); }, true); } @@ -79,7 +81,7 @@ namespace osu.Game.Overlays var medalAnimation = new MedalAnimation(medal); queuedMedals.Enqueue(medalAnimation); - Show(); + Scheduler.AddOnce(Show); } protected override void Update() From 611e3fe76bd0930e0ef0320c57ba23658e9b2bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 15:52:15 +0100 Subject: [PATCH 524/915] Delay medal display when wanting to show results animation --- osu.Game/Overlays/MedalOverlay.cs | 5 +++-- .../Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 5 +++++ osu.Game/Screens/Ranking/ResultsScreen.cs | 8 ++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 76936e0f5a..3601566dda 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -54,7 +54,7 @@ namespace osu.Game.Overlays OverlayActivationMode.BindValueChanged(val => { - if (val.NewValue != OverlayActivation.Disabled && (queuedMedals.Any() || medalContainer.Any())) + if (val.NewValue == OverlayActivation.All && (queuedMedals.Any() || medalContainer.Any())) Show(); }, true); } @@ -81,7 +81,8 @@ namespace osu.Game.Overlays var medalAnimation = new MedalAnimation(medal); queuedMedals.Enqueue(medalAnimation); - Scheduler.AddOnce(Show); + if (OverlayActivationMode.Value == OverlayActivation.All) + Scheduler.AddOnce(Show); } protected override void Update() diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index d209c305fa..f807126614 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -31,6 +31,11 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy /// public partial class AccuracyCircle : CompositeDrawable { + /// + /// The total duration of the animation. + /// + public const double TOTAL_DURATION = APPEAR_DURATION + ACCURACY_TRANSFORM_DELAY + ACCURACY_TRANSFORM_DURATION; + /// /// Duration for the transforms causing this component to appear. /// diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 69cfbed8f2..93114b1d18 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -25,8 +25,10 @@ using osu.Game.Input.Bindings; using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Online.Placeholders; +using osu.Game.Overlays; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osu.Game.Screens.Ranking.Expanded.Accuracy; using osu.Game.Screens.Ranking.Statistics; using osuTK; @@ -41,6 +43,8 @@ namespace osu.Game.Screens.Ranking public override bool? AllowGlobalTrackControl => true; + protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; + public readonly Bindable SelectedScore = new Bindable(); [CanBeNull] @@ -160,6 +164,10 @@ namespace osu.Game.Screens.Ranking bool shouldFlair = player != null && !Score.User.IsBot; ScorePanelList.AddScore(Score, shouldFlair); + // this is mostly for medal display. + // we don't want the medal animation to trample on the results screen animation, so we (ab)use `OverlayActivationMode` + // to give the results screen enough time to play the animation out before the medals can be shown. + Scheduler.AddDelayed(() => OverlayActivationMode.Value = OverlayActivation.All, shouldFlair ? AccuracyCircle.TOTAL_DURATION + 1000 : 0); } if (allowWatchingReplay) From 1db5cd3abadcc5f24ceada0092fcf8e2d7ece869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 16:16:30 +0100 Subject: [PATCH 525/915] Move medal overlay to topmost container --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a829758f0e..dbdc86e016 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1072,7 +1072,6 @@ namespace osu.Game loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); loadComponentSingleFile(wikiOverlay = new WikiOverlay(), overlayContent.Add, true); loadComponentSingleFile(skinEditor = new SkinEditorOverlay(ScreenContainer), overlayContent.Add, true); - loadComponentSingleFile(new MedalOverlay(), overlayContent.Add); loadComponentSingleFile(new LoginOverlay { @@ -1088,6 +1087,7 @@ namespace osu.Game loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); + loadComponentSingleFile(new MedalOverlay(), topMostOverlayContent.Add); loadComponentSingleFile(CreateHighPerformanceSession(), Add); From e9aca9226a43285bded225e75465b41045965938 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Feb 2024 19:10:03 +0300 Subject: [PATCH 526/915] Reduce allocations in ManiaPlayfield.TotalColumns --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 0d36f51943..b3420c49f3 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Mania.Beatmaps; @@ -149,7 +148,18 @@ namespace osu.Game.Rulesets.Mania.UI /// /// Retrieves the total amount of columns across all stages in this playfield. /// - public int TotalColumns => stages.Sum(s => s.Columns.Length); + public int TotalColumns + { + get + { + int sum = 0; + + foreach (var stage in stages) + sum += stage.Columns.Length; + + return sum; + } + } private Stage getStageByColumn(int column) { From 9b938f333de39b0d497cab545f4e0719e17c9b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 17:25:11 +0100 Subject: [PATCH 527/915] Fix test failures --- osu.Game/Overlays/MedalOverlay.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 3601566dda..072d7db6c7 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -34,6 +34,7 @@ namespace osu.Game.Overlays private IAPIProvider api { get; set; } = null!; private Container medalContainer = null!; + private MedalAnimation? lastAnimation; [BackgroundDependencyLoader] private void load() @@ -54,7 +55,7 @@ namespace osu.Game.Overlays OverlayActivationMode.BindValueChanged(val => { - if (val.NewValue == OverlayActivation.All && (queuedMedals.Any() || medalContainer.Any())) + if (val.NewValue == OverlayActivation.All && (queuedMedals.Any() || medalContainer.Any() || lastAnimation?.IsLoaded == false)) Show(); }, true); } @@ -89,21 +90,21 @@ namespace osu.Game.Overlays { base.Update(); - if (medalContainer.Any()) + if (medalContainer.Any() || lastAnimation?.IsLoaded == false) return; - if (!queuedMedals.TryDequeue(out var medal)) + if (!queuedMedals.TryDequeue(out lastAnimation)) { Hide(); return; } - LoadComponentAsync(medal, medalContainer.Add); + LoadComponentAsync(lastAnimation, medalContainer.Add); } protected override bool OnClick(ClickEvent e) { - (medalContainer.FirstOrDefault(anim => anim.IsAlive) as MedalAnimation)?.Dismiss(); + lastAnimation?.Dismiss(); return true; } @@ -111,7 +112,7 @@ namespace osu.Game.Overlays { if (e.Action == GlobalAction.Back) { - (medalContainer.FirstOrDefault(anim => anim.IsAlive) as MedalAnimation)?.Dismiss(); + lastAnimation?.Dismiss(); return true; } From 6678c4783bc338287b6465f65cf7a8bb3ee2d288 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Feb 2024 19:31:28 +0300 Subject: [PATCH 528/915] Fix PlaybackControl string allocations --- osu.Game/Screens/Edit/Components/PlaybackControl.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 431336aa60..a5ed0d680f 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -97,11 +97,14 @@ namespace osu.Game.Screens.Edit.Components editorClock.Start(); } + private static readonly IconUsage play_icon = FontAwesome.Regular.PlayCircle; + private static readonly IconUsage pause_icon = FontAwesome.Regular.PauseCircle; + protected override void Update() { base.Update(); - playButton.Icon = editorClock.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle; + playButton.Icon = editorClock.IsRunning ? pause_icon : play_icon; } private partial class PlaybackTabControl : OsuTabControl From 33a0dcaf20fad0c79802367f81b9a370a9be035f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 17:59:21 +0100 Subject: [PATCH 529/915] NRT-annotate `MedalAnimation` and fix possible nullref --- osu.Game/Overlays/MedalAnimation.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/MedalAnimation.cs b/osu.Game/Overlays/MedalAnimation.cs index 041929be67..25776d50db 100644 --- a/osu.Game/Overlays/MedalAnimation.cs +++ b/osu.Game/Overlays/MedalAnimation.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osuTK; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; @@ -20,6 +18,7 @@ using osu.Framework.Audio; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Shapes; using System; +using System.Diagnostics; using osu.Framework.Graphics.Effects; using osu.Framework.Utils; @@ -37,9 +36,9 @@ namespace osu.Game.Overlays private readonly BackgroundStrip leftStrip, rightStrip; private readonly CircularContainer disc; private readonly Sprite innerSpin, outerSpin; - private DrawableMedal drawableMedal; - private Sample getSample; + private DrawableMedal? drawableMedal; + private Sample? getSample; private readonly Container content; @@ -197,7 +196,7 @@ namespace osu.Game.Overlays background.FlashColour(Color4.White.Opacity(0.25f), 400); - getSample.Play(); + getSample?.Play(); innerSpin.Spin(20000, RotationDirection.Clockwise); outerSpin.Spin(40000, RotationDirection.Clockwise); @@ -216,6 +215,8 @@ namespace osu.Game.Overlays leftStrip.ResizeWidthTo(1f, step_duration, Easing.OutQuint); rightStrip.ResizeWidthTo(1f, step_duration, Easing.OutQuint); + Debug.Assert(drawableMedal != null); + this.Animate().Schedule(() => { if (drawableMedal.State != DisplayState.Full) @@ -245,7 +246,7 @@ namespace osu.Game.Overlays public void Dismiss() { - if (drawableMedal.State != DisplayState.Full) + if (drawableMedal != null && drawableMedal.State != DisplayState.Full) { // if we haven't yet, play out the animation fully drawableMedal.State = DisplayState.Full; From 871bdb9cf7919088f0344cf9c9f6ca37b204b622 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Feb 2024 19:38:57 +0300 Subject: [PATCH 530/915] Reduce string allocations in TimeInfoContainer --- .../Edit/Components/TimeInfoContainer.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index 9c51258f17..4747828bca 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -47,11 +47,26 @@ namespace osu.Game.Screens.Edit.Components }; } + private double? lastTime; + private double? lastBPM; + protected override void Update() { base.Update(); - trackTimer.Text = editorClock.CurrentTime.ToEditorFormattedString(); - bpm.Text = @$"{editorBeatmap.ControlPointInfo.TimingPointAt(editorClock.CurrentTime).BPM:0} BPM"; + + if (lastTime != editorClock.CurrentTime) + { + lastTime = editorClock.CurrentTime; + trackTimer.Text = editorClock.CurrentTime.ToEditorFormattedString(); + } + + double newBPM = editorBeatmap.ControlPointInfo.TimingPointAt(editorClock.CurrentTime).BPM; + + if (lastBPM != newBPM) + { + lastBPM = newBPM; + bpm.Text = @$"{newBPM:0} BPM"; + } } } } From e5be8838e68e10cc11c14dc11f5ee1dbfb5a69eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Feb 2024 18:42:01 +0100 Subject: [PATCH 531/915] Fix yet another failure --- osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index fe9c524285..5dc553b9df 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.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.Linq; using Moq; using Newtonsoft.Json.Linq; using NUnit.Framework; @@ -51,6 +52,7 @@ namespace osu.Game.Tests.Visual.Gameplay Slug = @"all-intro-doubletime" }); AddUntilStep("overlay shown", () => overlay.State.Value, () => Is.EqualTo(Visibility.Visible)); + AddUntilStep("wait for load", () => this.ChildrenOfType().Any()); AddRepeatStep("dismiss", () => InputManager.Key(Key.Escape), 2); AddUntilStep("overlay hidden", () => overlay.State.Value, () => Is.EqualTo(Visibility.Hidden)); } From b92cff9a8ed370c59fca69dba9b9cb9923efa737 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Feb 2024 20:29:35 +0300 Subject: [PATCH 532/915] Reduce allocations in ManiaSelectionBlueprint --- .../Blueprints/ManiaSelectionBlueprint.cs | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index 1ae65dd8c0..c645ddd98d 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects; @@ -17,9 +18,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private Playfield playfield { get; set; } = null!; - [Resolved] - private IScrollingInfo scrollingInfo { get; set; } = null!; - protected ScrollingHitObjectContainer HitObjectContainer => ((ManiaPlayfield)playfield).GetColumn(HitObject.Column).HitObjectContainer; protected ManiaSelectionBlueprint(T hitObject) @@ -28,14 +26,31 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints RelativeSizeAxes = Axes.None; } - protected override void Update() - { - base.Update(); + private readonly IBindable directionBindable = new Bindable(); - var anchor = scrollingInfo.Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + [BackgroundDependencyLoader] + private void load(IScrollingInfo scrollingInfo) + { + directionBindable.BindTo(scrollingInfo.Direction); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + directionBindable.BindValueChanged(onDirectionChanged, true); + } + + private void onDirectionChanged(ValueChangedEvent direction) + { + var anchor = direction.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; Anchor = Origin = anchor; foreach (var child in InternalChildren) child.Anchor = child.Origin = anchor; + } + + protected override void Update() + { + base.Update(); Position = Parent!.ToLocalSpace(HitObjectContainer.ScreenSpacePositionAtTime(HitObject.StartTime)) - AnchorPosition; Width = HitObjectContainer.DrawWidth; From 2543a48ac83a2983b76da3bfe5d63f55ad3b1544 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 20 Feb 2024 23:18:37 +0300 Subject: [PATCH 533/915] Apply padding to GridContainers directly --- .../Chat/ChannelList/ChannelListItem.cs | 56 ++++---- .../Profile/Header/DetailHeaderContainer.cs | 63 ++++----- osu.Game/Screens/Edit/BottomBar.cs | 46 +++---- .../Compose/Components/BeatDivisorControl.cs | 89 +++++------- .../Screens/Edit/EditorScreenWithTimeline.cs | 35 ++--- .../Screens/Edit/Timing/TapTimingControl.cs | 35 ++--- osu.Game/Screens/Edit/Verify/VerifyScreen.cs | 24 ++-- .../Components/MatchBeatmapDetailArea.cs | 52 ++++--- .../Lounge/Components/PillContainer.cs | 30 ++-- .../Playlists/PlaylistsRoomSubScreen.cs | 42 +++--- .../ContractedPanelMiddleContent.cs | 50 ++++--- osu.Game/Screens/Select/BeatmapDetails.cs | 129 +++++++++--------- 12 files changed, 292 insertions(+), 359 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs index 21b6147113..87b1f4ef01 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs @@ -66,41 +66,37 @@ namespace osu.Game.Overlays.Chat.ChannelList Colour = colourProvider.Background4, Alpha = 0f, }, - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = 18, Right = 10 }, - Child = new GridContainer + ColumnDimensions = new[] { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new Drawable?[] - { - createIcon(), - text = new TruncatingSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Text = Channel.Name, - Font = OsuFont.Torus.With(size: 17, weight: FontWeight.SemiBold), - Colour = colourProvider.Light3, - Margin = new MarginPadding { Bottom = 2 }, - RelativeSizeAxes = Axes.X, - }, - createMentionPill(), - close = createCloseButton(), - } - }, + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), }, - }, + Content = new[] + { + new Drawable?[] + { + createIcon(), + text = new TruncatingSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Text = Channel.Name, + Font = OsuFont.Torus.With(size: 17, weight: FontWeight.SemiBold), + Colour = colourProvider.Light3, + Margin = new MarginPadding { Bottom = 2 }, + RelativeSizeAxes = Axes.X, + }, + createMentionPill(), + close = createCloseButton(), + } + } + } }; Action = () => OnRequestSelect?.Invoke(Channel); diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 1f35f39b49..118bf9171e 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -26,47 +26,42 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background5, }, - new Container + new GridContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = 10 }, - Child = new GridContainer + RowDimensions = new[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - RowDimensions = new[] + new Dimension(GridSizeMode.AutoSize), + }, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] { - new Dimension(GridSizeMode.AutoSize), - }, - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new Drawable[] + new MainDetails { - new MainDetails - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User } - }, - new Box - { - RelativeSizeAxes = Axes.Y, - Width = 2, - Colour = colourProvider.Background6, - Margin = new MarginPadding { Horizontal = 15 } - }, - new ExtendedDetails - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - User = { BindTarget = User } - } + RelativeSizeAxes = Axes.X, + User = { BindTarget = User } + }, + new Box + { + RelativeSizeAxes = Axes.Y, + Width = 2, + Colour = colourProvider.Background6, + Margin = new MarginPadding { Horizontal = 15 } + }, + new ExtendedDetails + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + User = { BindTarget = User } } } } diff --git a/osu.Game/Screens/Edit/BottomBar.cs b/osu.Game/Screens/Edit/BottomBar.cs index aa3c4ba0d0..bc7dfaab88 100644 --- a/osu.Game/Screens/Edit/BottomBar.cs +++ b/osu.Game/Screens/Edit/BottomBar.cs @@ -47,35 +47,31 @@ namespace osu.Game.Screens.Edit RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background4, }, - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, - Child = new GridContainer + ColumnDimensions = new[] { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Absolute, 170), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 220), - new Dimension(GridSizeMode.Absolute, HitObjectComposer.TOOLBOX_CONTRACTED_SIZE_RIGHT), - }, - Content = new[] - { - new Drawable[] - { - new TimeInfoContainer { RelativeSizeAxes = Axes.Both }, - new SummaryTimeline { RelativeSizeAxes = Axes.Both }, - new PlaybackControl { RelativeSizeAxes = Axes.Both }, - TestGameplayButton = new TestGameplayButton - { - RelativeSizeAxes = Axes.Both, - Size = new Vector2(1), - Action = editor.TestGameplay, - } - }, - } + new Dimension(GridSizeMode.Absolute, 170), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 220), + new Dimension(GridSizeMode.Absolute, HitObjectComposer.TOOLBOX_CONTRACTED_SIZE_RIGHT), }, + Content = new[] + { + new Drawable[] + { + new TimeInfoContainer { RelativeSizeAxes = Axes.Both }, + new SummaryTimeline { RelativeSizeAxes = Axes.Both }, + new PlaybackControl { RelativeSizeAxes = Axes.Both }, + TestGameplayButton = new TestGameplayButton + { + RelativeSizeAxes = Axes.Both, + Size = new Vector2(1), + Action = editor.TestGameplay, + } + }, + } } }; } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index da1a37d57f..40b97d2137 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -86,35 +86,31 @@ namespace osu.Game.Screens.Edit.Compose.Components RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background3 }, - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, - Child = new GridContainer + Content = new[] { - RelativeSizeAxes = Axes.Both, - Content = new[] + new Drawable[] { - new Drawable[] + new ChevronButton { - new ChevronButton - { - Icon = FontAwesome.Solid.ChevronLeft, - Action = beatDivisor.SelectPrevious - }, - new DivisorDisplay { BeatDivisor = { BindTarget = beatDivisor } }, - new ChevronButton - { - Icon = FontAwesome.Solid.ChevronRight, - Action = beatDivisor.SelectNext - } + Icon = FontAwesome.Solid.ChevronLeft, + Action = beatDivisor.SelectPrevious }, + new DivisorDisplay { BeatDivisor = { BindTarget = beatDivisor } }, + new ChevronButton + { + Icon = FontAwesome.Solid.ChevronRight, + Action = beatDivisor.SelectNext + } }, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Absolute, 20), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 20) - } + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 20), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 20) } } } @@ -122,42 +118,31 @@ namespace osu.Game.Screens.Edit.Compose.Components }, new Drawable[] { - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + Content = new[] { - new Container + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Child = new GridContainer + new ChevronButton { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new ChevronButton - { - Icon = FontAwesome.Solid.ChevronLeft, - Action = () => cycleDivisorType(-1) - }, - new DivisorTypeText { BeatDivisor = { BindTarget = beatDivisor } }, - new ChevronButton - { - Icon = FontAwesome.Solid.ChevronRight, - Action = () => cycleDivisorType(1) - } - }, - }, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Absolute, 20), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 20) - } + Icon = FontAwesome.Solid.ChevronLeft, + Action = () => cycleDivisorType(-1) + }, + new DivisorTypeText { BeatDivisor = { BindTarget = beatDivisor } }, + new ChevronButton + { + Icon = FontAwesome.Solid.ChevronRight, + Action = () => cycleDivisorType(1) } - } + }, + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 20), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 20) } } }, diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 575a66d421..2b97d363f1 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -57,37 +57,32 @@ namespace osu.Game.Screens.Edit RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background4 }, - new Container + new GridContainer { Name = "Timeline content", RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Horizontal = PADDING, Top = PADDING }, - Child = new GridContainer + Content = new[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Content = new[] + new Drawable[] { - new Drawable[] + TimelineContent = new Container { - TimelineContent = new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, }, }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - }, - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 90), - } }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + }, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.Absolute, 90), + } } } }, diff --git a/osu.Game/Screens/Edit/Timing/TapTimingControl.cs b/osu.Game/Screens/Edit/Timing/TapTimingControl.cs index bb7a3b8be3..8cdbd97ecb 100644 --- a/osu.Game/Screens/Edit/Timing/TapTimingControl.cs +++ b/osu.Game/Screens/Edit/Timing/TapTimingControl.cs @@ -65,35 +65,28 @@ namespace osu.Game.Screens.Edit.Timing { new Drawable[] { - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(padding), - Children = new Drawable[] + ColumnDimensions = new[] { - new GridContainer + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + metronome = new MetronomeDisplay { - new Dimension(GridSizeMode.AutoSize), - new Dimension() - }, - Content = new[] - { - new Drawable[] - { - metronome = new MetronomeDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - new WaveformComparisonDisplay() - } + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, }, + new WaveformComparisonDisplay() } - } - }, + }, + } }, new Drawable[] { diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs index b6e0450e23..fe508860e0 100644 --- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs +++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs @@ -34,25 +34,21 @@ namespace osu.Game.Screens.Edit.Verify InterpretedDifficulty.Default = StarDifficulty.GetDifficultyRating(EditorBeatmap.BeatmapInfo.StarRating); InterpretedDifficulty.SetDefault(); - Child = new Container + Child = new GridContainer { RelativeSizeAxes = Axes.Both, - Child = new GridContainer + ColumnDimensions = new[] { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + new Dimension(), + new Dimension(GridSizeMode.Absolute, 250), + }, + Content = new[] + { + new Drawable[] { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 250), + IssueList = new IssueList(), + new IssueSettings(), }, - Content = new[] - { - new Drawable[] - { - IssueList = new IssueList(), - new IssueSettings(), - }, - } } }; } diff --git a/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs b/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs index dec91d8a37..b0ede8d9b5 100644 --- a/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs +++ b/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs @@ -26,48 +26,44 @@ namespace osu.Game.Screens.OnlinePlay.Components [Resolved(typeof(Room))] protected BindableList Playlist { get; private set; } - private readonly Drawable playlistArea; + private readonly GridContainer playlistArea; private readonly DrawableRoomPlaylist playlist; public MatchBeatmapDetailArea() { - Add(playlistArea = new Container + Add(playlistArea = new GridContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Vertical = 10 }, - Child = new GridContainer + Content = new[] { - RelativeSizeAxes = Axes.Both, - Content = new[] + new Drawable[] { - new Drawable[] + new Container { - new Container + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Bottom = 10 }, + Child = playlist = new PlaylistsRoomSettingsPlaylist { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Bottom = 10 }, - Child = playlist = new PlaylistsRoomSettingsPlaylist - { - RelativeSizeAxes = Axes.Both - } + RelativeSizeAxes = Axes.Both } - }, - new Drawable[] - { - new RoundedButton - { - Text = "Add new playlist entry", - RelativeSizeAxes = Axes.Both, - Size = Vector2.One, - Action = () => CreateNewItem?.Invoke() - } - }, + } }, - RowDimensions = new[] + new Drawable[] { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 50), - } + new RoundedButton + { + Text = "Add new playlist entry", + RelativeSizeAxes = Axes.Both, + Size = Vector2.One, + Action = () => CreateNewItem?.Invoke() + } + }, + }, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.Absolute, 50), } }); } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs index b473ea82c6..5f77742588 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs @@ -40,35 +40,31 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Colour = Color4.Black, Alpha = 0.5f }, - new Container + new GridContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = padding }, - Child = new GridContainer + ColumnDimensions = new[] { - AutoSizeAxes = Axes.Both, - ColumnDimensions = new[] + new Dimension(GridSizeMode.AutoSize, minSize: 80 - 2 * padding) + }, + Content = new[] + { + new[] { - new Dimension(GridSizeMode.AutoSize, minSize: 80 - 2 * padding) - }, - Content = new[] - { - new[] + new Container { - new Container + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Padding = new MarginPadding { Bottom = 2 }, + Child = content = new Container { AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Padding = new MarginPadding { Bottom = 2 }, - Child = content = new Container - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } } } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index cf5a8e1985..2460f78c96 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -95,38 +95,34 @@ namespace osu.Game.Screens.OnlinePlay.Playlists new Drawable[] { // Playlist items column - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = 5 }, - Child = new GridContainer + Content = new[] { - RelativeSizeAxes = Axes.Both, - Content = new[] + new Drawable[] { new OverlinedPlaylistHeader(), }, + new Drawable[] { - new Drawable[] { new OverlinedPlaylistHeader(), }, - new Drawable[] + new DrawableRoomPlaylist { - new DrawableRoomPlaylist + RelativeSizeAxes = Axes.Both, + Items = { BindTarget = Room.Playlist }, + SelectedItem = { BindTarget = SelectedItem }, + AllowSelection = true, + AllowShowingResults = true, + RequestResults = item => { - RelativeSizeAxes = Axes.Both, - Items = { BindTarget = Room.Playlist }, - SelectedItem = { BindTarget = SelectedItem }, - AllowSelection = true, - AllowShowingResults = true, - RequestResults = item => - { - Debug.Assert(RoomId.Value != null); - ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item, false)); - } + Debug.Assert(RoomId.Value != null); + ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item, false)); } - }, + } }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - } + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), } }, // Spacer diff --git a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs index 195cd03e9b..cfb6465e62 100644 --- a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs @@ -150,44 +150,40 @@ namespace osu.Game.Screens.Ranking.Contracted }, new Drawable[] { - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Vertical = 5 }, - Child = new GridContainer + Content = new[] { - RelativeSizeAxes = Axes.Both, - Content = new[] + new Drawable[] { - new Drawable[] + new OsuSpriteText { - new OsuSpriteText + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = scoreManager.GetBindableTotalScoreString(score), + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, fixedWidth: true), + Spacing = new Vector2(-1, 0) + }, + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 2 }, + Child = new DrawableRank(score.Rank) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Current = scoreManager.GetBindableTotalScoreString(score), - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, fixedWidth: true), - Spacing = new Vector2(-1, 0) - }, - }, - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 2 }, - Child = new DrawableRank(score.Rank) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } } - }, + } }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - } + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), } } }, diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index dec2c1c1de..2bb60716ff 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -75,99 +75,92 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.Both, Colour = Colour4.Black.Opacity(0.3f), }, - new Container + new GridContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = spacing }, - Children = new Drawable[] + RowDimensions = new[] { - new GridContainer + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + new FillFlowContainer { - new Dimension(GridSizeMode.AutoSize), - new Dimension() - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Children = new Drawable[] { new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Children = new Drawable[] + Width = 0.5f, + Spacing = new Vector2(spacing), + Padding = new MarginPadding { Right = spacing / 2 }, + Children = new[] { - new FillFlowContainer + new DetailBox().WithChild(new OnlineViewContainer(string.Empty) { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.5f, - Spacing = new Vector2(spacing), - Padding = new MarginPadding { Right = spacing / 2 }, - Children = new[] + Height = 134, + Padding = new MarginPadding { Horizontal = spacing, Top = spacing }, + Child = ratingsDisplay = new UserRatings { - new DetailBox().WithChild(new OnlineViewContainer(string.Empty) - { - RelativeSizeAxes = Axes.X, - Height = 134, - Padding = new MarginPadding { Horizontal = spacing, Top = spacing }, - Child = ratingsDisplay = new UserRatings - { - RelativeSizeAxes = Axes.Both, - }, - }), + RelativeSizeAxes = Axes.Both, }, - }, - new OsuScrollContainer + }), + }, + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.X, + Height = 250, + Width = 0.5f, + ScrollbarVisible = false, + Padding = new MarginPadding { Left = spacing / 2 }, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + LayoutDuration = transition_duration, + LayoutEasing = Easing.OutQuad, + Children = new[] { - RelativeSizeAxes = Axes.X, - Height = 250, - Width = 0.5f, - ScrollbarVisible = false, - Padding = new MarginPadding { Left = spacing / 2 }, - Child = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - LayoutDuration = transition_duration, - LayoutEasing = Easing.OutQuad, - Children = new[] - { - description = new MetadataSectionDescription(query => songSelect?.Search(query)), - source = new MetadataSectionSource(query => songSelect?.Search(query)), - tags = new MetadataSectionTags(query => songSelect?.Search(query)), - }, - }, + description = new MetadataSectionDescription(query => songSelect?.Search(query)), + source = new MetadataSectionSource(query => songSelect?.Search(query)), + tags = new MetadataSectionTags(query => songSelect?.Search(query)), }, }, }, }, - new Drawable[] + }, + }, + new Drawable[] + { + failRetryContainer = new OnlineViewContainer("Sign in to view more details") + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - failRetryContainer = new OnlineViewContainer("Sign in to view more details") + new OsuSpriteText + { + Text = BeatmapsetsStrings.ShowInfoPointsOfFailure, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), + }, + failRetryGraph = new FailRetryGraph { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = BeatmapsetsStrings.ShowInfoPointsOfFailure, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), - }, - failRetryGraph = new FailRetryGraph - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 14 + spacing / 2 }, - }, - }, + Padding = new MarginPadding { Top = 14 + spacing / 2 }, }, - } - } - }, - }, + }, + }, + } + } }, loading = new LoadingLayer(true) }; From 86e3b597b42e79eafdb6ea0722277b6a9882485b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Feb 2024 13:18:51 +0800 Subject: [PATCH 534/915] Fix `LegacyApproachCircle` incorrectly applying scaling factor --- .../Skinning/Legacy/LegacyApproachCircle.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs index 0bdea0cab1..8ff85090ca 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Skinning; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy @@ -26,10 +25,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy var texture = skin.GetTexture(@"approachcircle"); Debug.Assert(texture != null); Texture = texture.WithMaximumSize(OsuHitObject.OBJECT_DIMENSIONS * 2); - - // account for the sprite being used for the default approach circle being taken from stable, - // when hitcircles have 5px padding on each size. this should be removed if we update the sprite. - Scale = new Vector2(128 / 118f); } protected override void LoadComplete() From a11a83ac480f86f9420ee2f78abb01a2912b858d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Feb 2024 13:44:04 +0800 Subject: [PATCH 535/915] Improve comment regarding scale adjust of approach circles --- .../Skinning/Default/DefaultApproachCircle.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs index 272f4b5658..3a4c454bf1 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs @@ -25,8 +25,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default { Texture = textures.Get(@"Gameplay/osu/approachcircle").WithMaximumSize(OsuHitObject.OBJECT_DIMENSIONS * 2); - // account for the sprite being used for the default approach circle being taken from stable, - // when hitcircles have 5px padding on each size. this should be removed if we update the sprite. + // In triangles and argon skins, we expanded hitcircles to take up the full 128 px which are clickable, + // but still use the old approach circle sprite. To make it feel correct (ie. disappear as it collides + // with the hitcircle, *not when it overlaps the border*) we need to expand it slightly. Scale = new Vector2(128 / 118f); } From a137fa548080cf6c5ff5b6d79b427cf23a677d2b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Feb 2024 15:43:53 +0800 Subject: [PATCH 536/915] Fix classic skin follow circles animating from incorrect starting point --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs index fa2bb9b2ad..4a8b737206 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy // Note that the scale adjust here is 2 instead of DrawableSliderBall.FOLLOW_AREA to match legacy behaviour. // This means the actual tracking area for gameplay purposes is larger than the sprite (but skins may be accounting for this). - this.ScaleTo(0.5f).ScaleTo(2f, Math.Min(180f, remainingTime), Easing.Out) + this.ScaleTo(1f).ScaleTo(2f, Math.Min(180f, remainingTime), Easing.Out) .FadeTo(0).FadeTo(1f, Math.Min(60f, remainingTime)); } From 259be976e870db1fcc6f64f1382a23be02919ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 21 Feb 2024 11:42:34 +0100 Subject: [PATCH 537/915] Adjust test to fail --- .../SongSelect/TestSceneBeatmapCarousel.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index aa4c879468..de2ae3708f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -629,7 +629,8 @@ namespace osu.Game.Tests.Visual.SongSelect { var sets = new List(); - const string zzz_string = "zzzzz"; + const string zzz_lowercase = "zzzzz"; + const string zzz_uppercase = "ZZZZZ"; AddStep("Populuate beatmap sets", () => { @@ -640,10 +641,16 @@ namespace osu.Game.Tests.Visual.SongSelect var set = TestResources.CreateTestBeatmapSetInfo(); if (i == 4) - set.Beatmaps.ForEach(b => b.Metadata.Artist = zzz_string); + set.Beatmaps.ForEach(b => b.Metadata.Artist = zzz_uppercase); + + if (i == 8) + set.Beatmaps.ForEach(b => b.Metadata.Artist = zzz_lowercase); + + if (i == 12) + set.Beatmaps.ForEach(b => b.Metadata.Author.Username = zzz_uppercase); if (i == 16) - set.Beatmaps.ForEach(b => b.Metadata.Author.Username = zzz_string); + set.Beatmaps.ForEach(b => b.Metadata.Author.Username = zzz_lowercase); sets.Add(set); } @@ -652,9 +659,11 @@ namespace osu.Game.Tests.Visual.SongSelect loadBeatmaps(sets); AddStep("Sort by author", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Author }, false)); - AddAssert($"Check {zzz_string} is at bottom", () => carousel.BeatmapSets.Last().Metadata.Author.Username == zzz_string); + AddAssert($"Check {zzz_uppercase} is last", () => carousel.BeatmapSets.Last().Metadata.Author.Username == zzz_uppercase); + AddAssert($"Check {zzz_lowercase} is second last", () => carousel.BeatmapSets.SkipLast(1).Last().Metadata.Author.Username == zzz_lowercase); AddStep("Sort by artist", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Artist }, false)); - AddAssert($"Check {zzz_string} is at bottom", () => carousel.BeatmapSets.Last().Metadata.Artist == zzz_string); + AddAssert($"Check {zzz_uppercase} is last", () => carousel.BeatmapSets.Last().Metadata.Artist == zzz_uppercase); + AddAssert($"Check {zzz_lowercase} is second last", () => carousel.BeatmapSets.SkipLast(1).Last().Metadata.Artist == zzz_lowercase); } /// From 59235d6c50a796469bb29440745eec9e13d0e926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 21 Feb 2024 12:07:18 +0100 Subject: [PATCH 538/915] Implement custom comparer for expected carousel sort behaviour Co-authored-by: Salman Ahmed --- .../Utils/OrdinalSortByCaseStringComparer.cs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 osu.Game/Utils/OrdinalSortByCaseStringComparer.cs diff --git a/osu.Game/Utils/OrdinalSortByCaseStringComparer.cs b/osu.Game/Utils/OrdinalSortByCaseStringComparer.cs new file mode 100644 index 0000000000..99d73f644f --- /dev/null +++ b/osu.Game/Utils/OrdinalSortByCaseStringComparer.cs @@ -0,0 +1,49 @@ +// 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; + +namespace osu.Game.Utils +{ + /// + /// This string comparer is something of a cross-over between and . + /// is used first, but is used as a tie-breaker. + /// + /// + /// This comparer's behaviour somewhat emulates , + /// but non-ordinal comparers - both culture-aware and culture-invariant - have huge performance overheads due to i18n factors (up to 5x slower). + /// + /// + /// Given the following strings to sort: [A, B, C, D, a, b, c, d, A] and a stable sorting algorithm: + /// + /// + /// would return [A, A, B, C, D, a, b, c, d]. + /// This is undesirable as letters are interleaved. + /// + /// + /// would return [A, a, A, B, b, C, c, D, d]. + /// Different letters are not interleaved, but because case is ignored, the As are left in arbitrary order. + /// + /// + /// + /// would return [a, A, A, b, B, c, C, d, D], which is the expected behaviour. + /// + /// + public class OrdinalSortByCaseStringComparer : IComparer + { + public static readonly OrdinalSortByCaseStringComparer INSTANCE = new OrdinalSortByCaseStringComparer(); + + private OrdinalSortByCaseStringComparer() + { + } + + public int Compare(string? a, string? b) + { + int result = StringComparer.OrdinalIgnoreCase.Compare(a, b); + if (result == 0) + result = -StringComparer.Ordinal.Compare(a, b); // negative to place lowercase letters before uppercase. + return result; + } + } +} From 04a2ac3df332fda91ae41c2ee9bc5e1300a60d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 21 Feb 2024 12:07:28 +0100 Subject: [PATCH 539/915] Add benchmarking for custom string comparer --- .../BenchmarkStringComparison.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 osu.Game.Benchmarks/BenchmarkStringComparison.cs diff --git a/osu.Game.Benchmarks/BenchmarkStringComparison.cs b/osu.Game.Benchmarks/BenchmarkStringComparison.cs new file mode 100644 index 0000000000..78e4130abe --- /dev/null +++ b/osu.Game.Benchmarks/BenchmarkStringComparison.cs @@ -0,0 +1,48 @@ +// 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 BenchmarkDotNet.Attributes; +using osu.Game.Utils; + +namespace osu.Game.Benchmarks +{ + public class BenchmarkStringComparison + { + private string[] strings = null!; + + [GlobalSetup] + public void GlobalSetUp() + { + strings = new string[10000]; + + for (int i = 0; i < strings.Length; ++i) + strings[i] = Guid.NewGuid().ToString(); + + for (int i = 0; i < strings.Length; ++i) + { + if (i % 2 == 0) + strings[i] = strings[i].ToUpperInvariant(); + } + } + + [Benchmark] + public void OrdinalIgnoreCase() => compare(StringComparer.OrdinalIgnoreCase); + + [Benchmark] + public void OrdinalSortByCase() => compare(OrdinalSortByCaseStringComparer.INSTANCE); + + [Benchmark] + public void InvariantCulture() => compare(StringComparer.InvariantCulture); + + private void compare(IComparer comparer) + { + for (int i = 0; i < strings.Length; ++i) + { + for (int j = i + 1; j < strings.Length; ++j) + _ = comparer.Compare(strings[i], strings[j]); + } + } + } +} From 929858226ad208e29746f1b22b80399623f07d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 21 Feb 2024 12:09:37 +0100 Subject: [PATCH 540/915] Use custom comparer in beatmap carousel for expected sort behaviour --- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 6c41bc3805..bf0d7dcbde 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps; using osu.Game.Screens.Select.Filter; +using osu.Game.Utils; namespace osu.Game.Screens.Select.Carousel { @@ -67,19 +68,19 @@ namespace osu.Game.Screens.Select.Carousel { default: case SortMode.Artist: - comparison = string.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist, StringComparison.Ordinal); + comparison = OrdinalSortByCaseStringComparer.INSTANCE.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist); break; case SortMode.Title: - comparison = string.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title, StringComparison.Ordinal); + comparison = OrdinalSortByCaseStringComparer.INSTANCE.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title); break; case SortMode.Author: - comparison = string.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username, StringComparison.Ordinal); + comparison = OrdinalSortByCaseStringComparer.INSTANCE.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username); break; case SortMode.Source: - comparison = string.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source, StringComparison.Ordinal); + comparison = OrdinalSortByCaseStringComparer.INSTANCE.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source); break; case SortMode.DateAdded: From fb593470d553c68b77e7ec129c47cfd9a21097d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Feb 2024 21:02:20 +0800 Subject: [PATCH 541/915] Use `DEFAULT` instead of `INSTANCE` or static field Matches other similar comparers. --- osu.Game.Benchmarks/BenchmarkStringComparison.cs | 2 +- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 8 ++++---- osu.Game/Utils/OrdinalSortByCaseStringComparer.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Benchmarks/BenchmarkStringComparison.cs b/osu.Game.Benchmarks/BenchmarkStringComparison.cs index 78e4130abe..d40b92db5f 100644 --- a/osu.Game.Benchmarks/BenchmarkStringComparison.cs +++ b/osu.Game.Benchmarks/BenchmarkStringComparison.cs @@ -31,7 +31,7 @@ namespace osu.Game.Benchmarks public void OrdinalIgnoreCase() => compare(StringComparer.OrdinalIgnoreCase); [Benchmark] - public void OrdinalSortByCase() => compare(OrdinalSortByCaseStringComparer.INSTANCE); + public void OrdinalSortByCase() => compare(OrdinalSortByCaseStringComparer.DEFAULT); [Benchmark] public void InvariantCulture() => compare(StringComparer.InvariantCulture); diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index bf0d7dcbde..43c9c621e8 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -68,19 +68,19 @@ namespace osu.Game.Screens.Select.Carousel { default: case SortMode.Artist: - comparison = OrdinalSortByCaseStringComparer.INSTANCE.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist); + comparison = OrdinalSortByCaseStringComparer.DEFAULT.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist); break; case SortMode.Title: - comparison = OrdinalSortByCaseStringComparer.INSTANCE.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title); + comparison = OrdinalSortByCaseStringComparer.DEFAULT.Compare(BeatmapSet.Metadata.Title, otherSet.BeatmapSet.Metadata.Title); break; case SortMode.Author: - comparison = OrdinalSortByCaseStringComparer.INSTANCE.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username); + comparison = OrdinalSortByCaseStringComparer.DEFAULT.Compare(BeatmapSet.Metadata.Author.Username, otherSet.BeatmapSet.Metadata.Author.Username); break; case SortMode.Source: - comparison = OrdinalSortByCaseStringComparer.INSTANCE.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source); + comparison = OrdinalSortByCaseStringComparer.DEFAULT.Compare(BeatmapSet.Metadata.Source, otherSet.BeatmapSet.Metadata.Source); break; case SortMode.DateAdded: diff --git a/osu.Game/Utils/OrdinalSortByCaseStringComparer.cs b/osu.Game/Utils/OrdinalSortByCaseStringComparer.cs index 99d73f644f..6c1532eef5 100644 --- a/osu.Game/Utils/OrdinalSortByCaseStringComparer.cs +++ b/osu.Game/Utils/OrdinalSortByCaseStringComparer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Utils /// public class OrdinalSortByCaseStringComparer : IComparer { - public static readonly OrdinalSortByCaseStringComparer INSTANCE = new OrdinalSortByCaseStringComparer(); + public static readonly OrdinalSortByCaseStringComparer DEFAULT = new OrdinalSortByCaseStringComparer(); private OrdinalSortByCaseStringComparer() { From 6d32cfb7ee7c466a6a8b673ea6b9cac3c66d6ffd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Feb 2024 21:39:33 +0800 Subject: [PATCH 542/915] Update framework --- 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 85171cc0fa..30037c868c 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index f23debd38f..463a726856 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From 805f0b6a296aa2507d97fdeec1f14fe78e8c8854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 21 Feb 2024 14:55:10 +0100 Subject: [PATCH 543/915] Remove unused using directive --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 25fe8170b1..5bf7c0326a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; -using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; From 4cefa8bb8d256228266d204449610f443c6c37d6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 21 Feb 2024 22:47:49 +0300 Subject: [PATCH 544/915] Reduce allocations in TimelineBlueprintContainer --- .../Components/Timeline/TimelineBlueprintContainer.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index b60e04afc1..6ebd1961a2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -116,6 +116,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline updateStacking(); } + private readonly Stack currentConcurrentObjects = new Stack(); + private void updateStacking() { // because only blueprints of objects which are alive (via pooling) are displayed in the timeline, it's feasible to do this every-update. @@ -125,10 +127,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline // after the stack gets this tall, we can presume there is space underneath to draw subsequent blueprints. const int stack_reset_count = 3; - Stack currentConcurrentObjects = new Stack(); + currentConcurrentObjects.Clear(); - foreach (var b in SelectionBlueprints.Reverse()) + for (int i = SelectionBlueprints.Count - 1; i >= 0; i--) { + var b = SelectionBlueprints[i]; + // remove objects from the stack as long as their end time is in the past. while (currentConcurrentObjects.TryPeek(out HitObject hitObject)) { From d01421b951bc308583caa0c687f0715ab55f34de Mon Sep 17 00:00:00 2001 From: Boudewijn Popkema Date: Wed, 21 Feb 2024 23:15:37 +0100 Subject: [PATCH 545/915] clear remembered username when checkbox is unticked --- osu.Game/Overlays/Login/LoginForm.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index 80dfca93d2..a77baa3186 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -13,11 +13,11 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Overlays.Settings; using osu.Game.Resources.Localisation.Web; using osuTK; -using osu.Game.Localisation; namespace osu.Game.Overlays.Login { @@ -26,6 +26,7 @@ namespace osu.Game.Overlays.Login private TextBox username = null!; private TextBox password = null!; private ShakeContainer shakeSignIn = null!; + private SettingsCheckbox rememberUsername = null!; [Resolved] private IAPIProvider api { get; set; } = null!; @@ -82,7 +83,7 @@ namespace osu.Game.Overlays.Login }, }, }, - new SettingsCheckbox + rememberUsername = new SettingsCheckbox { LabelText = LoginPanelStrings.RememberUsername, Current = config.GetBindable(OsuSetting.SaveUsername), @@ -130,6 +131,7 @@ namespace osu.Game.Overlays.Login forgottenPasswordLink.AddLink(LayoutStrings.PopupLoginLoginForgot, $"{api.WebsiteRootUrl}/home/password-reset"); password.OnCommit += (_, _) => performLogin(); + rememberUsername.SettingChanged += () => onRememberUsernameChanged(config); if (api.LastLoginError?.Message is string error) { @@ -146,6 +148,12 @@ namespace osu.Game.Overlays.Login shakeSignIn.Shake(); } + private void onRememberUsernameChanged(OsuConfigManager config) + { + if (rememberUsername.Current.Value == false) + config.SetValue(OsuSetting.Username, string.Empty); + } + protected override bool OnClick(ClickEvent e) => true; protected override void OnFocus(FocusEvent e) From 2831ff60e1a361874f0285f1db74be7fa621300a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 09:39:49 +0100 Subject: [PATCH 546/915] Add test coverage --- .../Visual/Menus/TestSceneLoginOverlay.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index 5fc075ed99..e603f72bb8 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -8,11 +8,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays; using osu.Game.Overlays.Login; +using osu.Game.Overlays.Settings; using osu.Game.Users.Drawables; using osuTK.Input; @@ -25,6 +27,9 @@ namespace osu.Game.Tests.Visual.Menus private LoginOverlay loginOverlay = null!; + [Resolved] + private OsuConfigManager configManager { get; set; } = null!; + [BackgroundDependencyLoader] private void load() { @@ -156,5 +161,36 @@ namespace osu.Game.Tests.Visual.Menus }); AddAssert("login overlay is hidden", () => loginOverlay.State.Value == Visibility.Hidden); } + + [Test] + public void TestUncheckingRememberUsernameClearsIt() + { + AddStep("logout", () => API.Logout()); + AddStep("set username", () => configManager.SetValue(OsuSetting.Username, "test_user")); + AddStep("set remember password", () => configManager.SetValue(OsuSetting.SavePassword, true)); + AddStep("uncheck remember username", () => + { + InputManager.MoveMouseTo(loginOverlay.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + AddAssert("remember username off", () => configManager.Get(OsuSetting.SaveUsername), () => Is.False); + AddAssert("remember password off", () => configManager.Get(OsuSetting.SavePassword), () => Is.False); + AddAssert("username cleared", () => configManager.Get(OsuSetting.Username), () => Is.Empty); + } + + [Test] + public void TestUncheckingRememberPasswordClearsToken() + { + AddStep("logout", () => API.Logout()); + AddStep("set token", () => configManager.SetValue(OsuSetting.Token, "test_token")); + AddStep("set remember password", () => configManager.SetValue(OsuSetting.SavePassword, true)); + AddStep("uncheck remember token", () => + { + InputManager.MoveMouseTo(loginOverlay.ChildrenOfType().Last()); + InputManager.Click(MouseButton.Left); + }); + AddAssert("remember password off", () => configManager.Get(OsuSetting.SavePassword), () => Is.False); + AddAssert("token cleared", () => configManager.Get(OsuSetting.Token), () => Is.Empty); + } } } From a1046f0a865641e5b7ffea225d3ad32b45ae4177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 09:40:27 +0100 Subject: [PATCH 547/915] Revert "clear remembered username when checkbox is unticked" This reverts commit d01421b951bc308583caa0c687f0715ab55f34de. --- osu.Game/Overlays/Login/LoginForm.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index a77baa3186..80dfca93d2 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -13,11 +13,11 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Overlays.Settings; using osu.Game.Resources.Localisation.Web; using osuTK; +using osu.Game.Localisation; namespace osu.Game.Overlays.Login { @@ -26,7 +26,6 @@ namespace osu.Game.Overlays.Login private TextBox username = null!; private TextBox password = null!; private ShakeContainer shakeSignIn = null!; - private SettingsCheckbox rememberUsername = null!; [Resolved] private IAPIProvider api { get; set; } = null!; @@ -83,7 +82,7 @@ namespace osu.Game.Overlays.Login }, }, }, - rememberUsername = new SettingsCheckbox + new SettingsCheckbox { LabelText = LoginPanelStrings.RememberUsername, Current = config.GetBindable(OsuSetting.SaveUsername), @@ -131,7 +130,6 @@ namespace osu.Game.Overlays.Login forgottenPasswordLink.AddLink(LayoutStrings.PopupLoginLoginForgot, $"{api.WebsiteRootUrl}/home/password-reset"); password.OnCommit += (_, _) => performLogin(); - rememberUsername.SettingChanged += () => onRememberUsernameChanged(config); if (api.LastLoginError?.Message is string error) { @@ -148,12 +146,6 @@ namespace osu.Game.Overlays.Login shakeSignIn.Shake(); } - private void onRememberUsernameChanged(OsuConfigManager config) - { - if (rememberUsername.Current.Value == false) - config.SetValue(OsuSetting.Username, string.Empty); - } - protected override bool OnClick(ClickEvent e) => true; protected override void OnFocus(FocusEvent e) From 01f6ab0336a630a588b0938576660a02150bdeb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 09:44:59 +0100 Subject: [PATCH 548/915] Use more correct implementation --- osu.Game/Configuration/OsuConfigManager.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6b2cb4ee74..a71460ded7 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -77,12 +77,19 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.SavePassword, false).ValueChanged += enabled => { - if (enabled.NewValue) SetValue(OsuSetting.SaveUsername, true); + if (enabled.NewValue) + SetValue(OsuSetting.SaveUsername, true); + else + GetBindable(OsuSetting.Token).SetDefault(); }; SetDefault(OsuSetting.SaveUsername, true).ValueChanged += enabled => { - if (!enabled.NewValue) SetValue(OsuSetting.SavePassword, false); + if (!enabled.NewValue) + { + GetBindable(OsuSetting.Username).SetDefault(); + SetValue(OsuSetting.SavePassword, false); + } }; SetDefault(OsuSetting.ExternalLinkWarning, true); From 81a9908c60012bde9ee9135c254ab2b891be5ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 10:27:37 +0100 Subject: [PATCH 549/915] Extract common helper for BPM rounding --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 4 ++-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 7 ++++--- osu.Game/Utils/FormatUtils.cs | 10 ++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 1db02b7cf2..2f0b39bfbd 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.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; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -20,6 +19,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Utils; using osuTK; namespace osu.Game.Overlays.Mods @@ -169,7 +169,7 @@ namespace osu.Game.Overlays.Mods foreach (var mod in mods.Value.OfType()) rate = mod.ApplyToRate(0, rate); - bpmDisplay.Current.Value = (int)Math.Round(Math.Round(BeatmapInfo.Value.BPM) * rate); + bpmDisplay.Current.Value = FormatUtils.RoundBPM(BeatmapInfo.Value.BPM, rate); BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value.Difficulty); diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index c69cd6ead6..3cab4b67b6 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -31,6 +31,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Graphics.Containers; using osu.Game.Resources.Localisation.Web; +using osu.Game.Utils; namespace osu.Game.Screens.Select { @@ -405,9 +406,9 @@ namespace osu.Game.Screens.Select foreach (var mod in mods.Value.OfType()) rate = mod.ApplyToRate(0, rate); - int bpmMax = (int)Math.Round(Math.Round(beatmap.ControlPointInfo.BPMMaximum) * rate); - int bpmMin = (int)Math.Round(Math.Round(beatmap.ControlPointInfo.BPMMinimum) * rate); - int mostCommonBPM = (int)Math.Round(Math.Round(60000 / beatmap.GetMostCommonBeatLength()) * rate); + int bpmMax = FormatUtils.RoundBPM(beatmap.ControlPointInfo.BPMMaximum, rate); + int bpmMin = FormatUtils.RoundBPM(beatmap.ControlPointInfo.BPMMinimum, rate); + int mostCommonBPM = FormatUtils.RoundBPM(60000 / beatmap.GetMostCommonBeatLength(), rate); string labelText = bpmMin == bpmMax ? $"{bpmMin}" diff --git a/osu.Game/Utils/FormatUtils.cs b/osu.Game/Utils/FormatUtils.cs index 799dc75ca9..cccad3711c 100644 --- a/osu.Game/Utils/FormatUtils.cs +++ b/osu.Game/Utils/FormatUtils.cs @@ -49,5 +49,15 @@ namespace osu.Game.Utils return precision; } + + /// + /// Applies rounding to the given BPM value. + /// + /// + /// Double-rounding is applied intentionally (see https://github.com/ppy/osu/pull/18345#issue-1243311382 for rationale). + /// + /// The base BPM to round. + /// Rate adjustment, if applicable. + public static int RoundBPM(double baseBpm, double rate = 1) => (int)Math.Round(Math.Round(baseBpm) * rate); } } From 84fdcd24ef17194422a3aab9f3d6653955cda3d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 10:56:50 +0100 Subject: [PATCH 550/915] Remove description from mod search terms Closes https://github.com/ppy/osu/issues/27111. --- osu.Game/Overlays/Mods/ModPanel.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index 2d8d01d8c8..cf173b0d6a 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -77,12 +77,11 @@ namespace osu.Game.Overlays.Mods /// public bool Visible => modState.Visible; - public override IEnumerable FilterTerms => new[] + public override IEnumerable FilterTerms => new LocalisableString[] { Mod.Name, Mod.Name.Replace(" ", string.Empty), Mod.Acronym, - Mod.Description }; public override bool MatchingFilter From b08fcbd4e953af0051bf9560eba57006763ded43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 10:56:13 +0100 Subject: [PATCH 551/915] Adjust tests to new behaviour --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 99a5897dff..b26e126249 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -788,7 +788,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("all columns visible", () => this.ChildrenOfType().All(col => col.IsPresent)); AddStep("set search", () => modSelectOverlay.SearchTerm = "HD"); - AddAssert("one column visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 1); + AddAssert("two columns visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 2); AddStep("filter out everything", () => modSelectOverlay.SearchTerm = "Some long search term with no matches"); AddAssert("no columns visible", () => this.ChildrenOfType().All(col => !col.IsPresent)); @@ -812,7 +812,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("all columns visible", () => this.ChildrenOfType().All(col => col.IsPresent)); AddStep("set search", () => modSelectOverlay.SearchTerm = "fail"); - AddAssert("one column visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 2); + AddAssert("one column visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 1); AddStep("hide", () => modSelectOverlay.Hide()); AddStep("show", () => modSelectOverlay.Show()); From 47db317df84862a68947c20e71dcfe87c552830f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 11:45:57 +0100 Subject: [PATCH 552/915] Enable NRT in `TestSceneDifficultyIcon` --- osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs index 80320c138b..e544177d50 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,7 +14,7 @@ namespace osu.Game.Tests.Visual.Beatmaps { public partial class TestSceneDifficultyIcon : OsuTestScene { - private FillFlowContainer fill; + private FillFlowContainer fill = null!; protected override void LoadComplete() { @@ -35,7 +33,7 @@ namespace osu.Game.Tests.Visual.Beatmaps [Test] public void CreateDifficultyIcon() { - DifficultyIcon difficultyIcon = null; + DifficultyIcon difficultyIcon = null!; AddRepeatStep("create difficulty icon", () => { From d06c67ad8f921b02990b954256c95c22c5e70f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 11:57:40 +0100 Subject: [PATCH 553/915] Substitute two jank interdependent bool flags for single tri-state enums --- .../Beatmaps/TestSceneDifficultyIcon.cs | 12 ++------ osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 29 ++++++++++++++----- .../Drawables/DifficultyIconTooltip.cs | 11 ++++--- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 2 +- .../OnlinePlay/DrawableRoomPlaylistItem.cs | 2 +- .../Carousel/DrawableCarouselBeatmap.cs | 2 +- 6 files changed, 34 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs index e544177d50..6a226c2b8c 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs @@ -50,18 +50,12 @@ namespace osu.Game.Tests.Visual.Beatmaps fill.Add(difficultyIcon = new DifficultyIcon(beatmapInfo, rulesetInfo) { Scale = new Vector2(2), - ShowTooltip = true, - ShowExtendedTooltip = true }); }, 10); - AddStep("hide extended tooltip", () => difficultyIcon.ShowExtendedTooltip = false); - - AddStep("hide tooltip", () => difficultyIcon.ShowTooltip = false); - - AddStep("show tooltip", () => difficultyIcon.ShowTooltip = true); - - AddStep("show extended tooltip", () => difficultyIcon.ShowExtendedTooltip = true); + AddStep("no tooltip", () => difficultyIcon.TooltipType = DifficultyIconTooltipType.None); + AddStep("basic tooltip", () => difficultyIcon.TooltipType = DifficultyIconTooltipType.StarRating); + AddStep("extended tooltip", () => difficultyIcon.TooltipType = DifficultyIconTooltipType.Extended); } } } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 73073a8286..2e7f894d12 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -32,14 +32,9 @@ namespace osu.Game.Beatmaps.Drawables } /// - /// Whether to display a tooltip on hover. Only works if a beatmap was provided at construction time. + /// Which type of tooltip to show. Only works if a beatmap was provided at construction time. /// - public bool ShowTooltip { get; set; } = true; - - /// - /// Whether to include the difficulty stats in the tooltip or not. Defaults to false. Has no effect if is false. - /// - public bool ShowExtendedTooltip { get; set; } + public DifficultyIconTooltipType TooltipType { get; set; } = DifficultyIconTooltipType.StarRating; private readonly IBeatmapInfo? beatmap; @@ -138,6 +133,24 @@ namespace osu.Game.Beatmaps.Drawables GetCustomTooltip() => new DifficultyIconTooltip(); DifficultyIconTooltipContent IHasCustomTooltip. - TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods, ShowExtendedTooltip) : null)!; + TooltipContent => (TooltipType != DifficultyIconTooltipType.None && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current, ruleset, mods, TooltipType) : null)!; + } + + public enum DifficultyIconTooltipType + { + /// + /// No tooltip. + /// + None, + + /// + /// Star rating only. + /// + StarRating, + + /// + /// Star rating, OD, HP, CS, AR, length, BPM, and max combo. + /// + Extended, } } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 71366de654..952f71332f 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -113,7 +113,7 @@ namespace osu.Game.Beatmaps.Drawables starRating.Current.BindTarget = displayedContent.Difficulty; difficultyName.Text = displayedContent.BeatmapInfo.DifficultyName; - if (!displayedContent.ShowExtendedTooltip) + if (displayedContent.TooltipType == DifficultyIconTooltipType.StarRating) { difficultyFillFlowContainer.Hide(); miscFillFlowContainer.Hide(); @@ -166,15 +166,18 @@ namespace osu.Game.Beatmaps.Drawables public readonly IBindable Difficulty; public readonly IRulesetInfo Ruleset; public readonly Mod[]? Mods; - public readonly bool ShowExtendedTooltip; + public readonly DifficultyIconTooltipType TooltipType; - public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[]? mods, bool showExtendedTooltip = false) + public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty, IRulesetInfo rulesetInfo, Mod[]? mods, DifficultyIconTooltipType tooltipType) { + if (tooltipType == DifficultyIconTooltipType.None) + throw new ArgumentOutOfRangeException(nameof(tooltipType), tooltipType, "Cannot instantiate a tooltip without a type"); + BeatmapInfo = beatmapInfo; Difficulty = difficulty; Ruleset = rulesetInfo; Mods = mods; - ShowExtendedTooltip = showExtendedTooltip; + TooltipType = tooltipType; } } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 1f38e2ed6c..5f021803b0 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -297,7 +297,7 @@ namespace osu.Game.Overlays.BeatmapSet }, icon = new DifficultyIcon(beatmapInfo, ruleset) { - ShowTooltip = false, + TooltipType = DifficultyIconTooltipType.None, Current = { Value = new StarDifficulty(beatmapInfo.StarRating, 0) }, Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 44e91c6975..1b8e2d8be6 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -285,7 +285,7 @@ namespace osu.Game.Screens.OnlinePlay difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods) { Size = new Vector2(icon_height), - ShowExtendedTooltip = true + TooltipType = DifficultyIconTooltipType.Extended, }; } else diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index baf0a14062..01e58d4ab2 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -122,7 +122,7 @@ namespace osu.Game.Screens.Select.Carousel { difficultyIcon = new DifficultyIcon(beatmapInfo) { - ShowTooltip = false, + TooltipType = DifficultyIconTooltipType.None, Scale = new Vector2(1.8f), }, new FillFlowContainer From 37400643605426647eb80097401002828ff0d7ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 11:59:55 +0100 Subject: [PATCH 554/915] Fix test scene not properly setting tooltip type on all icons --- .../Visual/Beatmaps/TestSceneDifficultyIcon.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs index 6a226c2b8c..fb6bebe50d 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultyIcon.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; @@ -14,13 +15,13 @@ namespace osu.Game.Tests.Visual.Beatmaps { public partial class TestSceneDifficultyIcon : OsuTestScene { - private FillFlowContainer fill = null!; + private FillFlowContainer fill = null!; protected override void LoadComplete() { base.LoadComplete(); - Child = fill = new FillFlowContainer + Child = fill = new FillFlowContainer { AutoSizeAxes = Axes.Y, Width = 300, @@ -33,8 +34,6 @@ namespace osu.Game.Tests.Visual.Beatmaps [Test] public void CreateDifficultyIcon() { - DifficultyIcon difficultyIcon = null!; - AddRepeatStep("create difficulty icon", () => { var rulesetInfo = new OsuRuleset().RulesetInfo; @@ -47,15 +46,15 @@ namespace osu.Game.Tests.Visual.Beatmaps beatmapInfo.StarRating = RNG.NextSingle(0, 10); beatmapInfo.BPM = RNG.Next(60, 300); - fill.Add(difficultyIcon = new DifficultyIcon(beatmapInfo, rulesetInfo) + fill.Add(new DifficultyIcon(beatmapInfo, rulesetInfo) { Scale = new Vector2(2), }); }, 10); - AddStep("no tooltip", () => difficultyIcon.TooltipType = DifficultyIconTooltipType.None); - AddStep("basic tooltip", () => difficultyIcon.TooltipType = DifficultyIconTooltipType.StarRating); - AddStep("extended tooltip", () => difficultyIcon.TooltipType = DifficultyIconTooltipType.Extended); + AddStep("no tooltip", () => fill.ForEach(icon => icon.TooltipType = DifficultyIconTooltipType.None)); + AddStep("basic tooltip", () => fill.ForEach(icon => icon.TooltipType = DifficultyIconTooltipType.StarRating)); + AddStep("extended tooltip", () => fill.ForEach(icon => icon.TooltipType = DifficultyIconTooltipType.Extended)); } } } From 7861125e7ac1dcd48c06f5ab005870b5c111c31c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 12:11:49 +0100 Subject: [PATCH 555/915] Swap AR and OD on tooltips Matches everything else. --- osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 952f71332f..1f3dcfee8c 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -78,8 +78,8 @@ namespace osu.Game.Beatmaps.Drawables { circleSize = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, drainRate = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, + overallDifficulty = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, approachRate = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, - overallDifficulty = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) } } }, miscFillFlowContainer = new FillFlowContainer From bbf3f6b56ca29f367b40fb5cc5414aab349820c2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 22 Feb 2024 16:31:13 +0300 Subject: [PATCH 556/915] Fix old-style legacy spinner fade in not matching stable --- .../Skinning/Legacy/LegacyOldStyleSpinner.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs index c57487cf75..c75983f3d2 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs @@ -92,8 +92,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimePreempt)) this.FadeOut(); - using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimeFadeIn / 2)) - this.FadeInFromZero(spinner.TimeFadeIn / 2); + using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimeFadeIn)) + this.FadeInFromZero(spinner.TimeFadeIn); } protected override void Update() From 99bbbf810bfcdbe2d1ee8fea5cecbc86e46ce667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 16:58:21 +0100 Subject: [PATCH 557/915] Update github actions to resolve most node deprecation warnings As is github tradition, workflows started yelling about running on a node version that was getting sunset, so here we go again. Relevant bumps: - https://github.com/actions/checkout/releases/tag/v4.0.0 - https://github.com/actions/setup-dotnet/releases/tag/v4.0.0 - https://github.com/actions/cache/releases/tag/v4.0.0 - https://github.com/actions/setup-java/releases/tag/v4.0.0 - https://github.com/peter-evans/create-pull-request/releases/tag/v6.0.0 - https://github.com/dorny/test-reporter/releases/tag/v1.8.0 Notably, `actions/upload-artifact` is _not_ bumped to v4, although it should be to resolve the node deprecation warnings, because it has more breaking changes and bumping would break `dorny/test-reporter` (see https://github.com/dorny/test-reporter/issues/363). --- .github/workflows/ci.yml | 20 +++++++++---------- .github/workflows/diffcalc.yml | 2 +- .github/workflows/report-nunit.yml | 2 +- .github/workflows/sentry-release.yml | 2 +- .../workflows/update-web-mod-definitions.yml | 10 +++++----- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de902df93f..1ea4654563 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install .NET 8.0.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" @@ -27,7 +27,7 @@ jobs: run: dotnet restore osu.Desktop.slnf - name: Restore inspectcode cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ github.workspace }}/inspectcode key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', 'osu*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }} @@ -70,10 +70,10 @@ jobs: timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install .NET 8.0.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" @@ -99,16 +99,16 @@ jobs: timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup JDK 11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: microsoft java-version: 11 - name: Install .NET 8.0.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" @@ -126,10 +126,10 @@ jobs: timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install .NET 8.0.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml index 5f16e09040..7a2dcecb9c 100644 --- a/.github/workflows/diffcalc.yml +++ b/.github/workflows/diffcalc.yml @@ -140,7 +140,7 @@ jobs: GOOGLE_CREDS_FILE: ${{ steps.set-outputs.outputs.GOOGLE_CREDS_FILE }} steps: - name: Checkout diffcalc-sheet-generator - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ${{ env.EXECUTION_ID }} repository: 'smoogipoo/diffcalc-sheet-generator' diff --git a/.github/workflows/report-nunit.yml b/.github/workflows/report-nunit.yml index 99e39f6f56..c44f46d70a 100644 --- a/.github/workflows/report-nunit.yml +++ b/.github/workflows/report-nunit.yml @@ -28,7 +28,7 @@ jobs: timeout-minutes: 5 steps: - name: Annotate CI run with test results - uses: dorny/test-reporter@v1.6.0 + uses: dorny/test-reporter@v1.8.0 with: artifact: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}} name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}}) diff --git a/.github/workflows/sentry-release.yml b/.github/workflows/sentry-release.yml index ff4165c414..be104d0fd3 100644 --- a/.github/workflows/sentry-release.yml +++ b/.github/workflows/sentry-release.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/.github/workflows/update-web-mod-definitions.yml b/.github/workflows/update-web-mod-definitions.yml index 5827a6cdbf..b19f03ad7d 100644 --- a/.github/workflows/update-web-mod-definitions.yml +++ b/.github/workflows/update-web-mod-definitions.yml @@ -13,23 +13,23 @@ jobs: runs-on: ubuntu-latest steps: - name: Install .NET 8.0.x - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: "8.0.x" - name: Checkout ppy/osu - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: osu - name: Checkout ppy/osu-tools - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ppy/osu-tools path: osu-tools - name: Checkout ppy/osu-web - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ppy/osu-web path: osu-web @@ -43,7 +43,7 @@ jobs: working-directory: ./osu-tools - name: Create pull request with changes - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6 with: title: Update mod definitions body: "This PR has been auto-generated to update the mod definitions to match ppy/osu@${{ github.ref_name }}." From e1ceb8a5fa9abb9512c5e1639ae1132b64a9d272 Mon Sep 17 00:00:00 2001 From: SupDos <6813986+SupDos@users.noreply.github.com> Date: Thu, 22 Feb 2024 18:54:28 +0100 Subject: [PATCH 558/915] Add missing .olz association to iOS --- osu.iOS/Info.plist | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index cf51fe995b..1330e29bc1 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -102,6 +102,19 @@ osz + + UTTypeConformsTo + + sh.ppy.osu.items + + UTTypeIdentifier + sh.ppy.osu.olz + UTTypeTagSpecification + + public.filename-extension + olz + + CFBundleDocumentTypes From 0074bdc5a17be66df7dd656106973829e0909bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 19:15:02 +0100 Subject: [PATCH 559/915] Change `ResultsScreen` constructor boolean params to init-only properties --- .../Background/TestSceneUserDimBackgrounds.cs | 3 ++- .../TestScenePlaylistsResultsScreen.cs | 5 +++-- .../Visual/Ranking/TestSceneResultsScreen.cs | 6 ++++-- osu.Game/OsuGame.cs | 2 +- .../Multiplayer/MultiplayerResultsScreen.cs | 2 +- .../OnlinePlay/Playlists/PlaylistsPlayer.cs | 5 ++++- .../Playlists/PlaylistsResultsScreen.cs | 4 ++-- .../Playlists/PlaylistsRoomSubScreen.cs | 2 +- osu.Game/Screens/Play/Player.cs | 5 +++-- osu.Game/Screens/Play/ReplayPlayer.cs | 2 +- .../Screens/Play/SpectatorResultsScreen.cs | 2 +- osu.Game/Screens/Ranking/ResultsScreen.cs | 19 ++++++++++++------- osu.Game/Screens/Ranking/SoloResultsScreen.cs | 4 ++-- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- 14 files changed, 38 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index 566ccd6bd5..204dea39b2 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -349,8 +349,9 @@ namespace osu.Game.Tests.Visual.Background private partial class FadeAccessibleResults : ResultsScreen { public FadeAccessibleResults(ScoreInfo score) - : base(score, true) + : base(score) { + AllowRetry = true; } protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs index 25ee20b089..fca965052f 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs @@ -420,9 +420,10 @@ namespace osu.Game.Tests.Visual.Playlists public new LoadingSpinner RightSpinner => base.RightSpinner; public new ScorePanelList ScorePanelList => base.ScorePanelList; - public TestResultsScreen([CanBeNull] ScoreInfo score, int roomId, PlaylistItem playlistItem, bool allowRetry = true) - : base(score, roomId, playlistItem, allowRetry) + public TestResultsScreen([CanBeNull] ScoreInfo score, int roomId, PlaylistItem playlistItem) + : base(score, roomId, playlistItem) { + AllowRetry = true; } } } diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index cf4bec54ff..ffc5dbc8fb 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -399,8 +399,9 @@ namespace osu.Game.Tests.Visual.Ranking public HotkeyRetryOverlay RetryOverlay; public TestResultsScreen(ScoreInfo score) - : base(score, true) + : base(score) { + AllowRetry = true; ShowUserStatistics = true; } @@ -470,8 +471,9 @@ namespace osu.Game.Tests.Visual.Ranking public HotkeyRetryOverlay RetryOverlay; public UnrankedSoloResultsScreen(ScoreInfo score) - : base(score, true) + : base(score) { + AllowRetry = true; Score!.BeatmapInfo!.OnlineID = 0; Score.BeatmapInfo.Status = BeatmapOnlineStatus.Pending; } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9ffa88947b..ec44076520 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -768,7 +768,7 @@ namespace osu.Game break; case ScorePresentType.Results: - screen.Push(new SoloResultsScreen(databasedScore.ScoreInfo, false)); + screen.Push(new SoloResultsScreen(databasedScore.ScoreInfo)); break; } }, validScreens: validScreens); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index f665ed2d41..6ed75508dc 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -10,7 +10,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public partial class MultiplayerResultsScreen : PlaylistsResultsScreen { public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem) - : base(score, roomId, playlistItem, false) + : base(score, roomId, playlistItem) { } } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs index b0e4585986..74454959a1 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs @@ -58,7 +58,10 @@ namespace osu.Game.Screens.OnlinePlay.Playlists protected override ResultsScreen CreateResults(ScoreInfo score) { Debug.Assert(Room.RoomID.Value != null); - return new PlaylistsResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem, true); + return new PlaylistsResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem) + { + AllowRetry = true, + }; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs index 6a1924dea2..add7aee8cd 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs @@ -41,8 +41,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists [Resolved] private RulesetStore rulesets { get; set; } - public PlaylistsResultsScreen([CanBeNull] ScoreInfo score, long roomId, PlaylistItem playlistItem, bool allowRetry, bool allowWatchingReplay = true) - : base(score, allowRetry, allowWatchingReplay) + public PlaylistsResultsScreen([CanBeNull] ScoreInfo score, long roomId, PlaylistItem playlistItem) + : base(score) { this.roomId = roomId; this.playlistItem = playlistItem; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 2460f78c96..3fb9de428a 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -114,7 +114,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists RequestResults = item => { Debug.Assert(RoomId.Value != null); - ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item, false)); + ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item)); } } }, diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 11ff5fdbef..8383936f7c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1224,9 +1224,10 @@ namespace osu.Game.Screens.Play /// /// The to be displayed in the results screen. /// The . - protected virtual ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score, true) + protected virtual ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score) { - ShowUserStatistics = true + AllowRetry = true, + ShowUserStatistics = true, }; private void fadeOut(bool instant = false) diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 3c5b85662a..ff60dbc0d0 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Play Scores = { BindTarget = LeaderboardScores } }; - protected override ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score, false); + protected override ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score); public bool OnPressed(KeyBindingPressEvent e) { diff --git a/osu.Game/Screens/Play/SpectatorResultsScreen.cs b/osu.Game/Screens/Play/SpectatorResultsScreen.cs index 393cbddb34..5ee2a5ce0e 100644 --- a/osu.Game/Screens/Play/SpectatorResultsScreen.cs +++ b/osu.Game/Screens/Play/SpectatorResultsScreen.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Play public partial class SpectatorResultsScreen : SoloResultsScreen { public SpectatorResultsScreen(ScoreInfo score) - : base(score, false) + : base(score) { } diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 69cfbed8f2..6beb4d7401 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -63,16 +63,21 @@ namespace osu.Game.Screens.Ranking private bool lastFetchCompleted; - private readonly bool allowRetry; - private readonly bool allowWatchingReplay; + /// + /// Whether the user can retry the beatmap from the results screen. + /// + public bool AllowRetry { get; init; } + + /// + /// Whether the user can watch the replay of the completed play from the results screen. + /// + public bool AllowWatchingReplay { get; init; } = true; private Sample popInSample; - protected ResultsScreen([CanBeNull] ScoreInfo score, bool allowRetry, bool allowWatchingReplay = true) + protected ResultsScreen([CanBeNull] ScoreInfo score) { Score = score; - this.allowRetry = allowRetry; - this.allowWatchingReplay = allowWatchingReplay; SelectedScore.Value = score; } @@ -162,7 +167,7 @@ namespace osu.Game.Screens.Ranking ScorePanelList.AddScore(Score, shouldFlair); } - if (allowWatchingReplay) + if (AllowWatchingReplay) { buttons.Add(new ReplayDownloadButton(SelectedScore.Value) { @@ -171,7 +176,7 @@ namespace osu.Game.Screens.Ranking }); } - if (player != null && allowRetry) + if (player != null && AllowRetry) { buttons.Add(new RetryButton { Width = 300 }); diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index 866440bbd6..38bc13ffb9 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -34,8 +34,8 @@ namespace osu.Game.Screens.Ranking private IBindable latestUpdate = null!; private readonly Bindable statisticsUpdate = new Bindable(); - public SoloResultsScreen(ScoreInfo score, bool allowRetry) - : base(score, allowRetry) + public SoloResultsScreen(ScoreInfo score) + : base(score) { } diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 7b7b8857f3..52f49ba56a 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Select } protected void PresentScore(ScoreInfo score) => - FinaliseSelection(score.BeatmapInfo, score.Ruleset, () => this.Push(new SoloResultsScreen(score, false))); + FinaliseSelection(score.BeatmapInfo, score.Ruleset, () => this.Push(new SoloResultsScreen(score))); protected override BeatmapDetailArea CreateBeatmapDetailArea() { From 1e53503608aa683a97e3f7f3ca1e9855929c9f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 19:49:14 +0100 Subject: [PATCH 560/915] Show user statistics after completing a playlists / multiplayer score --- .../Ranking/TestSceneStatisticsPanel.cs | 4 +- .../Multiplayer/MultiplayerPlayer.cs | 8 +++- .../OnlinePlay/Playlists/PlaylistsPlayer.cs | 1 + osu.Game/Screens/Ranking/ResultsScreen.cs | 16 ++++++- osu.Game/Screens/Ranking/SoloResultsScreen.cs | 43 ------------------- ...tisticsPanel.cs => UserStatisticsPanel.cs} | 26 +++++++++-- 6 files changed, 46 insertions(+), 52 deletions(-) rename osu.Game/Screens/Ranking/Statistics/{SoloStatisticsPanel.cs => UserStatisticsPanel.cs} (55%) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs index d0a45856b2..c7bd52ce8e 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs @@ -82,12 +82,12 @@ namespace osu.Game.Tests.Visual.Ranking private void loadPanel(ScoreInfo score) => AddStep("load panel", () => { - Child = new SoloStatisticsPanel(score) + Child = new UserStatisticsPanel(score) { RelativeSizeAxes = Axes.Both, State = { Value = Visibility.Visible }, Score = { Value = score }, - StatisticsUpdate = + DisplayedUserStatisticsUpdate = { Value = new SoloStatisticsUpdate(score, new UserStatistics { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index c5c536eae6..e560c5ca5d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -200,7 +200,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer return multiplayerLeaderboard.TeamScores.Count == 2 ? new MultiplayerTeamResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem, multiplayerLeaderboard.TeamScores) - : new MultiplayerResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem); + { + ShowUserStatistics = true, + } + : new MultiplayerResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem) + { + ShowUserStatistics = true + }; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs index 74454959a1..48f63731e1 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs @@ -61,6 +61,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists return new PlaylistsResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem) { AllowRetry = true, + ShowUserStatistics = true, }; } diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 6beb4d7401..b63c753721 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -73,6 +73,13 @@ namespace osu.Game.Screens.Ranking /// public bool AllowWatchingReplay { get; init; } = true; + /// + /// Whether the user's personal statistics should be shown on the extended statistics panel + /// after clicking the score panel associated with the being presented. + /// Requires to be present. + /// + public bool ShowUserStatistics { get; init; } + private Sample popInSample; protected ResultsScreen([CanBeNull] ScoreInfo score) @@ -105,7 +112,7 @@ namespace osu.Game.Screens.Ranking RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - StatisticsPanel = CreateStatisticsPanel().With(panel => + StatisticsPanel = createStatisticsPanel().With(panel => { panel.RelativeSizeAxes = Axes.Both; panel.Score.BindTarget = SelectedScore; @@ -243,7 +250,12 @@ namespace osu.Game.Screens.Ranking /// /// Creates the to be used to display extended information about scores. /// - protected virtual StatisticsPanel CreateStatisticsPanel() => new StatisticsPanel(); + private StatisticsPanel createStatisticsPanel() + { + return ShowUserStatistics && Score != null + ? new UserStatisticsPanel(Score) + : new StatisticsPanel(); + } private void fetchScoresCallback(IEnumerable scores) => Schedule(() => { diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index 38bc13ffb9..ee0251b5ac 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -6,70 +6,27 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Online.API.Requests; -using osu.Game.Online.Solo; using osu.Game.Rulesets; using osu.Game.Scoring; -using osu.Game.Screens.Ranking.Statistics; namespace osu.Game.Screens.Ranking { public partial class SoloResultsScreen : ResultsScreen { - /// - /// Whether the user's personal statistics should be shown on the extended statistics panel - /// after clicking the score panel associated with the being presented. - /// - public bool ShowUserStatistics { get; init; } - private GetScoresRequest? getScoreRequest; [Resolved] private RulesetStore rulesets { get; set; } = null!; - private IBindable latestUpdate = null!; - private readonly Bindable statisticsUpdate = new Bindable(); - public SoloResultsScreen(ScoreInfo score) : base(score) { } - [BackgroundDependencyLoader] - private void load(SoloStatisticsWatcher? soloStatisticsWatcher) - { - if (ShowUserStatistics && soloStatisticsWatcher != null) - { - Debug.Assert(Score != null); - - latestUpdate = soloStatisticsWatcher.LatestUpdate.GetBoundCopy(); - latestUpdate.BindValueChanged(update => - { - if (update.NewValue?.Score.MatchesOnlineID(Score) == true) - statisticsUpdate.Value = update.NewValue; - }); - } - } - - protected override StatisticsPanel CreateStatisticsPanel() - { - Debug.Assert(Score != null); - - if (ShowUserStatistics) - { - return new SoloStatisticsPanel(Score) - { - StatisticsUpdate = { BindTarget = statisticsUpdate } - }; - } - - return base.CreateStatisticsPanel(); - } - protected override APIRequest? FetchScores(Action>? scoresCallback) { Debug.Assert(Score != null); diff --git a/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs similarity index 55% rename from osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs rename to osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs index 762be61853..280e5ec90f 100644 --- a/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs @@ -3,25 +3,43 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Extensions; using osu.Game.Online.Solo; using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics.User; namespace osu.Game.Screens.Ranking.Statistics { - public partial class SoloStatisticsPanel : StatisticsPanel + public partial class UserStatisticsPanel : StatisticsPanel { private readonly ScoreInfo achievedScore; - public SoloStatisticsPanel(ScoreInfo achievedScore) + internal readonly Bindable DisplayedUserStatisticsUpdate = new Bindable(); + + private IBindable latestGlobalStatisticsUpdate = null!; + + public UserStatisticsPanel(ScoreInfo achievedScore) { this.achievedScore = achievedScore; } - public Bindable StatisticsUpdate { get; } = new Bindable(); + [BackgroundDependencyLoader] + private void load(SoloStatisticsWatcher? soloStatisticsWatcher) + { + if (soloStatisticsWatcher != null) + { + latestGlobalStatisticsUpdate = soloStatisticsWatcher.LatestUpdate.GetBoundCopy(); + latestGlobalStatisticsUpdate.BindValueChanged(update => + { + if (update.NewValue?.Score.MatchesOnlineID(achievedScore) == true) + DisplayedUserStatisticsUpdate.Value = update.NewValue; + }); + } + } protected override ICollection CreateStatisticItems(ScoreInfo newScore, IBeatmap playableBeatmap) { @@ -37,7 +55,7 @@ namespace osu.Game.Screens.Ranking.Statistics RelativeSizeAxes = Axes.X, Anchor = Anchor.Centre, Origin = Anchor.Centre, - StatisticsUpdate = { BindTarget = StatisticsUpdate } + StatisticsUpdate = { BindTarget = DisplayedUserStatisticsUpdate } })).ToArray(); } From eac4c5f69d6a201ced50c19fd826d8d618c9b7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Feb 2024 19:50:46 +0100 Subject: [PATCH 561/915] Rename `{Solo -> User}StatisticsWatcher` et al. The "solo" prefix is a bit unbecoming now. The updates are not only for solo. --- .../Menus/TestSceneToolbarUserButton.cs | 10 +++++----- .../Online/TestSceneSoloStatisticsWatcher.cs | 20 +++++++++---------- .../Visual/Ranking/TestSceneOverallRanking.cs | 2 +- .../Ranking/TestSceneStatisticsPanel.cs | 2 +- ...sticsUpdate.cs => UserStatisticsUpdate.cs} | 6 +++--- ...icsWatcher.cs => UserStatisticsWatcher.cs} | 8 ++++---- osu.Game/OsuGame.cs | 2 +- .../TransientUserStatisticsUpdateDisplay.cs | 6 +++--- osu.Game/Screens/Play/SubmittingPlayer.cs | 4 ++-- .../Ranking/Statistics/User/OverallRanking.cs | 4 ++-- .../Statistics/User/RankingChangeRow.cs | 4 ++-- .../Ranking/Statistics/UserStatisticsPanel.cs | 6 +++--- 12 files changed, 37 insertions(+), 37 deletions(-) rename osu.Game/Online/Solo/{SoloStatisticsUpdate.cs => UserStatisticsUpdate.cs} (88%) rename osu.Game/Online/Solo/{SoloStatisticsWatcher.cs => UserStatisticsWatcher.cs} (93%) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs index 69fedf4a3a..41ce739c2f 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs @@ -100,7 +100,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("Gain", () => { var transientUpdateDisplay = this.ChildrenOfType().Single(); - transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + transientUpdateDisplay.LatestUpdate.Value = new UserStatisticsUpdate( new ScoreInfo(), new UserStatistics { @@ -116,7 +116,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("Loss", () => { var transientUpdateDisplay = this.ChildrenOfType().Single(); - transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + transientUpdateDisplay.LatestUpdate.Value = new UserStatisticsUpdate( new ScoreInfo(), new UserStatistics { @@ -132,7 +132,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("No change", () => { var transientUpdateDisplay = this.ChildrenOfType().Single(); - transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + transientUpdateDisplay.LatestUpdate.Value = new UserStatisticsUpdate( new ScoreInfo(), new UserStatistics { @@ -148,7 +148,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("Was null", () => { var transientUpdateDisplay = this.ChildrenOfType().Single(); - transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + transientUpdateDisplay.LatestUpdate.Value = new UserStatisticsUpdate( new ScoreInfo(), new UserStatistics { @@ -164,7 +164,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("Became null", () => { var transientUpdateDisplay = this.ChildrenOfType().Single(); - transientUpdateDisplay.LatestUpdate.Value = new SoloStatisticsUpdate( + transientUpdateDisplay.LatestUpdate.Value = new UserStatisticsUpdate( new ScoreInfo(), new UserStatistics { diff --git a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs index 19121b7f58..733769b9f3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Online { protected override bool UseOnlineAPI => false; - private SoloStatisticsWatcher watcher = null!; + private UserStatisticsWatcher watcher = null!; [Resolved] private SpectatorClient spectatorClient { get; set; } = null!; @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("create watcher", () => { - Child = watcher = new SoloStatisticsWatcher(); + Child = watcher = new UserStatisticsWatcher(); }); } @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual.Online var ruleset = new OsuRuleset().RulesetInfo; - SoloStatisticsUpdate? update = null; + UserStatisticsUpdate? update = null; registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); feignScoreProcessing(userId, ruleset, 5_000_000); @@ -146,7 +146,7 @@ namespace osu.Game.Tests.Visual.Online // note ordering - in this test processing completes *before* the registration is added. feignScoreProcessing(userId, ruleset, 5_000_000); - SoloStatisticsUpdate? update = null; + UserStatisticsUpdate? update = null; registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, scoreId)); @@ -164,7 +164,7 @@ namespace osu.Game.Tests.Visual.Online long scoreId = getScoreId(); var ruleset = new OsuRuleset().RulesetInfo; - SoloStatisticsUpdate? update = null; + UserStatisticsUpdate? update = null; registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); feignScoreProcessing(userId, ruleset, 5_000_000); @@ -191,7 +191,7 @@ namespace osu.Game.Tests.Visual.Online long scoreId = getScoreId(); var ruleset = new OsuRuleset().RulesetInfo; - SoloStatisticsUpdate? update = null; + UserStatisticsUpdate? update = null; registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); feignScoreProcessing(userId, ruleset, 5_000_000); @@ -212,7 +212,7 @@ namespace osu.Game.Tests.Visual.Online long scoreId = getScoreId(); var ruleset = new OsuRuleset().RulesetInfo; - SoloStatisticsUpdate? update = null; + UserStatisticsUpdate? update = null; registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); feignScoreProcessing(userId, ruleset, 5_000_000); @@ -241,7 +241,7 @@ namespace osu.Game.Tests.Visual.Online feignScoreProcessing(userId, ruleset, 6_000_000); - SoloStatisticsUpdate? update = null; + UserStatisticsUpdate? update = null; registerForUpdates(secondScoreId, ruleset, receivedUpdate => update = receivedUpdate); AddStep("signal score processed", () => ((ISpectatorClient)spectatorClient).UserScoreProcessed(userId, secondScoreId)); @@ -259,7 +259,7 @@ namespace osu.Game.Tests.Visual.Online var ruleset = new OsuRuleset().RulesetInfo; - SoloStatisticsUpdate? update = null; + UserStatisticsUpdate? update = null; registerForUpdates(scoreId, ruleset, receivedUpdate => update = receivedUpdate); feignScoreProcessing(userId, ruleset, 5_000_000); @@ -289,7 +289,7 @@ namespace osu.Game.Tests.Visual.Online }); } - private void registerForUpdates(long scoreId, RulesetInfo rulesetInfo, Action onUpdateReady) => + private void registerForUpdates(long scoreId, RulesetInfo rulesetInfo, Action onUpdateReady) => AddStep("register for updates", () => { watcher.RegisterForStatisticsUpdateAfter( diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs b/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs index 355a572f95..ee0ab0c880 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs @@ -112,6 +112,6 @@ namespace osu.Game.Tests.Visual.Ranking }); private void displayUpdate(UserStatistics before, UserStatistics after) => - AddStep("display update", () => overallRanking.StatisticsUpdate.Value = new SoloStatisticsUpdate(new ScoreInfo(), before, after)); + AddStep("display update", () => overallRanking.StatisticsUpdate.Value = new UserStatisticsUpdate(new ScoreInfo(), before, after)); } } diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs index c7bd52ce8e..ecb8073a88 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs @@ -89,7 +89,7 @@ namespace osu.Game.Tests.Visual.Ranking Score = { Value = score }, DisplayedUserStatisticsUpdate = { - Value = new SoloStatisticsUpdate(score, new UserStatistics + Value = new UserStatisticsUpdate(score, new UserStatistics { Level = new UserStatistics.LevelInfo { diff --git a/osu.Game/Online/Solo/SoloStatisticsUpdate.cs b/osu.Game/Online/Solo/UserStatisticsUpdate.cs similarity index 88% rename from osu.Game/Online/Solo/SoloStatisticsUpdate.cs rename to osu.Game/Online/Solo/UserStatisticsUpdate.cs index cb9dac97c7..03f3abbb66 100644 --- a/osu.Game/Online/Solo/SoloStatisticsUpdate.cs +++ b/osu.Game/Online/Solo/UserStatisticsUpdate.cs @@ -9,7 +9,7 @@ namespace osu.Game.Online.Solo /// /// Contains data about the change in a user's profile statistics after completing a score. /// - public class SoloStatisticsUpdate + public class UserStatisticsUpdate { /// /// The score set by the user that triggered the update. @@ -27,12 +27,12 @@ namespace osu.Game.Online.Solo public UserStatistics After { get; } /// - /// Creates a new . + /// Creates a new . /// /// The score set by the user that triggered the update. /// The user's profile statistics prior to the score being set. /// The user's profile statistics after the score was set. - public SoloStatisticsUpdate(ScoreInfo score, UserStatistics before, UserStatistics after) + public UserStatisticsUpdate(ScoreInfo score, UserStatistics before, UserStatistics after) { Score = score; Before = before; diff --git a/osu.Game/Online/Solo/SoloStatisticsWatcher.cs b/osu.Game/Online/Solo/UserStatisticsWatcher.cs similarity index 93% rename from osu.Game/Online/Solo/SoloStatisticsWatcher.cs rename to osu.Game/Online/Solo/UserStatisticsWatcher.cs index 2072e8633f..2fff92fe0f 100644 --- a/osu.Game/Online/Solo/SoloStatisticsWatcher.cs +++ b/osu.Game/Online/Solo/UserStatisticsWatcher.cs @@ -20,10 +20,10 @@ namespace osu.Game.Online.Solo /// /// A persistent component that binds to the spectator server and API in order to deliver updates about the logged in user's gameplay statistics. /// - public partial class SoloStatisticsWatcher : Component + public partial class UserStatisticsWatcher : Component { - public IBindable LatestUpdate => latestUpdate; - private readonly Bindable latestUpdate = new Bindable(); + public IBindable LatestUpdate => latestUpdate; + private readonly Bindable latestUpdate = new Bindable(); [Resolved] private SpectatorClient spectatorClient { get; set; } = null!; @@ -120,7 +120,7 @@ namespace osu.Game.Online.Solo latestStatistics.TryGetValue(rulesetName, out UserStatistics? latestRulesetStatistics); latestRulesetStatistics ??= new UserStatistics(); - latestUpdate.Value = new SoloStatisticsUpdate(scoreInfo, latestRulesetStatistics, updatedStatistics); + latestUpdate.Value = new UserStatisticsUpdate(scoreInfo, latestRulesetStatistics, updatedStatistics); latestStatistics[rulesetName] = updatedStatistics; } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ec44076520..419e31bacd 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1022,7 +1022,7 @@ namespace osu.Game ScreenStack.Push(CreateLoader().With(l => l.RelativeSizeAxes = Axes.Both)); }); - loadComponentSingleFile(new SoloStatisticsWatcher(), Add, true); + loadComponentSingleFile(new UserStatisticsWatcher(), Add, true); loadComponentSingleFile(Toolbar = new Toolbar { OnHome = delegate diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index f56a1a3dd2..e7a78f8b80 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -21,13 +21,13 @@ namespace osu.Game.Overlays.Toolbar { public partial class TransientUserStatisticsUpdateDisplay : CompositeDrawable { - public Bindable LatestUpdate { get; } = new Bindable(); + public Bindable LatestUpdate { get; } = new Bindable(); private Statistic globalRank = null!; private Statistic pp = null!; [BackgroundDependencyLoader] - private void load(SoloStatisticsWatcher? soloStatisticsWatcher) + private void load(UserStatisticsWatcher? soloStatisticsWatcher) { RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Toolbar }; if (soloStatisticsWatcher != null) - ((IBindable)LatestUpdate).BindTo(soloStatisticsWatcher.LatestUpdate); + ((IBindable)LatestUpdate).BindTo(soloStatisticsWatcher.LatestUpdate); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index ecb507f382..ee88171789 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Play [Resolved(canBeNull: true)] [CanBeNull] - private SoloStatisticsWatcher soloStatisticsWatcher { get; set; } + private UserStatisticsWatcher userStatisticsWatcher { get; set; } private readonly object scoreSubmissionLock = new object(); private TaskCompletionSource scoreSubmissionSource; @@ -189,7 +189,7 @@ namespace osu.Game.Screens.Play await submitScore(score).ConfigureAwait(false); spectatorClient.EndPlaying(GameplayState); - soloStatisticsWatcher?.RegisterForStatisticsUpdateAfter(score.ScoreInfo); + userStatisticsWatcher?.RegisterForStatisticsUpdateAfter(score.ScoreInfo); } [Resolved] diff --git a/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs b/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs index d08a654e99..5c96a2b6c3 100644 --- a/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs +++ b/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Ranking.Statistics.User { private const float transition_duration = 300; - public Bindable StatisticsUpdate { get; } = new Bindable(); + public Bindable StatisticsUpdate { get; } = new Bindable(); private LoadingLayer loadingLayer = null!; private GridContainer content = null!; @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Ranking.Statistics.User FinishTransforms(true); } - private void onUpdateReceived(ValueChangedEvent update) + private void onUpdateReceived(ValueChangedEvent update) { if (update.NewValue == null) { diff --git a/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs index 906bf8d5ca..a477f38cd1 100644 --- a/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs +++ b/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Ranking.Statistics.User { public abstract partial class RankingChangeRow : CompositeDrawable { - public Bindable StatisticsUpdate { get; } = new Bindable(); + public Bindable StatisticsUpdate { get; } = new Bindable(); private readonly Func accessor; @@ -113,7 +113,7 @@ namespace osu.Game.Screens.Ranking.Statistics.User StatisticsUpdate.BindValueChanged(onStatisticsUpdate, true); } - private void onStatisticsUpdate(ValueChangedEvent statisticsUpdate) + private void onStatisticsUpdate(ValueChangedEvent statisticsUpdate) { var update = statisticsUpdate.NewValue; diff --git a/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs index 280e5ec90f..7f8c12ddab 100644 --- a/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs @@ -18,9 +18,9 @@ namespace osu.Game.Screens.Ranking.Statistics { private readonly ScoreInfo achievedScore; - internal readonly Bindable DisplayedUserStatisticsUpdate = new Bindable(); + internal readonly Bindable DisplayedUserStatisticsUpdate = new Bindable(); - private IBindable latestGlobalStatisticsUpdate = null!; + private IBindable latestGlobalStatisticsUpdate = null!; public UserStatisticsPanel(ScoreInfo achievedScore) { @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Ranking.Statistics } [BackgroundDependencyLoader] - private void load(SoloStatisticsWatcher? soloStatisticsWatcher) + private void load(UserStatisticsWatcher? soloStatisticsWatcher) { if (soloStatisticsWatcher != null) { From d6beae2ce1d34d0efb17eaf9ccc531a72a757ecf Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 22 Feb 2024 19:10:15 -0800 Subject: [PATCH 562/915] Update delete/restore mod presets message when none --- .../MaintenanceSettingsStrings.cs | 10 +++++++ .../Sections/Maintenance/ModPresetSettings.cs | 27 ++++++++++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/osu.Game/Localisation/MaintenanceSettingsStrings.cs b/osu.Game/Localisation/MaintenanceSettingsStrings.cs index 469f565f1e..2511e7aecc 100644 --- a/osu.Game/Localisation/MaintenanceSettingsStrings.cs +++ b/osu.Game/Localisation/MaintenanceSettingsStrings.cs @@ -109,11 +109,21 @@ namespace osu.Game.Localisation /// public static LocalisableString DeletedAllModPresets => new TranslatableString(getKey(@"deleted_all_mod_presets"), @"Deleted all mod presets!"); + /// + /// "No mod presets found to delete!" + /// + public static LocalisableString NoModPresetsFoundToDelete => new TranslatableString(getKey(@"no_mod_presets_found_to_delete"), @"No mod presets found to delete!"); + /// /// "Restored all deleted mod presets!" /// public static LocalisableString RestoredAllDeletedModPresets => new TranslatableString(getKey(@"restored_all_deleted_mod_presets"), @"Restored all deleted mod presets!"); + /// + /// "No mod presets found to restore!" + /// + public static LocalisableString NoModPresetsFoundToRestore => new TranslatableString(getKey(@"no_mod_presets_found_to_restore"), @"No mod presets found to restore!"); + /// /// "Please select your osu!stable install location" /// diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs index ba45d9c896..f0d6d10e51 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Logging; @@ -52,36 +53,50 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance }); } - private void deleteAllModPresets() => + private bool deleteAllModPresets() => realm.Write(r => { + bool anyDeleted = false; + foreach (var preset in r.All()) + { + anyDeleted |= !preset.DeletePending; preset.DeletePending = true; + } + + return anyDeleted; }); - private void onAllModPresetsDeleted(Task deletionTask) + private void onAllModPresetsDeleted(Task deletionTask) { deleteAllButton.Enabled.Value = true; if (deletionTask.IsCompletedSuccessfully) - notificationOverlay?.Post(new ProgressCompletionNotification { Text = MaintenanceSettingsStrings.DeletedAllModPresets }); + notificationOverlay?.Post(new ProgressCompletionNotification { Text = deletionTask.GetResultSafely() ? MaintenanceSettingsStrings.DeletedAllModPresets : MaintenanceSettingsStrings.NoModPresetsFoundToDelete }); else if (deletionTask.IsFaulted) Logger.Error(deletionTask.Exception, "Failed to delete all mod presets"); } - private void undeleteModPresets() => + private bool undeleteModPresets() => realm.Write(r => { + bool anyRestored = false; + foreach (var preset in r.All().Where(preset => preset.DeletePending)) + { + anyRestored |= preset.DeletePending; preset.DeletePending = false; + } + + return anyRestored; }); - private void onModPresetsUndeleted(Task undeletionTask) + private void onModPresetsUndeleted(Task undeletionTask) { undeleteButton.Enabled.Value = true; if (undeletionTask.IsCompletedSuccessfully) - notificationOverlay?.Post(new ProgressCompletionNotification { Text = MaintenanceSettingsStrings.RestoredAllDeletedModPresets }); + notificationOverlay?.Post(new ProgressCompletionNotification { Text = undeletionTask.GetResultSafely() ? MaintenanceSettingsStrings.RestoredAllDeletedModPresets : MaintenanceSettingsStrings.NoModPresetsFoundToRestore }); else if (undeletionTask.IsFaulted) Logger.Error(undeletionTask.Exception, "Failed to restore mod presets"); } From 6c8204f9a35cfcc11b4a6fc9003b50dd30e37960 Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 22 Feb 2024 19:40:02 -0800 Subject: [PATCH 563/915] Update delete collections message when none --- .../Localisation/MaintenanceSettingsStrings.cs | 5 +++++ .../Sections/Maintenance/CollectionsSettings.cs | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/MaintenanceSettingsStrings.cs b/osu.Game/Localisation/MaintenanceSettingsStrings.cs index 2511e7aecc..2e5f1d29df 100644 --- a/osu.Game/Localisation/MaintenanceSettingsStrings.cs +++ b/osu.Game/Localisation/MaintenanceSettingsStrings.cs @@ -104,6 +104,11 @@ namespace osu.Game.Localisation /// public static LocalisableString DeletedAllCollections => new TranslatableString(getKey(@"deleted_all_collections"), @"Deleted all collections!"); + /// + /// "No collections found to delete!" + /// + public static LocalisableString NoCollectionsFoundToDelete => new TranslatableString(getKey(@"no_collections_found_to_delete"), @"No collections found to delete!"); + /// /// "Deleted all mod presets!" /// diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs index 09acc22c25..b373535a8b 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.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.Linq; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Game.Collections; @@ -35,8 +36,20 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance private void deleteAllCollections() { - realm.Write(r => r.RemoveAll()); - notificationOverlay?.Post(new ProgressCompletionNotification { Text = MaintenanceSettingsStrings.DeletedAllCollections }); + bool anyDeleted = realm.Write(r => + { + if (r.All().Any()) + { + r.RemoveAll(); + return true; + } + else + { + return false; + } + }); + + notificationOverlay?.Post(new ProgressCompletionNotification { Text = anyDeleted ? MaintenanceSettingsStrings.DeletedAllCollections : MaintenanceSettingsStrings.NoCollectionsFoundToDelete }); } } } From 157819c19931b581abf36cbcf3538f70637d970c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Feb 2024 11:23:11 +0800 Subject: [PATCH 564/915] Materialise realm collection hashes during song select search process Without this, there's a large overhead to do a realm-live `Contains` search when a collection is selected. This may also help considerably alleviate https://github.com/ppy/osu/discussions/27298#discussioncomment-8552508 as we will be performing the native realm search much less. --- osu.Game/Screens/Select/FilterControl.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 1827eb58ca..6fd22364f6 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -64,7 +65,7 @@ namespace osu.Game.Screens.Select Sort = sortMode.Value, AllowConvertedBeatmaps = showConverted.Value, Ruleset = ruleset.Value, - CollectionBeatmapMD5Hashes = collectionDropdown.Current.Value?.Collection?.PerformRead(c => c.BeatmapMD5Hashes) + CollectionBeatmapMD5Hashes = collectionDropdown.Current.Value?.Collection?.PerformRead(c => c.BeatmapMD5Hashes).ToList() }; if (!minimumStars.IsDefault) From d1d32fc16cf6474ec8661c83dbd6bd282cff172b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 23 Feb 2024 14:49:46 +0100 Subject: [PATCH 565/915] Fix editor displaying combo colours in effectively incorrect order Addresses https://github.com/ppy/osu/discussions/27316. Stable lies about the first combo colour being first; in the `.osu` file it is actually second. It does a thing in editor itself to correct for this. https://github.com/peppy/osu-stable-reference/blob/master/osu!/GameModes/Edit/Forms/SongSetup.cs#L233-L234 --- osu.Game/Screens/Edit/EditorBeatmapSkin.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs index 80239504d8..71530ee5bc 100644 --- a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs +++ b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs @@ -4,7 +4,7 @@ #nullable disable using System; -using System.Linq; +using System.Collections.Generic; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -38,8 +38,17 @@ namespace osu.Game.Screens.Edit Skin = skin; ComboColours = new BindableList(); - if (Skin.Configuration.ComboColours != null) - ComboColours.AddRange(Skin.Configuration.ComboColours.Select(c => (Colour4)c)); + + if (Skin.Configuration.ComboColours is IReadOnlyList comboColours) + { + // due to the foibles of how `IHasComboInformation` / `ComboIndexWithOffsets` work, + // the actual effective first combo colour that will be used on the beatmap is the one with index 1, not 0. + // see also: `IHasComboInformation.UpdateComboInformation`, + // https://github.com/peppy/osu-stable-reference/blob/46cd3a10af7cc6cc96f4eba92ef1812dc8c3a27e/osu!/GameModes/Edit/Forms/SongSetup.cs#L233-L234. + for (int i = 0; i < comboColours.Count; ++i) + ComboColours.Add(comboColours[(i + 1) % comboColours.Count]); + } + ComboColours.BindCollectionChanged((_, _) => updateColours()); } @@ -47,7 +56,10 @@ namespace osu.Game.Screens.Edit private void updateColours() { - Skin.Configuration.CustomComboColours = ComboColours.Select(c => (Color4)c).ToList(); + // performs the inverse of the index rotation operation described in the ctor. + Skin.Configuration.CustomComboColours.Clear(); + for (int i = 0; i < ComboColours.Count; ++i) + Skin.Configuration.CustomComboColours.Add(ComboColours[(ComboColours.Count + i - 1) % ComboColours.Count]); invokeSkinChanged(); } From ae9c58be3030cb5c0b3c0148446afbf8edf452ac Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 16:42:58 +0300 Subject: [PATCH 566/915] Remove "multiplayer" references from subclass and move to appropriate place --- .../OnlinePlay/Match/RoomModSelectOverlay.cs} | 24 ++++++++++--------- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) rename osu.Game/{Overlays/Mods/MultiplayerModSelectOverlay.cs => Screens/OnlinePlay/Match/RoomModSelectOverlay.cs} (72%) diff --git a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs similarity index 72% rename from osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs rename to osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs index ee087bb149..00704b7ec7 100644 --- a/osu.Game/Overlays/Mods/MultiplayerModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// 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; @@ -6,26 +6,28 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Rulesets; using osu.Game.Online.Rooms; +using osu.Game.Overlays; +using osu.Game.Overlays.Mods; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; -namespace osu.Game.Overlays.Mods +namespace osu.Game.Screens.OnlinePlay.Match { - public partial class MultiplayerModSelectOverlay : UserModSelectOverlay + public partial class RoomModSelectOverlay : UserModSelectOverlay { - public MultiplayerModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Plum) + public RoomModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Plum) : base(colourScheme) { } [Resolved(CanBeNull = true)] - private IBindable? multiplayerRoomItem { get; set; } + private IBindable? selectedItem { get; set; } [Resolved] private OsuGameBase game { get; set; } = null!; - protected override BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new MultiplayerBeatmapAttributesDisplay + protected override BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new RoomBeatmapAttributesDisplay { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, @@ -35,7 +37,7 @@ namespace osu.Game.Overlays.Mods protected override void LoadComplete() { base.LoadComplete(); - multiplayerRoomItem?.BindValueChanged(_ => SelectedMods.TriggerChange()); + selectedItem?.BindValueChanged(_ => SelectedMods.TriggerChange()); } protected override IEnumerable AllSelectedMods @@ -44,10 +46,10 @@ namespace osu.Game.Overlays.Mods { IEnumerable allMods = SelectedMods.Value; - if (multiplayerRoomItem?.Value != null) + if (selectedItem?.Value != null) { Ruleset ruleset = game.Ruleset.Value.CreateInstance(); - var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); + var multiplayerRoomMods = selectedItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); allMods = allMods.Concat(multiplayerRoomMods); } @@ -56,7 +58,7 @@ namespace osu.Game.Overlays.Mods } } - public partial class MultiplayerBeatmapAttributesDisplay : BeatmapAttributesDisplay + public partial class RoomBeatmapAttributesDisplay : BeatmapAttributesDisplay { [Resolved(CanBeNull = true)] private IBindable? multiplayerRoomItem { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index b20760b114..97fbb83992 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -241,7 +241,7 @@ namespace osu.Game.Screens.OnlinePlay.Match } }; - LoadComponent(UserModsSelectOverlay = new MultiplayerModSelectOverlay + LoadComponent(UserModsSelectOverlay = new RoomModSelectOverlay { SelectedMods = { BindTarget = UserMods }, IsValidMod = _ => false From f94cd4483cb4f4b0a4b8cd189975ccca92f54720 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 16:47:37 +0300 Subject: [PATCH 567/915] Avoid relying on game-wide ruleset bindable --- .../OnlinePlay/Match/RoomModSelectOverlay.cs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs index 00704b7ec7..e6ff2260e9 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -25,7 +26,7 @@ namespace osu.Game.Screens.OnlinePlay.Match private IBindable? selectedItem { get; set; } [Resolved] - private OsuGameBase game { get; set; } = null!; + private RulesetStore rulesets { get; set; } = null!; protected override BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new RoomBeatmapAttributesDisplay { @@ -48,9 +49,9 @@ namespace osu.Game.Screens.OnlinePlay.Match if (selectedItem?.Value != null) { - Ruleset ruleset = game.Ruleset.Value.CreateInstance(); - var multiplayerRoomMods = selectedItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - allMods = allMods.Concat(multiplayerRoomMods); + var rulesetInstance = rulesets.GetRuleset(selectedItem.Value.RulesetID)?.CreateInstance(); + Debug.Assert(rulesetInstance != null); + allMods = allMods.Concat(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); } return allMods; @@ -61,12 +62,15 @@ namespace osu.Game.Screens.OnlinePlay.Match public partial class RoomBeatmapAttributesDisplay : BeatmapAttributesDisplay { [Resolved(CanBeNull = true)] - private IBindable? multiplayerRoomItem { get; set; } + private IBindable? selectedItem { get; set; } + + [Resolved] + private RulesetStore rulesets { get; set; } = null!; protected override void LoadComplete() { base.LoadComplete(); - multiplayerRoomItem?.BindValueChanged(_ => Mods.TriggerChange()); + selectedItem?.BindValueChanged(_ => Mods.TriggerChange()); } protected override IEnumerable SelectedMods @@ -75,11 +79,11 @@ namespace osu.Game.Screens.OnlinePlay.Match { IEnumerable selectedMods = Mods.Value; - if (multiplayerRoomItem?.Value != null) + if (selectedItem?.Value != null) { - Ruleset ruleset = GameRuleset.Value.CreateInstance(); - var multiplayerRoomMods = multiplayerRoomItem.Value.RequiredMods.Select(m => m.ToMod(ruleset)); - selectedMods = selectedMods.Concat(multiplayerRoomMods); + var rulesetInstance = rulesets.GetRuleset(selectedItem.Value.RulesetID)?.CreateInstance(); + Debug.Assert(rulesetInstance != null); + selectedMods = selectedMods.Concat(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); } return selectedMods; From f86b7f0702790bd21522f86501ca9a19e771d018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 23 Feb 2024 14:52:44 +0100 Subject: [PATCH 568/915] Enable NRT in `EditorBeatmapSkin` --- osu.Game/Screens/Edit/EditorBeatmapSkin.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs index 71530ee5bc..07fa1cb49c 100644 --- a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs +++ b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using osu.Framework.Audio.Sample; @@ -20,7 +18,7 @@ namespace osu.Game.Screens.Edit /// public class EditorBeatmapSkin : ISkin { - public event Action BeatmapSkinChanged; + public event Action? BeatmapSkinChanged; /// /// The underlying beatmap skin. @@ -65,10 +63,14 @@ namespace osu.Game.Screens.Edit #region Delegated ISkin implementation - public Drawable GetDrawableComponent(ISkinComponentLookup lookup) => Skin.GetDrawableComponent(lookup); - public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => Skin.GetTexture(componentName, wrapModeS, wrapModeT); - public ISample GetSample(ISampleInfo sampleInfo) => Skin.GetSample(sampleInfo); - public IBindable GetConfig(TLookup lookup) => Skin.GetConfig(lookup); + public Drawable? GetDrawableComponent(ISkinComponentLookup lookup) => Skin.GetDrawableComponent(lookup); + public Texture? GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => Skin.GetTexture(componentName, wrapModeS, wrapModeT); + public ISample? GetSample(ISampleInfo sampleInfo) => Skin.GetSample(sampleInfo); + + public IBindable? GetConfig(TLookup lookup) + where TLookup : notnull + where TValue : notnull + => Skin.GetConfig(lookup); #endregion } From 918577d530c0fa27fc58f2677a731df23b20d230 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 16:51:52 +0300 Subject: [PATCH 569/915] Compute required mods list once per update --- .../OnlinePlay/Match/RoomModSelectOverlay.cs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs index e6ff2260e9..5406912f49 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs @@ -35,28 +35,28 @@ namespace osu.Game.Screens.OnlinePlay.Match BeatmapInfo = { Value = Beatmap?.BeatmapInfo } }; + private readonly List roomMods = new List(); + protected override void LoadComplete() { base.LoadComplete(); - selectedItem?.BindValueChanged(_ => SelectedMods.TriggerChange()); - } - protected override IEnumerable AllSelectedMods - { - get + selectedItem?.BindValueChanged(_ => { - IEnumerable allMods = SelectedMods.Value; + roomMods.Clear(); if (selectedItem?.Value != null) { var rulesetInstance = rulesets.GetRuleset(selectedItem.Value.RulesetID)?.CreateInstance(); Debug.Assert(rulesetInstance != null); - allMods = allMods.Concat(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); + roomMods.AddRange(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); } - return allMods; - } + SelectedMods.TriggerChange(); + }); } + + protected override IEnumerable AllSelectedMods => roomMods.Concat(base.AllSelectedMods); } public partial class RoomBeatmapAttributesDisplay : BeatmapAttributesDisplay @@ -67,27 +67,27 @@ namespace osu.Game.Screens.OnlinePlay.Match [Resolved] private RulesetStore rulesets { get; set; } = null!; + private readonly List roomMods = new List(); + protected override void LoadComplete() { base.LoadComplete(); - selectedItem?.BindValueChanged(_ => Mods.TriggerChange()); - } - protected override IEnumerable SelectedMods - { - get + selectedItem?.BindValueChanged(_ => { - IEnumerable selectedMods = Mods.Value; + roomMods.Clear(); if (selectedItem?.Value != null) { var rulesetInstance = rulesets.GetRuleset(selectedItem.Value.RulesetID)?.CreateInstance(); Debug.Assert(rulesetInstance != null); - selectedMods = selectedMods.Concat(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); + roomMods.AddRange(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); } - return selectedMods; - } + Mods.TriggerChange(); + }); } + + protected override IEnumerable SelectedMods => roomMods.Concat(base.SelectedMods); } } From 323d7f8e2dabbd090c29b51926338cece1a94f64 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 16:59:08 +0300 Subject: [PATCH 570/915] Change `BeatmapAttributesDisplay` retrieval to proper method --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 16 +++--- .../OnlinePlay/Match/RoomModSelectOverlay.cs | 56 +++++++++---------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 8a3b1954ed..99981c28d5 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -130,13 +130,6 @@ namespace osu.Game.Overlays.Mods private RankingInformationDisplay? rankingInformationDisplay; private BeatmapAttributesDisplay? beatmapAttributesDisplay; - protected virtual BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new BeatmapAttributesDisplay - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - BeatmapInfo = { Value = Beatmap?.BeatmapInfo } - }; - protected ShearedButton BackButton { get; private set; } = null!; protected ShearedToggleButton? CustomisationButton { get; private set; } protected SelectAllModsButton? SelectAllModsButton { get; set; } @@ -283,7 +276,12 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight }, - beatmapAttributesDisplay = GetBeatmapAttributesDisplay + beatmapAttributesDisplay = CreateBeatmapAttributesDisplay().With(b => + { + b.Anchor = Anchor.BottomRight; + b.Origin = Anchor.BottomRight; + b.BeatmapInfo.Value = Beatmap?.BeatmapInfo; + }), } }); } @@ -293,6 +291,8 @@ namespace osu.Game.Overlays.Mods textSearchStartsActive = configManager.GetBindable(OsuSetting.ModSelectTextSearchStartsActive); } + protected virtual BeatmapAttributesDisplay CreateBeatmapAttributesDisplay() => new BeatmapAttributesDisplay(); + public override void Hide() { base.Hide(); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs index 5406912f49..4bf8e22d4e 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Overlays.Mods; @@ -28,13 +27,6 @@ namespace osu.Game.Screens.OnlinePlay.Match [Resolved] private RulesetStore rulesets { get; set; } = null!; - protected override BeatmapAttributesDisplay GetBeatmapAttributesDisplay => new RoomBeatmapAttributesDisplay - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - BeatmapInfo = { Value = Beatmap?.BeatmapInfo } - }; - private readonly List roomMods = new List(); protected override void LoadComplete() @@ -57,37 +49,39 @@ namespace osu.Game.Screens.OnlinePlay.Match } protected override IEnumerable AllSelectedMods => roomMods.Concat(base.AllSelectedMods); - } - public partial class RoomBeatmapAttributesDisplay : BeatmapAttributesDisplay - { - [Resolved(CanBeNull = true)] - private IBindable? selectedItem { get; set; } + protected override BeatmapAttributesDisplay CreateBeatmapAttributesDisplay() => new RoomBeatmapAttributesDisplay(); - [Resolved] - private RulesetStore rulesets { get; set; } = null!; - - private readonly List roomMods = new List(); - - protected override void LoadComplete() + private partial class RoomBeatmapAttributesDisplay : BeatmapAttributesDisplay { - base.LoadComplete(); + [Resolved(CanBeNull = true)] + private IBindable? selectedItem { get; set; } - selectedItem?.BindValueChanged(_ => + [Resolved] + private RulesetStore rulesets { get; set; } = null!; + + private readonly List roomMods = new List(); + + protected override void LoadComplete() { - roomMods.Clear(); + base.LoadComplete(); - if (selectedItem?.Value != null) + selectedItem?.BindValueChanged(_ => { - var rulesetInstance = rulesets.GetRuleset(selectedItem.Value.RulesetID)?.CreateInstance(); - Debug.Assert(rulesetInstance != null); - roomMods.AddRange(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); - } + roomMods.Clear(); - Mods.TriggerChange(); - }); + if (selectedItem?.Value != null) + { + var rulesetInstance = rulesets.GetRuleset(selectedItem.Value.RulesetID)?.CreateInstance(); + Debug.Assert(rulesetInstance != null); + roomMods.AddRange(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); + } + + Mods.TriggerChange(); + }); + } + + protected override IEnumerable SelectedMods => roomMods.Concat(base.SelectedMods); } - - protected override IEnumerable SelectedMods => roomMods.Concat(base.SelectedMods); } } From 9ce07a96b2f98358050eacb4d72767fc1dede2cc Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 17:28:54 +0300 Subject: [PATCH 571/915] Rewrite mods flow and remove `RoomBeatmapAttributesDisplay` --- .../Overlays/Mods/BeatmapAttributesDisplay.cs | 26 ++++--------- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 34 +++++++++++------ .../OnlinePlay/Match/RoomModSelectOverlay.cs | 37 +------------------ 3 files changed, 31 insertions(+), 66 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 7c3c971d76..8f84b51127 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -13,7 +13,6 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; -using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -39,15 +38,10 @@ namespace osu.Game.Overlays.Mods public Bindable BeatmapInfo { get; } = new Bindable(); - [Resolved] - protected Bindable> Mods { get; private set; } = null!; - - protected virtual IEnumerable SelectedMods => Mods.Value; + public Bindable> Mods { get; } = new Bindable>(); public BindableBool Collapsed { get; } = new BindableBool(true); - private ModSettingChangeTracker? modSettingChangeTracker; - [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } = null!; @@ -102,15 +96,8 @@ namespace osu.Game.Overlays.Mods { base.LoadComplete(); - Mods.BindValueChanged(_ => - { - modSettingChangeTracker?.Dispose(); - modSettingChangeTracker = new ModSettingChangeTracker(Mods.Value); - modSettingChangeTracker.SettingChanged += _ => updateValues(); - updateValues(); - }, true); - - BeatmapInfo.BindValueChanged(_ => updateValues(), true); + Mods.BindValueChanged(_ => updateValues()); + BeatmapInfo.BindValueChanged(_ => updateValues()); Collapsed.BindValueChanged(_ => { @@ -122,8 +109,9 @@ namespace osu.Game.Overlays.Mods GameRuleset = game.Ruleset.GetBoundCopy(); GameRuleset.BindValueChanged(_ => updateValues()); - BeatmapInfo.BindValueChanged(_ => updateValues(), true); + BeatmapInfo.BindValueChanged(_ => updateValues()); + updateValues(); updateCollapsedState(); } @@ -167,14 +155,14 @@ namespace osu.Game.Overlays.Mods }); double rate = 1; - foreach (var mod in SelectedMods.OfType()) + foreach (var mod in Mods.Value.OfType()) rate = mod.ApplyToRate(0, rate); bpmDisplay.Current.Value = BeatmapInfo.Value.BPM * rate; BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(BeatmapInfo.Value.Difficulty); - foreach (var mod in SelectedMods.OfType()) + foreach (var mod in Mods.Value.OfType()) mod.ApplyToDifficulty(originalDifficulty); Ruleset ruleset = GameRuleset.Value.CreateInstance(); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 99981c28d5..fa87b0aa0d 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -114,8 +114,6 @@ namespace osu.Game.Overlays.Mods public IEnumerable AllAvailableMods => AvailableMods.Value.SelectMany(pair => pair.Value); - protected virtual IEnumerable AllSelectedMods => SelectedMods.Value; - private readonly BindableBool customisationVisible = new BindableBool(); private Bindable textSearchStartsActive = null!; @@ -319,7 +317,7 @@ namespace osu.Game.Overlays.Mods SelectedMods.BindValueChanged(_ => { - updateRankingInformation(); + UpdateOverlayInformation(SelectedMods.Value); updateFromExternalSelection(); updateCustomisation(); @@ -332,7 +330,7 @@ namespace osu.Game.Overlays.Mods // // See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988 modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); - modSettingChangeTracker.SettingChanged += _ => updateRankingInformation(); + modSettingChangeTracker.SettingChanged += _ => UpdateOverlayInformation(SelectedMods.Value); } }, true); @@ -454,18 +452,30 @@ namespace osu.Game.Overlays.Mods modState.ValidForSelection.Value = modState.Mod.Type != ModType.System && modState.Mod.HasImplementation && IsValidMod.Invoke(modState.Mod); } - private void updateRankingInformation() + /// + /// Updates any information displayed on the overlay regarding the effects of the selected mods. + /// + /// The list of mods to show effect from. This can be overriden to include effect of mods that are not part of the bindable (e.g. room mods in multiplayer/playlists). + protected virtual void UpdateOverlayInformation(IReadOnlyList mods) { - if (rankingInformationDisplay == null) - return; + if (rankingInformationDisplay != null) + { + double multiplier = 1.0; - double multiplier = 1.0; + foreach (var mod in mods) + multiplier *= mod.ScoreMultiplier; - foreach (var mod in AllSelectedMods) - multiplier *= mod.ScoreMultiplier; + rankingInformationDisplay.ModMultiplier.Value = multiplier; + rankingInformationDisplay.Ranked.Value = mods.All(m => m.Ranked); + } - rankingInformationDisplay.ModMultiplier.Value = multiplier; - rankingInformationDisplay.Ranked.Value = AllSelectedMods.All(m => m.Ranked); + if (beatmapAttributesDisplay != null) + { + if (!ReferenceEquals(beatmapAttributesDisplay.Mods.Value, mods)) + beatmapAttributesDisplay.Mods.Value = mods; + else + beatmapAttributesDisplay.Mods.TriggerChange(); // mods list may be same but a mod setting has changed, trigger change in that case. + } } private void updateCustomisation() diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs index 4bf8e22d4e..dd0ecbad90 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs @@ -48,40 +48,7 @@ namespace osu.Game.Screens.OnlinePlay.Match }); } - protected override IEnumerable AllSelectedMods => roomMods.Concat(base.AllSelectedMods); - - protected override BeatmapAttributesDisplay CreateBeatmapAttributesDisplay() => new RoomBeatmapAttributesDisplay(); - - private partial class RoomBeatmapAttributesDisplay : BeatmapAttributesDisplay - { - [Resolved(CanBeNull = true)] - private IBindable? selectedItem { get; set; } - - [Resolved] - private RulesetStore rulesets { get; set; } = null!; - - private readonly List roomMods = new List(); - - protected override void LoadComplete() - { - base.LoadComplete(); - - selectedItem?.BindValueChanged(_ => - { - roomMods.Clear(); - - if (selectedItem?.Value != null) - { - var rulesetInstance = rulesets.GetRuleset(selectedItem.Value.RulesetID)?.CreateInstance(); - Debug.Assert(rulesetInstance != null); - roomMods.AddRange(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); - } - - Mods.TriggerChange(); - }); - } - - protected override IEnumerable SelectedMods => roomMods.Concat(base.SelectedMods); - } + protected override void UpdateOverlayInformation(IReadOnlyList mods) + => base.UpdateOverlayInformation(roomMods.Concat(mods).ToList()); } } From fdc0636554ca83daf3762c229feee047f34966b5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 17:30:31 +0300 Subject: [PATCH 572/915] General code cleanup --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 12 +++++----- .../OnlinePlay/Match/RoomModSelectOverlay.cs | 22 +++++++++---------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index fa87b0aa0d..bf43dc3d9c 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -274,12 +274,12 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight }, - beatmapAttributesDisplay = CreateBeatmapAttributesDisplay().With(b => + beatmapAttributesDisplay = new BeatmapAttributesDisplay { - b.Anchor = Anchor.BottomRight; - b.Origin = Anchor.BottomRight; - b.BeatmapInfo.Value = Beatmap?.BeatmapInfo; - }), + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + BeatmapInfo = { Value = Beatmap?.BeatmapInfo }, + }, } }); } @@ -289,8 +289,6 @@ namespace osu.Game.Overlays.Mods textSearchStartsActive = configManager.GetBindable(OsuSetting.ModSelectTextSearchStartsActive); } - protected virtual BeatmapAttributesDisplay CreateBeatmapAttributesDisplay() => new BeatmapAttributesDisplay(); - public override void Hide() { base.Hide(); diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs index dd0ecbad90..db7cfe980c 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs @@ -16,32 +16,32 @@ namespace osu.Game.Screens.OnlinePlay.Match { public partial class RoomModSelectOverlay : UserModSelectOverlay { - public RoomModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Plum) - : base(colourScheme) - { - } - - [Resolved(CanBeNull = true)] - private IBindable? selectedItem { get; set; } + [Resolved] + private IBindable selectedItem { get; set; } = null!; [Resolved] private RulesetStore rulesets { get; set; } = null!; private readonly List roomMods = new List(); + public RoomModSelectOverlay() + : base(OverlayColourScheme.Plum) + { + } + protected override void LoadComplete() { base.LoadComplete(); - selectedItem?.BindValueChanged(_ => + selectedItem.BindValueChanged(_ => { roomMods.Clear(); - if (selectedItem?.Value != null) + if (selectedItem.Value is PlaylistItem item) { - var rulesetInstance = rulesets.GetRuleset(selectedItem.Value.RulesetID)?.CreateInstance(); + var rulesetInstance = rulesets.GetRuleset(item.RulesetID)?.CreateInstance(); Debug.Assert(rulesetInstance != null); - roomMods.AddRange(selectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))); + roomMods.AddRange(item.RequiredMods.Select(m => m.ToMod(rulesetInstance))); } SelectedMods.TriggerChange(); From 869f0a82de4272806eda4350944c7fd989f52e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 23 Feb 2024 15:38:52 +0100 Subject: [PATCH 573/915] Use hashset for faster lookup --- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 6fd22364f6..17297c9ebf 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -4,7 +4,7 @@ #nullable disable using System; -using System.Linq; +using System.Collections.Immutable; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Select Sort = sortMode.Value, AllowConvertedBeatmaps = showConverted.Value, Ruleset = ruleset.Value, - CollectionBeatmapMD5Hashes = collectionDropdown.Current.Value?.Collection?.PerformRead(c => c.BeatmapMD5Hashes).ToList() + CollectionBeatmapMD5Hashes = collectionDropdown.Current.Value?.Collection?.PerformRead(c => c.BeatmapMD5Hashes).ToImmutableHashSet() }; if (!minimumStars.IsDefault) From c1db9d7819496e52db88223134d642d6cba6f0d3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 18:16:35 +0300 Subject: [PATCH 574/915] Add test coverage --- .../TestSceneMultiplayerMatchSubScreen.cs | 30 +++++++++++++++++++ .../Overlays/Mods/BeatmapAttributesDisplay.cs | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index a41eff067b..4bedc31f38 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -286,6 +286,36 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } + [Test] + [FlakyTest] // See above + public void TestModSelectOverlay() + { + AddStep("add playlist item", () => + { + SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo) + { + RulesetID = new OsuRuleset().RulesetInfo.OnlineID, + RequiredMods = new[] + { + new APIMod(new OsuModDoubleTime { SpeedChange = { Value = 2.0 } }), + new APIMod(new OsuModStrictTracking()), + }, + AllowedMods = new[] + { + new APIMod(new OsuModFlashlight()), + new APIMod(new OsuModHardRock()), + } + }); + }); + ClickButtonWhenEnabled(); + + AddUntilStep("wait for join", () => RoomJoined); + + ClickButtonWhenEnabled(); + AddAssert("mod select shows unranked", () => this.ChildrenOfType().Single().Ranked.Value == false); + AddAssert("mod select shows different multiplier", () => !this.ChildrenOfType().Single().ModMultiplier.IsDefault); + } + private partial class TestMultiplayerMatchSubScreen : MultiplayerMatchSubScreen { [Resolved(canBeNull: true)] diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 8f84b51127..472fe6f476 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -184,7 +184,7 @@ namespace osu.Game.Overlays.Mods RightContent.FadeTo(Collapsed.Value && !IsHovered ? 0 : 1, transition_duration, Easing.OutQuint); } - private partial class BPMDisplay : RollingCounter + public partial class BPMDisplay : RollingCounter { protected override double RollingDuration => 250; From 31dabaefaa95dfb04cebe69a25b3965ae549201d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 23 Feb 2024 18:21:11 +0300 Subject: [PATCH 575/915] Reduce smoke allocations --- osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs b/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs index 9838cb2c37..f4fe42b8de 100644 --- a/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs +++ b/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -228,7 +227,9 @@ namespace osu.Game.Rulesets.Osu.Skinning int futurePointIndex = ~Source.SmokePoints.BinarySearch(new SmokePoint { Time = CurrentTime }, new SmokePoint.UpperBoundComparer()); points.Clear(); - points.AddRange(Source.SmokePoints.Skip(firstVisiblePointIndex).Take(futurePointIndex - firstVisiblePointIndex)); + + for (int i = firstVisiblePointIndex; i < futurePointIndex; i++) + points.Add(Source.SmokePoints[i]); } protected sealed override void Draw(IRenderer renderer) From 771cdf9cd6eb12de88691ec9cddfecd52e586c88 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 18:30:14 +0300 Subject: [PATCH 576/915] Fix `TestSceneModEffectPreviewPanel` --- .../Visual/UserInterface/TestSceneModEffectPreviewPanel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModEffectPreviewPanel.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModEffectPreviewPanel.cs index b3ad5a499e..cdb6900f06 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModEffectPreviewPanel.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModEffectPreviewPanel.cs @@ -57,6 +57,7 @@ namespace osu.Game.Tests.Visual.UserInterface { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Mods = { BindTarget = SelectedMods }, }); AddStep("set beatmap", () => From d4bc3090e7fd680f0f3452a1e242fa29b09f0178 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Feb 2024 18:42:07 +0300 Subject: [PATCH 577/915] Fix incorrect conflict resolution --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 3432529976..7035af1594 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -185,7 +185,7 @@ namespace osu.Game.Overlays.Mods RightContent.FadeTo(Collapsed.Value && !IsHovered ? 0 : 1, transition_duration, Easing.OutQuint); } - public partial class BPMDisplay : RollingCounter + public partial class BPMDisplay : RollingCounter { protected override double RollingDuration => 250; From 8934cf33f069d211511097861696c8af3019bb3d Mon Sep 17 00:00:00 2001 From: jvyden Date: Fri, 23 Feb 2024 22:07:47 -0500 Subject: [PATCH 578/915] Apply Discord RPC changes regardless of user's status --- osu.Desktop/DiscordRichPresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index f990fd55fc..1944a73c0a 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -92,7 +92,7 @@ namespace osu.Desktop return; } - if (status.Value == UserStatus.Online && activity.Value != null) + if (activity.Value != null) { bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited; presence.State = truncate(activity.Value.GetStatus(hideIdentifiableInformation)); From e80b08c46fe45da19ffa6fba4862329333a6f112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Feb 2024 09:55:51 +0100 Subject: [PATCH 579/915] Fix incorrect standardised score estimation on selected beatmaps --- osu.Game/Database/StandardisedScoreMigrationTools.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index 403e73ab77..0594c80390 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -365,6 +365,17 @@ namespace osu.Game.Database + bonusProportion) * modMultiplier); } + // see similar check above. + // if there is no legacy combo score, all combo conversion operations below + // are either pointless or wildly wrong. + if (maximumLegacyComboScore + maximumLegacyBonusScore == 0) + { + return (long)Math.Round(( + 500000 * comboProportion // as above, zero if mods result in zero multiplier, one otherwise + + 500000 * Math.Pow(score.Accuracy, 5) + + bonusProportion) * modMultiplier); + } + // Assumptions: // - sliders and slider ticks are uniformly distributed in the beatmap, and thus can be ignored without losing much precision. // We thus consider a map of hit-circles only, which gives objectCount == maximumCombo. From e7d8ca3292e4213b248914c7a0416b48b84b2f18 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 24 Feb 2024 14:22:34 +0300 Subject: [PATCH 580/915] Fix Argon and Trianles spinner stutter --- osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs index ee9f228137..7ed6d2dce7 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon { base.Update(); - if (!spmContainer.IsPresent && drawableSpinner.Result?.TimeStarted != null) + if (spmContainer.Alpha != 0 && drawableSpinner.Result?.TimeStarted != null) fadeCounterOnTimeStart(); } diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs index 4a76a1aec4..a5973ad444 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default { base.Update(); - if (!spmContainer.IsPresent && drawableSpinner.Result?.TimeStarted != null) + if (spmContainer.Alpha != 0 && drawableSpinner.Result?.TimeStarted != null) fadeCounterOnTimeStart(); } From 4bc92a263f9c95eece33fe97dadc40eeddc897d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Feb 2024 13:20:42 +0100 Subject: [PATCH 581/915] Bump score version --- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index c74980abb6..775d87f3f2 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -44,9 +44,10 @@ namespace osu.Game.Scoring.Legacy /// method. Reconvert all scores. /// /// 30000013: All local scores will use lazer definitions of ranks for consistency. Recalculates the rank of all scores. + /// 30000014: Fix edge cases in conversion for osu! scores on selected beatmaps. Reconvert all scores. /// /// - public const int LATEST_VERSION = 30000013; + public const int LATEST_VERSION = 30000014; /// /// The first stable-compatible YYYYMMDD format version given to lazer usage of replays. From f6ceedc7a6dfd727c4ea29c14bca6c63575c6dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Feb 2024 13:55:44 +0100 Subject: [PATCH 582/915] Inline last version which touched ranks when checking for upgrade --- osu.Game/Database/BackgroundDataStoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/BackgroundDataStoreProcessor.cs b/osu.Game/Database/BackgroundDataStoreProcessor.cs index be0c83bdb3..872194aa1d 100644 --- a/osu.Game/Database/BackgroundDataStoreProcessor.cs +++ b/osu.Game/Database/BackgroundDataStoreProcessor.cs @@ -382,7 +382,7 @@ namespace osu.Game.Database HashSet scoreIds = realmAccess.Run(r => new HashSet( r.All() - .Where(s => s.TotalScoreVersion < LegacyScoreEncoder.LATEST_VERSION) + .Where(s => s.TotalScoreVersion < 30000013) // last total score version with a significant change to ranks .AsEnumerable() // must be done after materialisation, as realm doesn't support // filtering on nested property predicates or projection via `.Select()` From 9b526912e9f58f9b9250ca4df8f104a988a9644b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 24 Feb 2024 16:41:53 +0300 Subject: [PATCH 583/915] Fix incorrect operator --- osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs index 7ed6d2dce7..e168e14858 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon { base.Update(); - if (spmContainer.Alpha != 0 && drawableSpinner.Result?.TimeStarted != null) + if (spmContainer.Alpha == 0 && drawableSpinner.Result?.TimeStarted != null) fadeCounterOnTimeStart(); } diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs index a5973ad444..2088839e82 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default { base.Update(); - if (spmContainer.Alpha != 0 && drawableSpinner.Result?.TimeStarted != null) + if (spmContainer.Alpha == 0 && drawableSpinner.Result?.TimeStarted != null) fadeCounterOnTimeStart(); } From 4bba0eaf4b5b996ff6b053e1b88cb2b86bcd477c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 24 Feb 2024 16:42:44 +0300 Subject: [PATCH 584/915] Remove repeated TimeStarted check --- osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs index e168e14858..25ce92d1c5 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon { base.Update(); - if (spmContainer.Alpha == 0 && drawableSpinner.Result?.TimeStarted != null) + if (spmContainer.Alpha == 0) fadeCounterOnTimeStart(); } diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs index 2088839e82..5c4d7ae47b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default { base.Update(); - if (spmContainer.Alpha == 0 && drawableSpinner.Result?.TimeStarted != null) + if (spmContainer.Alpha == 0) fadeCounterOnTimeStart(); } From 2696620d12078432f749f02103c7a7774740f90a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 24 Feb 2024 17:09:21 +0300 Subject: [PATCH 585/915] Completely remove transform flow for spm counter --- .../Skinning/Argon/ArgonSpinner.cs | 33 +++++-------------- .../Skinning/Default/DefaultSpinner.cs | 33 +++++-------------- 2 files changed, 16 insertions(+), 50 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs index 25ce92d1c5..f2bbd7373e 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs @@ -5,7 +5,6 @@ using System; using System.Globalization; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -111,42 +110,26 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon { spmCounter.Text = Math.Truncate(spm.NewValue).ToString(@"#0"); }, true); - - drawableSpinner.ApplyCustomUpdateState += updateStateTransforms; - updateStateTransforms(drawableSpinner, drawableSpinner.State.Value); } protected override void Update() { base.Update(); - if (spmContainer.Alpha == 0) - fadeCounterOnTimeStart(); + updateSpmAlpha(); } - private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state) - { - if (!(drawableHitObject is DrawableSpinner)) - return; - - fadeCounterOnTimeStart(); - } - - private void fadeCounterOnTimeStart() + private void updateSpmAlpha() { if (drawableSpinner.Result?.TimeStarted is double startTime) { - using (BeginAbsoluteSequence(startTime)) - spmContainer.FadeIn(drawableSpinner.HitObject.TimeFadeIn); + double timeOffset = Math.Clamp(Clock.CurrentTime, startTime, startTime + drawableSpinner.HitObject.TimeFadeIn) - startTime; + spmContainer.Alpha = (float)(timeOffset / drawableSpinner.HitObject.TimeFadeIn); + } + else + { + spmContainer.Alpha = 0; } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (drawableSpinner.IsNotNull()) - drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs index 5c4d7ae47b..0bd877b902 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs @@ -5,7 +5,6 @@ using System; using System.Globalization; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -117,42 +116,26 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default { spmCounter.Text = Math.Truncate(spm.NewValue).ToString(@"#0"); }, true); - - drawableSpinner.ApplyCustomUpdateState += updateStateTransforms; - updateStateTransforms(drawableSpinner, drawableSpinner.State.Value); } protected override void Update() { base.Update(); - if (spmContainer.Alpha == 0) - fadeCounterOnTimeStart(); + updateSpmAlpha(); } - private void updateStateTransforms(DrawableHitObject drawableHitObject, ArmedState state) - { - if (!(drawableHitObject is DrawableSpinner)) - return; - - fadeCounterOnTimeStart(); - } - - private void fadeCounterOnTimeStart() + private void updateSpmAlpha() { if (drawableSpinner.Result?.TimeStarted is double startTime) { - using (BeginAbsoluteSequence(startTime)) - spmContainer.FadeIn(drawableSpinner.HitObject.TimeFadeIn); + double timeOffset = Math.Clamp(Clock.CurrentTime, startTime, startTime + drawableSpinner.HitObject.TimeFadeIn) - startTime; + spmContainer.Alpha = (float)(timeOffset / drawableSpinner.HitObject.TimeFadeIn); + } + else + { + spmContainer.Alpha = 0; } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (drawableSpinner.IsNotNull()) - drawableSpinner.ApplyCustomUpdateState -= updateStateTransforms; } } } From 824d671cce71eded91dee5ade2868da18a5f8e4b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Feb 2024 00:12:20 +0800 Subject: [PATCH 586/915] Simplify implementation --- osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs | 7 +------ osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs index f2bbd7373e..3b48d36bb5 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinner.cs @@ -122,14 +122,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon private void updateSpmAlpha() { if (drawableSpinner.Result?.TimeStarted is double startTime) - { - double timeOffset = Math.Clamp(Clock.CurrentTime, startTime, startTime + drawableSpinner.HitObject.TimeFadeIn) - startTime; - spmContainer.Alpha = (float)(timeOffset / drawableSpinner.HitObject.TimeFadeIn); - } + spmContainer.Alpha = (float)Math.Clamp((Clock.CurrentTime - startTime) / drawableSpinner.HitObject.TimeFadeIn, 0, 1); else - { spmContainer.Alpha = 0; - } } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs index 0bd877b902..ac56b45b69 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs @@ -128,14 +128,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default private void updateSpmAlpha() { if (drawableSpinner.Result?.TimeStarted is double startTime) - { - double timeOffset = Math.Clamp(Clock.CurrentTime, startTime, startTime + drawableSpinner.HitObject.TimeFadeIn) - startTime; - spmContainer.Alpha = (float)(timeOffset / drawableSpinner.HitObject.TimeFadeIn); - } + spmContainer.Alpha = (float)Math.Clamp((Clock.CurrentTime - startTime) / drawableSpinner.HitObject.TimeFadeIn, 0, 1); else - { spmContainer.Alpha = 0; - } } } } From 1fb19e712922871adca31db706afd27ebb0a247f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 24 Feb 2024 20:18:30 +0300 Subject: [PATCH 587/915] Reduce allocations in DrawableSpinner --- .../Objects/Drawables/DrawableSpinner.cs | 32 ++++++++++++++++--- .../Objects/Drawables/DrawableHitObject.cs | 4 ++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 11120e49b5..8c21e6a6bc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -279,10 +279,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (HandleUserInput) { bool isValidSpinningTime = Time.Current >= HitObject.StartTime && Time.Current <= HitObject.EndTime; - bool correctButtonPressed = (OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); RotationTracker.Tracking = !Result.HasResult - && correctButtonPressed + && correctButtonPressed() && isValidSpinningTime; } @@ -292,11 +291,34 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // Ticks can theoretically be judged at any point in the spinner's duration. // A tick must be alive to correctly play back samples, // but for performance reasons, we only want to keep the next tick alive. - var next = NestedHitObjects.FirstOrDefault(h => !h.Judged); + DrawableHitObject nextTick = null; + + foreach (var nested in NestedHitObjects) + { + if (!nested.Judged) + { + nextTick = nested; + break; + } + } // See default `LifetimeStart` as set in `DrawableSpinnerTick`. - if (next?.LifetimeStart == double.MaxValue) - next.LifetimeStart = HitObject.StartTime; + if (nextTick?.LifetimeStart == double.MaxValue) + nextTick.LifetimeStart = HitObject.StartTime; + } + + private bool correctButtonPressed() + { + if (OsuActionInputManager == null) + return false; + + foreach (var action in OsuActionInputManager.PressedActions) + { + if (action == OsuAction.LeftButton || action == OsuAction.RightButton) + return true; + } + + return false; } protected override void UpdateAfterChildren() diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 16bd4b565c..de05219212 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -11,10 +11,12 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ListExtensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; +using osu.Framework.Lists; using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Audio; @@ -65,7 +67,7 @@ namespace osu.Game.Rulesets.Objects.Drawables public virtual IEnumerable GetSamples() => HitObject.Samples; private readonly List nestedHitObjects = new List(); - public IReadOnlyList NestedHitObjects => nestedHitObjects; + public SlimReadOnlyListWrapper NestedHitObjects => nestedHitObjects.AsSlimReadOnly(); /// /// Whether this object should handle any user input events. From 9e90f7fb0d731e06d36bce8e5bc269f362f307cd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 24 Feb 2024 20:36:06 +0300 Subject: [PATCH 588/915] Store last enqueued RotationRecord in SpinnerSpmCalculator --- .../Skinning/Default/SpinnerSpmCalculator.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs index 44962c8548..7986108fbd 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs @@ -2,7 +2,6 @@ // 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.Bindables; using osu.Framework.Extensions.ObjectExtensions; @@ -33,14 +32,16 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default drawableSpinner.HitObjectApplied += resetState; } + private RotationRecord lastRecord; + public void SetRotation(float currentRotation) { // If we've gone back in time, it's fine to work with a fresh set of records for now - if (records.Count > 0 && Time.Current < records.Last().Time) + if (records.Count > 0 && Time.Current < lastRecord.Time) records.Clear(); // Never calculate SPM by same time of record to avoid 0 / 0 = NaN or X / 0 = Infinity result. - if (records.Count > 0 && Precision.AlmostEquals(Time.Current, records.Last().Time)) + if (records.Count > 0 && Precision.AlmostEquals(Time.Current, lastRecord.Time)) return; if (records.Count > 0) @@ -52,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default result.Value = (currentRotation - record.Rotation) / (Time.Current - record.Time) * 1000 * 60 / 360; } - records.Enqueue(new RotationRecord { Rotation = currentRotation, Time = Time.Current }); + records.Enqueue(lastRecord = new RotationRecord { Rotation = currentRotation, Time = Time.Current }); } private void resetState(DrawableHitObject hitObject) From 3b53ed3c3aae40476d7f061a2796186a9f70c8b7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 24 Feb 2024 22:44:58 +0300 Subject: [PATCH 589/915] Reduce allocations in ModColumn --- osu.Game/Overlays/Mods/ModColumn.cs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index d65c94d14d..df33c78ea4 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -67,8 +67,25 @@ namespace osu.Game.Overlays.Mods private IModHotkeyHandler hotkeyHandler = null!; private Task? latestLoadTask; - private ICollection? latestLoadedPanels; - internal bool ItemsLoaded => latestLoadTask?.IsCompleted == true && latestLoadedPanels?.All(panel => panel.Parent != null) == true; + private ModPanel[]? latestLoadedPanels; + internal bool ItemsLoaded => latestLoadTask?.IsCompleted == true && allPanelsLoaded; + + private bool allPanelsLoaded + { + get + { + if (latestLoadedPanels == null) + return false; + + foreach (var panel in latestLoadedPanels) + { + if (panel.Parent == null) + return false; + } + + return true; + } + } public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; From 6d2187e079c278d36ca628b128223bafc31e5e4d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 24 Feb 2024 22:58:23 +0300 Subject: [PATCH 590/915] Reduce allocations in ModSelectOverlay --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ddf96c1cb3..3009297741 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -349,15 +350,23 @@ namespace osu.Game.Overlays.Mods }); } + private static readonly LocalisableString input_search_placeholder = Resources.Localisation.Web.CommonStrings.InputSearch; + private static readonly LocalisableString tab_to_search_placeholder = ModSelectOverlayStrings.TabToSearch; + protected override void Update() { base.Update(); - SearchTextBox.PlaceholderText = SearchTextBox.HasFocus ? Resources.Localisation.Web.CommonStrings.InputSearch : ModSelectOverlayStrings.TabToSearch; + SearchTextBox.PlaceholderText = SearchTextBox.HasFocus ? input_search_placeholder : tab_to_search_placeholder; if (beatmapAttributesDisplay != null) { - float rightEdgeOfLastButton = footerButtonFlow.Last().ScreenSpaceDrawQuad.TopRight.X; + ShearedButton lastFooterButton = null!; + + foreach (var b in footerButtonFlow) + lastFooterButton = b; + + float rightEdgeOfLastButton = lastFooterButton.ScreenSpaceDrawQuad.TopRight.X; // this is cheating a bit; the 640 value is hardcoded based on how wide the expanded panel _generally_ is. // due to the transition applied, the raw screenspace quad of the panel cannot be used, as it will trigger an ugly feedback cycle of expanding and collapsing. From 91d7bd10265a806946ba0e528da8aa6c07cdcd8e Mon Sep 17 00:00:00 2001 From: Detze <92268414+Detze@users.noreply.github.com> Date: Sat, 24 Feb 2024 21:56:44 +0100 Subject: [PATCH 591/915] Don't dim slider head in `DrawableSlider` --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 6d492e7b08..b7ce712e2c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override IEnumerable DimmablePieces => new Drawable[] { - HeadCircle, + // HeadCircle should not be added to this list, as it handles dimming itself TailCircle, repeatContainer, Body, From e12f8c03eef09478b8c8f3823b60632d37713192 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Feb 2024 08:18:19 +0800 Subject: [PATCH 592/915] Reset `lastRecord` on `resetState` for good measure --- osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs index 7986108fbd..3383989367 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs @@ -58,6 +58,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default private void resetState(DrawableHitObject hitObject) { + lastRecord = default; result.Value = 0; records.Clear(); } From 081aa84718233618bd1d9fc81468e99023dbc705 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 25 Feb 2024 10:36:15 +0300 Subject: [PATCH 593/915] Simplify last footer button selection --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 3009297741..ce1d0d27a3 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -361,12 +361,7 @@ namespace osu.Game.Overlays.Mods if (beatmapAttributesDisplay != null) { - ShearedButton lastFooterButton = null!; - - foreach (var b in footerButtonFlow) - lastFooterButton = b; - - float rightEdgeOfLastButton = lastFooterButton.ScreenSpaceDrawQuad.TopRight.X; + float rightEdgeOfLastButton = footerButtonFlow[^1].ScreenSpaceDrawQuad.TopRight.X; // this is cheating a bit; the 640 value is hardcoded based on how wide the expanded panel _generally_ is. // due to the transition applied, the raw screenspace quad of the panel cannot be used, as it will trigger an ugly feedback cycle of expanding and collapsing. From f948f8ee5c49498ea58fe2a2e5817ef7fbb027c7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 25 Feb 2024 17:59:20 +0300 Subject: [PATCH 594/915] Fix HUDOverlay allocations --- osu.Game/Screens/Play/HUDOverlay.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 32ebb82f15..f965d3392a 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -258,13 +258,13 @@ namespace osu.Game.Screens.Play Vector2? highestBottomScreenSpace = null; - foreach (var element in mainComponents.Components) - processDrawable(element); + for (int i = 0; i < mainComponents.Components.Count; i++) + processDrawable(mainComponents.Components[i]); if (rulesetComponents != null) { - foreach (var element in rulesetComponents.Components) - processDrawable(element); + for (int i = 0; i < rulesetComponents.Components.Count; i++) + processDrawable(rulesetComponents.Components[i]); } if (lowestTopScreenSpaceRight.HasValue) From c3fa97d062c370c4d5c60b2cee66e7b8298a79b7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 25 Feb 2024 18:02:42 +0300 Subject: [PATCH 595/915] Reduce allocations in HitObjectLifetimeEntry --- .../Rulesets/Objects/HitObjectLifetimeEntry.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs b/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs index 4450f026b4..9f2720b7ca 100644 --- a/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs +++ b/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs @@ -41,7 +41,22 @@ namespace osu.Game.Rulesets.Objects /// /// Whether and all of its nested objects have been judged. /// - public bool AllJudged => Judged && NestedEntries.All(h => h.AllJudged); + public bool AllJudged + { + get + { + if (!Judged) + return false; + + foreach (var entry in NestedEntries) + { + if (!entry.AllJudged) + return false; + } + + return true; + } + } private readonly IBindable startTimeBindable = new BindableDouble(); From 9e3defebda1d446f815cb0cae6618f822ba482d2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 25 Feb 2024 19:05:40 +0300 Subject: [PATCH 596/915] Remove unused using --- osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs b/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs index 9f2720b7ca..4962ac13b5 100644 --- a/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs +++ b/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics.Performance; using osu.Game.Rulesets.Judgements; From 5c049feca1e855daca7499b2e6bfb6482c99fe8a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Feb 2024 21:18:15 +0300 Subject: [PATCH 597/915] Fix advanced stats in beatmap info overlay showing "key count" on non-mania beatmaps --- osu.Game/Overlays/BeatmapSet/Details.cs | 30 ++++++++++++------- .../Screens/Select/Details/AdvancedStats.cs | 29 ++++++------------ osu.Game/Screens/Select/SongSelect.cs | 7 ++++- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index cf78f605aa..d656a6b14b 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Buttons; +using osu.Game.Rulesets; using osu.Game.Screens.Select.Details; using osuTK; @@ -33,10 +34,10 @@ namespace osu.Game.Overlays.BeatmapSet { if (value == beatmapSet) return; - beatmapSet = value; + basic.BeatmapSet = preview.BeatmapSet = beatmapSet = value; - basic.BeatmapSet = preview.BeatmapSet = BeatmapSet; - updateDisplay(); + if (IsLoaded) + updateDisplay(); } } @@ -50,13 +51,10 @@ namespace osu.Game.Overlays.BeatmapSet if (value == beatmapInfo) return; basic.BeatmapInfo = advanced.BeatmapInfo = beatmapInfo = value; - } - } - private void updateDisplay() - { - Ratings.Ratings = BeatmapSet?.Ratings; - ratingBox.Alpha = BeatmapSet?.Status > 0 ? 1 : 0; + if (IsLoaded) + updateDisplay(); + } } public Details() @@ -101,12 +99,22 @@ namespace osu.Game.Overlays.BeatmapSet }; } - [BackgroundDependencyLoader] - private void load() + [Resolved] + private RulesetStore rulesets { get; set; } + + protected override void LoadComplete() { + base.LoadComplete(); updateDisplay(); } + private void updateDisplay() + { + Ratings.Ratings = BeatmapSet?.Ratings; + ratingBox.Alpha = BeatmapSet?.Status > 0 ? 1 : 0; + advanced.Ruleset.Value = rulesets.GetRuleset(beatmapInfo?.Ruleset.OnlineID ?? 0); + } + private partial class DetailBox : Container { private readonly Container content; diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 0d68a0ec3c..74276795d2 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -38,11 +38,6 @@ namespace osu.Game.Screens.Select.Details [Resolved] private IBindable> mods { get; set; } - [Resolved] - private OsuGameBase game { get; set; } - - private IBindable gameRuleset; - protected readonly StatisticRow FirstValue, HpDrain, Accuracy, ApproachRate; private readonly StatisticRow starDifficulty; @@ -64,6 +59,8 @@ namespace osu.Game.Screens.Select.Details } } + public Bindable Ruleset { get; } = new Bindable(); + public AdvancedStats(int columns = 1) { switch (columns) @@ -137,12 +134,7 @@ namespace osu.Game.Screens.Select.Details { base.LoadComplete(); - // the cached ruleset bindable might be a decoupled bindable provided by SongSelect, - // which we can't rely on in combination with the game-wide selected mods list, - // since mods could be updated to the new ruleset instances while the decoupled bindable is held behind, - // therefore resulting in performing difficulty calculation with invalid states. - gameRuleset = game.Ruleset.GetBoundCopy(); - gameRuleset.BindValueChanged(_ => updateStatistics()); + Ruleset.BindValueChanged(_ => updateStatistics()); mods.BindValueChanged(modsChanged, true); } @@ -169,8 +161,6 @@ namespace osu.Game.Screens.Select.Details IBeatmapDifficultyInfo baseDifficulty = BeatmapInfo?.Difficulty; BeatmapDifficulty adjustedDifficulty = null; - IRulesetInfo ruleset = gameRuleset?.Value ?? beatmapInfo.Ruleset; - if (baseDifficulty != null) { BeatmapDifficulty originalDifficulty = new BeatmapDifficulty(baseDifficulty); @@ -180,24 +170,24 @@ namespace osu.Game.Screens.Select.Details adjustedDifficulty = originalDifficulty; - if (gameRuleset != null) + if (Ruleset.Value != null) { double rate = 1; foreach (var mod in mods.Value.OfType()) rate = mod.ApplyToRate(0, rate); - adjustedDifficulty = ruleset.CreateInstance().GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); + adjustedDifficulty = Ruleset.Value.CreateInstance().GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, adjustedDifficulty); } } - switch (ruleset.OnlineID) + switch (Ruleset.Value?.OnlineID) { case 3: // Account for mania differences locally for now. // Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes. - ILegacyRuleset legacyRuleset = (ILegacyRuleset)ruleset.CreateInstance(); + ILegacyRuleset legacyRuleset = (ILegacyRuleset)Ruleset.Value.CreateInstance(); // For the time being, the key count is static no matter what, because: // a) The method doesn't have knowledge of the active keymods. Doing so may require considerations for filtering. @@ -206,7 +196,6 @@ namespace osu.Game.Screens.Select.Details FirstValue.Title = BeatmapsetsStrings.ShowStatsCsMania; FirstValue.Value = (keyCount, keyCount); - break; default: @@ -240,8 +229,8 @@ namespace osu.Game.Screens.Select.Details starDifficultyCancellationSource = new CancellationTokenSource(); - var normalStarDifficultyTask = difficultyCache.GetDifficultyAsync(BeatmapInfo, gameRuleset.Value, null, starDifficultyCancellationSource.Token); - var moddedStarDifficultyTask = difficultyCache.GetDifficultyAsync(BeatmapInfo, gameRuleset.Value, mods.Value, starDifficultyCancellationSource.Token); + var normalStarDifficultyTask = difficultyCache.GetDifficultyAsync(BeatmapInfo, Ruleset.Value, null, starDifficultyCancellationSource.Token); + var moddedStarDifficultyTask = difficultyCache.GetDifficultyAsync(BeatmapInfo, Ruleset.Value, mods.Value, starDifficultyCancellationSource.Token); Task.WhenAll(normalStarDifficultyTask, moddedStarDifficultyTask).ContinueWith(_ => Schedule(() => { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index a603934a9d..15469fad5b 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -286,7 +286,7 @@ namespace osu.Game.Screens.Select AutoSizeAxes = Axes.Y, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Padding = new MarginPadding(10) + Padding = new MarginPadding(10), }, } }, @@ -585,6 +585,11 @@ namespace osu.Game.Screens.Select beatmapInfoPrevious = beatmap; } + // we can't run this in the debounced run due to the selected mods bindable not being debounced, + // since mods could be updated to the new ruleset instances while the decoupled bindable is held behind, + // therefore resulting in performing difficulty calculation with invalid states. + advancedStats.Ruleset.Value = ruleset; + void run() { // clear pending task immediately to track any potential nested debounce operation. From b30a6d522462331e20043f0bada10186a3315196 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 25 Feb 2024 21:23:09 +0300 Subject: [PATCH 598/915] Adjust existing test coverage --- .../SongSelect/TestSceneAdvancedStats.cs | 49 ++----------------- 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs index 4bb2b557ff..3b89c70a63 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs @@ -37,15 +37,9 @@ namespace osu.Game.Tests.Visual.SongSelect [SetUp] public void Setup() => Schedule(() => Child = advancedStats = new TestAdvancedStats { - Width = 500 + Width = 500, }); - [SetUpSteps] - public void SetUpSteps() - { - AddStep("reset game ruleset", () => Ruleset.Value = new OsuRuleset().RulesetInfo); - } - private BeatmapInfo exampleBeatmapInfo => new BeatmapInfo { Ruleset = rulesets.AvailableRulesets.First(), @@ -74,45 +68,12 @@ namespace osu.Game.Tests.Visual.SongSelect } [Test] - public void TestManiaFirstBarTextManiaBeatmap() + public void TestFirstBarText() { - AddStep("set game ruleset to mania", () => Ruleset.Value = new ManiaRuleset().RulesetInfo); - - AddStep("set beatmap", () => advancedStats.BeatmapInfo = new BeatmapInfo - { - Ruleset = rulesets.GetRuleset(3) ?? throw new InvalidOperationException("osu!mania ruleset not found"), - Difficulty = new BeatmapDifficulty - { - CircleSize = 5, - DrainRate = 4.3f, - OverallDifficulty = 4.5f, - ApproachRate = 3.1f - }, - StarRating = 8 - }); - - AddAssert("first bar text is correct", () => advancedStats.ChildrenOfType().First().Text == BeatmapsetsStrings.ShowStatsCsMania); - } - - [Test] - public void TestManiaFirstBarTextConvert() - { - AddStep("set game ruleset to mania", () => Ruleset.Value = new ManiaRuleset().RulesetInfo); - - AddStep("set beatmap", () => advancedStats.BeatmapInfo = new BeatmapInfo - { - Ruleset = new OsuRuleset().RulesetInfo, - Difficulty = new BeatmapDifficulty - { - CircleSize = 5, - DrainRate = 4.3f, - OverallDifficulty = 4.5f, - ApproachRate = 3.1f - }, - StarRating = 8 - }); - + AddStep("set ruleset to mania", () => advancedStats.Ruleset.Value = new ManiaRuleset().RulesetInfo); AddAssert("first bar text is correct", () => advancedStats.ChildrenOfType().First().Text == BeatmapsetsStrings.ShowStatsCsMania); + AddStep("set ruleset to osu", () => advancedStats.Ruleset.Value = new OsuRuleset().RulesetInfo); + AddAssert("first bar text is correct", () => advancedStats.ChildrenOfType().First().Text == BeatmapsetsStrings.ShowStatsCs); } [Test] From 4421ff975b330e832ee0405b9171dfeed2255577 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 09:04:39 +0800 Subject: [PATCH 599/915] Add local function to perform iteration to better explain the "why" --- osu.Game/Screens/Play/HUDOverlay.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index f965d3392a..2ec2a011a6 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -258,14 +258,10 @@ namespace osu.Game.Screens.Play Vector2? highestBottomScreenSpace = null; - for (int i = 0; i < mainComponents.Components.Count; i++) - processDrawable(mainComponents.Components[i]); + processDrawables(mainComponents); if (rulesetComponents != null) - { - for (int i = 0; i < rulesetComponents.Components.Count; i++) - processDrawable(rulesetComponents.Components[i]); - } + processDrawables(rulesetComponents); if (lowestTopScreenSpaceRight.HasValue) topRightElements.Y = MathHelper.Clamp(ToLocalSpace(new Vector2(0, lowestTopScreenSpaceRight.Value)).Y, 0, DrawHeight - topRightElements.DrawHeight); @@ -282,6 +278,14 @@ namespace osu.Game.Screens.Play else bottomRightElements.Y = 0; + void processDrawables(SkinComponentsContainer components) + { + // Avoid using foreach due to missing GetEnumerator implementation. + // See https://github.com/ppy/osu-framework/blob/e10051e6643731e393b09de40a3a3d209a545031/osu.Framework/Bindables/IBindableList.cs#L41-L44. + for (int i = 0; i < components.Components.Count; i++) + processDrawable(components.Components[i]); + } + void processDrawable(ISerialisableDrawable element) { // Cast can be removed when IDrawable interface includes Anchor / RelativeSizeAxes. From 3502ec456d0131f4f6c1c9faabf01e6197a16ee1 Mon Sep 17 00:00:00 2001 From: Detze <92268414+Detze@users.noreply.github.com> Date: Mon, 26 Feb 2024 04:36:09 +0100 Subject: [PATCH 600/915] Match stable's slider border thickness more closely --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index b39092a467..6bf6776617 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy protected new float CalculatedBorderPortion // Roughly matches osu!stable's slider border portions. - => base.CalculatedBorderPortion * 0.77f; + => base.CalculatedBorderPortion * 0.84f; protected override Color4 ColourAt(float position) { From 4c744ccb698e9f41cc350fcde45159a30ec52944 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 14:11:54 +0800 Subject: [PATCH 601/915] Fix "Use current" snap not working Regressed with https://github.com/ppy/osu/pull/27249. I was suspicious of this specific operation at the time but didn't test properly. --- osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs index b2f38662cc..8bff5fe6ac 100644 --- a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Edit if (objTime >= editorClock.CurrentTime) continue; - if (objTime > lastBefore?.StartTime) + if (lastBefore == null || objTime > lastBefore?.StartTime) lastBefore = entry.Value.HitObject; } @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Edit if (objTime < editorClock.CurrentTime) continue; - if (objTime < firstAfter?.StartTime) + if (firstAfter == null || objTime < firstAfter?.StartTime) firstAfter = entry.Value.HitObject; } From 9a46e738bdf86cb0f8495e6ef69f5cc8a6d5456c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 15:45:29 +0800 Subject: [PATCH 602/915] Fix inspections --- osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs index 8bff5fe6ac..62ad2ce7e9 100644 --- a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Edit if (objTime >= editorClock.CurrentTime) continue; - if (lastBefore == null || objTime > lastBefore?.StartTime) + if (lastBefore == null || objTime > lastBefore.StartTime) lastBefore = entry.Value.HitObject; } @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Edit if (objTime < editorClock.CurrentTime) continue; - if (firstAfter == null || objTime < firstAfter?.StartTime) + if (firstAfter == null || objTime < firstAfter.StartTime) firstAfter = entry.Value.HitObject; } From 8962be2ed54f8431d29d6558aa8eacf28e467707 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 17:24:04 +0800 Subject: [PATCH 603/915] Allow better menu navigation using same hotkey to progress to destination As touched on in https://github.com/ppy/osu/discussions/27102. You can now use: - `L L L` to get to playlists - `M M M` to get to multiplayer - `S` to get to settings --- osu.Game/Screens/Menu/ButtonSystem.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index d742d2377f..15a2740160 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Menu buttonArea.AddRange(new Drawable[] { - new MainMenuButton(ButtonSystemStrings.Settings, string.Empty, OsuIcon.Settings, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O), + new MainMenuButton(ButtonSystemStrings.Settings, string.Empty, OsuIcon.Settings, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O, Key.S), backButton = new MainMenuButton(ButtonSystemStrings.Back, @"back-to-top", OsuIcon.PrevCircle, new Color4(51, 58, 94, 255), () => State = ButtonSystemState.TopLevel, -WEDGE_WIDTH) { @@ -132,11 +132,11 @@ namespace osu.Game.Screens.Menu buttonsPlay.Add(new MainMenuButton(ButtonSystemStrings.Playlists, @"button-default-select", OsuIcon.Tournament, new Color4(94, 63, 186, 255), onPlaylists, 0, Key.L)); buttonsPlay.ForEach(b => b.VisibleState = ButtonSystemState.Play); - buttonsEdit.Add(new MainMenuButton(EditorStrings.BeatmapEditor.ToLower(), @"button-default-select", OsuIcon.Beatmap, new Color4(238, 170, 0, 255), () => OnEditBeatmap?.Invoke(), WEDGE_WIDTH, Key.B)); + buttonsEdit.Add(new MainMenuButton(EditorStrings.BeatmapEditor.ToLower(), @"button-default-select", OsuIcon.Beatmap, new Color4(238, 170, 0, 255), () => OnEditBeatmap?.Invoke(), WEDGE_WIDTH, Key.B, Key.E)); buttonsEdit.Add(new MainMenuButton(SkinEditorStrings.SkinEditor.ToLower(), @"button-default-select", OsuIcon.SkinB, new Color4(220, 160, 0, 255), () => OnEditSkin?.Invoke(), 0, Key.S)); buttonsEdit.ForEach(b => b.VisibleState = ButtonSystemState.Edit); - buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Play, @"button-play-select", OsuIcon.Logo, new Color4(102, 68, 204, 255), () => State = ButtonSystemState.Play, WEDGE_WIDTH, Key.P)); + buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Play, @"button-play-select", OsuIcon.Logo, new Color4(102, 68, 204, 255), () => State = ButtonSystemState.Play, WEDGE_WIDTH, Key.P, Key.M, Key.L)); buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Edit, @"button-play-select", OsuIcon.EditCircle, new Color4(238, 170, 0, 255), () => State = ButtonSystemState.Edit, 0, Key.E)); buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Browse, @"button-default-select", OsuIcon.Beatmap, new Color4(165, 204, 0, 255), () => OnBeatmapListing?.Invoke(), 0, Key.B, Key.D)); From 115d82664bb0a3271e7593dacce987557a2ff098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 26 Feb 2024 10:37:03 +0100 Subject: [PATCH 604/915] Assert proportional scaling rather than assume average Because if scaling is ever actually non-proportional then this should be somewhat loud. Also use the absolute value to prevent funny things happening if/when someone does negative scale. --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index d714cd3c85..144842def0 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Runtime.InteropServices; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -13,6 +14,7 @@ using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Shaders.Types; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; +using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.OpenGL.Vertices; @@ -151,9 +153,10 @@ namespace osu.Game.Rulesets.Mods if (GetPlayfieldScale != null) { Vector2 playfieldScale = GetPlayfieldScale(); - float rulesetScaleAvg = (playfieldScale.X + playfieldScale.Y) / 2f; - size *= rulesetScaleAvg; + Debug.Assert(Precision.AlmostEquals(Math.Abs(playfieldScale.X), Math.Abs(playfieldScale.Y)), + @"Playfield has non-proportional scaling. Flashlight implementations should be revisited with regard to balance."); + size *= Math.Abs(playfieldScale.X); } if (isBreakTime.Value) From 8e336610d090b2d1f94239620c336a7e0854fc34 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 18:31:36 +0800 Subject: [PATCH 605/915] Add xmldoc explaining `Ruleset` bindable's usage --- osu.Game/Screens/Select/Details/AdvancedStats.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 74276795d2..1aba977f44 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -59,6 +59,13 @@ namespace osu.Game.Screens.Select.Details } } + /// + /// Ruleset to be used for certain elements of display. + /// When set, this will override the set 's own ruleset. + /// + /// + /// No checks are done as to whether the ruleset specified is valid for the currently . + /// public Bindable Ruleset { get; } = new Bindable(); public AdvancedStats(int columns = 1) From 8966ea2fa3a81cd567aeacbbee60e857af7d9520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 26 Feb 2024 11:59:57 +0100 Subject: [PATCH 606/915] Add test coverage --- ...tSceneHitObjectComposerDistanceSnapping.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs index 463287fb35..12b7dbbf12 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.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.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -17,6 +18,7 @@ using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; using osu.Game.Tests.Visual; +using osuTK; namespace osu.Game.Tests.Editing { @@ -228,6 +230,28 @@ namespace osu.Game.Tests.Editing assertSnappedDistance(400, 400); } + [Test] + public void TestUseCurrentSnap() + { + AddStep("add objects to beatmap", () => + { + editorBeatmap.Add(new HitCircle { StartTime = 1000 }); + editorBeatmap.Add(new HitCircle { Position = new Vector2(100), StartTime = 2000 }); + }); + + AddStep("hover use current snap button", () => InputManager.MoveMouseTo(composer.ChildrenOfType().Single())); + AddUntilStep("use current snap expanded", () => composer.ChildrenOfType().Single().Expanded.Value, () => Is.True); + + AddStep("seek before first object", () => EditorClock.Seek(0)); + AddUntilStep("use current snap not available", () => composer.ChildrenOfType().Single().Enabled.Value, () => Is.False); + + AddStep("seek to between objects", () => EditorClock.Seek(1500)); + AddUntilStep("use current snap available", () => composer.ChildrenOfType().Single().Enabled.Value, () => Is.True); + + AddStep("seek after last object", () => EditorClock.Seek(2500)); + AddUntilStep("use current snap not available", () => composer.ChildrenOfType().Single().Enabled.Value, () => Is.False); + } + private void assertSnapDistance(float expectedDistance, HitObject? referenceObject, bool includeSliderVelocity) => AddAssert($"distance is {expectedDistance}", () => composer.DistanceSnapProvider.GetBeatSnapDistanceAt(referenceObject ?? new HitObject(), includeSliderVelocity), () => Is.EqualTo(expectedDistance).Within(Precision.FLOAT_EPSILON)); From 6dbba705b3127757dbb36f16911790d776934527 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 26 Feb 2024 12:27:02 +0100 Subject: [PATCH 607/915] Refine uninstall logic to account for legacy windows features --- osu.Desktop/Windows/WindowsAssociationManager.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 4bb8e57c9d..490faab632 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -222,12 +222,21 @@ namespace osu.Desktop.Windows programKey?.SetValue(null, description); } + /// + /// Uninstalls the file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/shell/fa-file-types#deleting-registry-information-during-uninstallation + /// public void Uninstall(RegistryKey classes) { - // importantly, we don't delete the default program entry because some other program could have taken it. + using (var extensionKey = classes.OpenSubKey(Extension, true)) + { + // clear our default association so that Explorer doesn't show the raw programId to users + // the null/(Default) entry is used for both ProdID association and as a fallback friendly name, for legacy reasons + if (extensionKey?.GetValue(null) is string s && s == programId) + extensionKey.SetValue(null, string.Empty); - using (var extensionKey = classes.OpenSubKey($@"{Extension}\OpenWithProgIds", true)) - extensionKey?.DeleteValue(programId, throwOnMissingValue: false); + using (var openWithKey = extensionKey?.CreateSubKey(@"OpenWithProgIds")) + openWithKey?.DeleteValue(programId, throwOnMissingValue: false); + } classes.DeleteSubKeyTree(programId, throwOnMissingSubKey: false); } From f2807470efc66a560dbd09da75be2ff70bf83b1d Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 26 Feb 2024 13:03:23 +0100 Subject: [PATCH 608/915] Inline `EXE_PATH` usage --- osu.Desktop/Windows/WindowsAssociationManager.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 490faab632..3fd566edab 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -136,10 +136,10 @@ namespace osu.Desktop.Windows Debug.Assert(classes != null); foreach (var association in file_associations) - association.Install(classes, EXE_PATH); + association.Install(classes); foreach (var association in uri_associations) - association.Install(classes, EXE_PATH); + association.Install(classes); } private static void updateDescriptions(LocalisationManager? localisation) @@ -192,7 +192,7 @@ namespace osu.Desktop.Windows /// /// Installs a file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key /// - public void Install(RegistryKey classes, string exePath) + public void Install(RegistryKey classes) { // register a program id for the given extension using (var programKey = classes.CreateSubKey(programId)) @@ -201,7 +201,7 @@ namespace osu.Desktop.Windows defaultIconKey.SetValue(null, IconPath); using (var openCommandKey = programKey.CreateSubKey(SHELL_OPEN_COMMAND)) - openCommandKey.SetValue(null, $@"""{exePath}"" ""%1"""); + openCommandKey.SetValue(null, $@"""{EXE_PATH}"" ""%1"""); } using (var extensionKey = classes.CreateSubKey(Extension)) @@ -253,7 +253,7 @@ namespace osu.Desktop.Windows /// /// Registers an URI protocol handler in accordance with https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85). /// - public void Install(RegistryKey classes, string exePath) + public void Install(RegistryKey classes) { using (var protocolKey = classes.CreateSubKey(Protocol)) { @@ -263,7 +263,7 @@ namespace osu.Desktop.Windows defaultIconKey.SetValue(null, IconPath); using (var openCommandKey = protocolKey.CreateSubKey(SHELL_OPEN_COMMAND)) - openCommandKey.SetValue(null, $@"""{exePath}"" ""%1"""); + openCommandKey.SetValue(null, $@"""{EXE_PATH}"" ""%1"""); } } From 9b3ec64f411b234391ac653fb319cbb07d1d6fea Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 26 Feb 2024 13:10:37 +0100 Subject: [PATCH 609/915] Inline `HKCU\Software\Classes` usage --- .../Windows/WindowsAssociationManager.cs | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 3fd566edab..2a1aeba7e0 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -108,14 +107,11 @@ namespace osu.Desktop.Windows { try { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); - Debug.Assert(classes != null); - foreach (var association in file_associations) - association.Uninstall(classes); + association.Uninstall(); foreach (var association in uri_associations) - association.Uninstall(classes); + association.Uninstall(); NotifyShellUpdate(); } @@ -132,26 +128,20 @@ namespace osu.Desktop.Windows /// private static void updateAssociations() { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); - Debug.Assert(classes != null); - foreach (var association in file_associations) - association.Install(classes); + association.Install(); foreach (var association in uri_associations) - association.Install(classes); + association.Install(); } private static void updateDescriptions(LocalisationManager? localisation) { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); - Debug.Assert(classes != null); - foreach (var association in file_associations) - association.UpdateDescription(classes, getLocalisedString(association.Description)); + association.UpdateDescription(getLocalisedString(association.Description)); foreach (var association in uri_associations) - association.UpdateDescription(classes, getLocalisedString(association.Description)); + association.UpdateDescription(getLocalisedString(association.Description)); string getLocalisedString(LocalisableString s) { @@ -192,8 +182,11 @@ namespace osu.Desktop.Windows /// /// Installs a file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key /// - public void Install(RegistryKey classes) + public void Install() { + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) return; + // register a program id for the given extension using (var programKey = classes.CreateSubKey(programId)) { @@ -216,8 +209,11 @@ namespace osu.Desktop.Windows } } - public void UpdateDescription(RegistryKey classes, string description) + public void UpdateDescription(string description) { + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) return; + using (var programKey = classes.OpenSubKey(programId, true)) programKey?.SetValue(null, description); } @@ -225,8 +221,11 @@ namespace osu.Desktop.Windows /// /// Uninstalls the file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/shell/fa-file-types#deleting-registry-information-during-uninstallation /// - public void Uninstall(RegistryKey classes) + public void Uninstall() { + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) return; + using (var extensionKey = classes.OpenSubKey(Extension, true)) { // clear our default association so that Explorer doesn't show the raw programId to users @@ -253,8 +252,11 @@ namespace osu.Desktop.Windows /// /// Registers an URI protocol handler in accordance with https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85). /// - public void Install(RegistryKey classes) + public void Install() { + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) return; + using (var protocolKey = classes.CreateSubKey(Protocol)) { protocolKey.SetValue(URL_PROTOCOL, string.Empty); @@ -267,15 +269,19 @@ namespace osu.Desktop.Windows } } - public void UpdateDescription(RegistryKey classes, string description) + public void UpdateDescription(string description) { + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + if (classes == null) return; + using (var protocolKey = classes.OpenSubKey(Protocol, true)) protocolKey?.SetValue(null, $@"URL:{description}"); } - public void Uninstall(RegistryKey classes) + public void Uninstall() { - classes.DeleteSubKeyTree(Protocol, throwOnMissingSubKey: false); + using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + classes?.DeleteSubKeyTree(Protocol, throwOnMissingSubKey: false); } } } From 3e9425fdf2d57dbeff8819bca208a63cb947eda9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 26 Feb 2024 22:12:04 +0900 Subject: [PATCH 610/915] Adjust API of HighPerformanceSession + rename --- osu.Game/OsuGame.cs | 4 +- .../Performance/HighPerformanceSession.cs | 42 ------------------- .../HighPerformanceSessionManager.cs | 34 +++++++++++++++ 3 files changed, 36 insertions(+), 44 deletions(-) delete mode 100644 osu.Game/Performance/HighPerformanceSession.cs create mode 100644 osu.Game/Performance/HighPerformanceSessionManager.cs diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9ffa88947b..f23a78d2dc 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -792,7 +792,7 @@ namespace osu.Game protected virtual UpdateManager CreateUpdateManager() => new UpdateManager(); - protected virtual HighPerformanceSession CreateHighPerformanceSession() => new HighPerformanceSession(); + protected virtual HighPerformanceSessionManager CreateHighPerformanceSessionManager() => new HighPerformanceSessionManager(); protected override Container CreateScalingContainer() => new ScalingContainer(ScalingMode.Everything); @@ -1088,7 +1088,7 @@ namespace osu.Game loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); - loadComponentSingleFile(CreateHighPerformanceSession(), Add); + loadComponentSingleFile(CreateHighPerformanceSessionManager(), Add, true); loadComponentSingleFile(new BackgroundDataStoreProcessor(), Add); diff --git a/osu.Game/Performance/HighPerformanceSession.cs b/osu.Game/Performance/HighPerformanceSession.cs deleted file mode 100644 index 07b5e7da98..0000000000 --- a/osu.Game/Performance/HighPerformanceSession.cs +++ /dev/null @@ -1,42 +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 osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Game.Screens.Play; - -namespace osu.Game.Performance -{ - public partial class HighPerformanceSession : Component - { - private readonly IBindable localUserPlaying = new Bindable(); - - [BackgroundDependencyLoader] - private void load(ILocalUserPlayInfo localUserInfo) - { - localUserPlaying.BindTo(localUserInfo.IsPlaying); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - localUserPlaying.BindValueChanged(playing => - { - if (playing.NewValue) - EnableHighPerformanceSession(); - else - DisableHighPerformanceSession(); - }, true); - } - - protected virtual void EnableHighPerformanceSession() - { - } - - protected virtual void DisableHighPerformanceSession() - { - } - } -} diff --git a/osu.Game/Performance/HighPerformanceSessionManager.cs b/osu.Game/Performance/HighPerformanceSessionManager.cs new file mode 100644 index 0000000000..8a49ba0dac --- /dev/null +++ b/osu.Game/Performance/HighPerformanceSessionManager.cs @@ -0,0 +1,34 @@ +// 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.Runtime; +using osu.Framework.Allocation; +using osu.Framework.Graphics; + +namespace osu.Game.Performance +{ + public partial class HighPerformanceSessionManager : Component + { + private GCLatencyMode originalGCMode; + + public IDisposable BeginSession() + { + EnableHighPerformanceSession(); + return new InvokeOnDisposal(this, static m => m.DisableHighPerformanceSession()); + } + + protected virtual void EnableHighPerformanceSession() + { + originalGCMode = GCSettings.LatencyMode; + GCSettings.LatencyMode = GCLatencyMode.LowLatency; + GC.Collect(0); + } + + protected virtual void DisableHighPerformanceSession() + { + if (GCSettings.LatencyMode == GCLatencyMode.LowLatency) + GCSettings.LatencyMode = originalGCMode; + } + } +} From 7a96cf12893c3e5d5d6ec2b679a07230e70efe29 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 21:15:44 +0800 Subject: [PATCH 611/915] Expose `AudioFilter.IsAttached` publicly --- osu.Game/Audio/Effects/AudioFilter.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game/Audio/Effects/AudioFilter.cs b/osu.Game/Audio/Effects/AudioFilter.cs index c8673372d7..bfa9b31242 100644 --- a/osu.Game/Audio/Effects/AudioFilter.cs +++ b/osu.Game/Audio/Effects/AudioFilter.cs @@ -17,12 +17,15 @@ namespace osu.Game.Audio.Effects /// public const int MAX_LOWPASS_CUTOFF = 22049; // nyquist - 1hz + /// + /// Whether this filter is currently attached to the audio track and thus applying an adjustment. + /// + public bool IsAttached { get; private set; } + private readonly AudioMixer mixer; private readonly BQFParameters filter; private readonly BQFType type; - private bool isAttached; - private readonly Cached filterApplication = new Cached(); private int cutoff; @@ -132,22 +135,22 @@ namespace osu.Game.Audio.Effects private void ensureAttached() { - if (isAttached) + if (IsAttached) return; Debug.Assert(!mixer.Effects.Contains(filter)); mixer.Effects.Add(filter); - isAttached = true; + IsAttached = true; } private void ensureDetached() { - if (!isAttached) + if (!IsAttached) return; Debug.Assert(mixer.Effects.Contains(filter)); mixer.Effects.Remove(filter); - isAttached = false; + IsAttached = false; } protected override void Dispose(bool isDisposing) From c686dfd36164f6eb980f0d96e64700dad95cf8f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 21:16:15 +0800 Subject: [PATCH 612/915] Apply safeties for `AudioFilter` usage around drawables which go non-present --- .../Collections/ManageCollectionsDialog.cs | 5 +++ osu.Game/Overlays/DialogOverlay.cs | 8 +++-- osu.Game/Screens/Play/PlayerLoader.cs | 35 +++++++++++++------ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/osu.Game/Collections/ManageCollectionsDialog.cs b/osu.Game/Collections/ManageCollectionsDialog.cs index cc0f23d030..16645d6796 100644 --- a/osu.Game/Collections/ManageCollectionsDialog.cs +++ b/osu.Game/Collections/ManageCollectionsDialog.cs @@ -115,6 +115,11 @@ namespace osu.Game.Collections }; } + public override bool IsPresent => base.IsPresent + // Safety for low pass filter potentially getting stuck in applied state due to + // transforms on `this` causing children to no longer be updated. + || lowPassFilter.IsAttached; + protected override void PopIn() { lowPassFilter.CutoffTo(300, 100, Easing.OutCubic); diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index a85f1ecbcd..9ad532ae50 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -27,6 +27,12 @@ namespace osu.Game.Overlays public PopupDialog CurrentDialog { get; private set; } + public override bool IsPresent => Scheduler.HasPendingTasks + || dialogContainer.Children.Count > 0 + // Safety for low pass filter potentially getting stuck in applied state due to + // transforms on `this` causing children to no longer be updated. + || lowPassFilter.IsAttached; + public DialogOverlay() { AutoSizeAxes = Axes.Y; @@ -95,8 +101,6 @@ namespace osu.Game.Overlays } } - public override bool IsPresent => Scheduler.HasPendingTasks || dialogContainer.Children.Count > 0; - protected override bool BlockNonPositionalInput => true; protected override void PopIn() diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index aa62256348..aef7a0739e 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -78,8 +78,8 @@ namespace osu.Game.Screens.Play private readonly BindableDouble volumeAdjustment = new BindableDouble(1); - private AudioFilter lowPassFilter = null!; - private AudioFilter highPassFilter = null!; + private AudioFilter? lowPassFilter; + private AudioFilter? highPassFilter; private SkinnableSound sampleRestart = null!; @@ -158,7 +158,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(SessionStatics sessionStatics, AudioManager audio, OsuConfigManager config) + private void load(SessionStatics sessionStatics, OsuConfigManager config) { muteWarningShownOnce = sessionStatics.GetBindable(Static.MutedAudioNotificationShownOnce); batteryWarningShownOnce = sessionStatics.GetBindable(Static.LowBatteryNotificationShownOnce); @@ -205,8 +205,6 @@ namespace osu.Game.Screens.Play }, }, idleTracker = new IdleTracker(750), - lowPassFilter = new AudioFilter(audio.TrackMixer), - highPassFilter = new AudioFilter(audio.TrackMixer, BQFType.HighPass), sampleRestart = new SkinnableSound(new SampleInfo(@"Gameplay/restart", @"pause-retry-click")) }; @@ -284,8 +282,9 @@ namespace osu.Game.Screens.Play // stop the track before removing adjustment to avoid a volume spike. Beatmap.Value.Track.Stop(); Beatmap.Value.Track.RemoveAdjustment(AdjustableProperty.Volume, volumeAdjustment); - lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); - highPassFilter.CutoffTo(0); + + lowPassFilter?.RemoveAndDisposeImmediately(); + highPassFilter?.RemoveAndDisposeImmediately(); } public override bool OnExiting(ScreenExitEvent e) @@ -425,6 +424,12 @@ namespace osu.Game.Screens.Play settingsScroll.FadeInFromZero(500, Easing.Out) .MoveToX(0, 500, Easing.OutQuint); + AddRangeInternal(new[] + { + lowPassFilter = new AudioFilter(audioManager.TrackMixer), + highPassFilter = new AudioFilter(audioManager.TrackMixer, BQFType.HighPass), + }); + lowPassFilter.CutoffTo(1000, 650, Easing.OutQuint); highPassFilter.CutoffTo(300).Then().CutoffTo(0, 1250); // 1250 is to line up with the appearance of MetadataInfo (750 delay + 500 fade-in) @@ -437,13 +442,23 @@ namespace osu.Game.Screens.Play content.StopTracking(); content.ScaleTo(0.7f, CONTENT_OUT_DURATION * 2, Easing.OutQuint); - content.FadeOut(CONTENT_OUT_DURATION, Easing.OutQuint); + content.FadeOut(CONTENT_OUT_DURATION, Easing.OutQuint) + // Safety for filter potentially getting stuck in applied state due to + // transforms on `this` causing children to no longer be updated. + .OnComplete(_ => + { + highPassFilter?.RemoveAndDisposeImmediately(); + highPassFilter = null; + + lowPassFilter?.RemoveAndDisposeImmediately(); + lowPassFilter = null; + }); settingsScroll.FadeOut(CONTENT_OUT_DURATION, Easing.OutQuint) .MoveToX(settingsScroll.DrawWidth, CONTENT_OUT_DURATION * 2, Easing.OutQuint); - lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF, CONTENT_OUT_DURATION); - highPassFilter.CutoffTo(0, CONTENT_OUT_DURATION); + lowPassFilter?.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF, CONTENT_OUT_DURATION); + highPassFilter?.CutoffTo(0, CONTENT_OUT_DURATION); } private void pushWhenLoaded() From bfb5098238b451fc768ae855854ac9b925b57816 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 26 Feb 2024 22:13:15 +0900 Subject: [PATCH 613/915] Use high performance session during gameplay --- .../Performance/HighPerformanceSessionManager.cs | 4 ++++ osu.Game/Screens/Play/PlayerLoader.cs | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/osu.Game/Performance/HighPerformanceSessionManager.cs b/osu.Game/Performance/HighPerformanceSessionManager.cs index 8a49ba0dac..c5146933b7 100644 --- a/osu.Game/Performance/HighPerformanceSessionManager.cs +++ b/osu.Game/Performance/HighPerformanceSessionManager.cs @@ -22,6 +22,8 @@ namespace osu.Game.Performance { originalGCMode = GCSettings.LatencyMode; GCSettings.LatencyMode = GCLatencyMode.LowLatency; + + // Without doing this, the new GC mode won't kick in until the next GC, which could be at a more noticeable point in time. GC.Collect(0); } @@ -29,6 +31,8 @@ namespace osu.Game.Performance { if (GCSettings.LatencyMode == GCLatencyMode.LowLatency) GCSettings.LatencyMode = originalGCMode; + + // No GC.Collect() as we were already collecting at a higher frequency in the old mode. } } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index aa62256348..fe235dd56d 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -25,6 +25,7 @@ using osu.Game.Input; using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; +using osu.Game.Performance; using osu.Game.Screens.Menu; using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Skinning; @@ -140,6 +141,8 @@ namespace osu.Game.Screens.Play private bool quickRestart; + private IDisposable? highPerformanceSession; + [Resolved] private INotificationOverlay? notificationOverlay { get; set; } @@ -152,6 +155,9 @@ namespace osu.Game.Screens.Play [Resolved] private BatteryInfo? batteryInfo { get; set; } + [Resolved] + private HighPerformanceSessionManager? highPerformanceSessionManager { get; set; } + public PlayerLoader(Func createPlayer) { this.createPlayer = createPlayer; @@ -264,6 +270,9 @@ namespace osu.Game.Screens.Play Debug.Assert(CurrentPlayer != null); + highPerformanceSession?.Dispose(); + highPerformanceSession = null; + // prepare for a retry. CurrentPlayer = null; playerConsumed = false; @@ -304,6 +313,9 @@ namespace osu.Game.Screens.Play BackgroundBrightnessReduction = false; Beatmap.Value.Track.RemoveAdjustment(AdjustableProperty.Volume, volumeAdjustment); + highPerformanceSession?.Dispose(); + highPerformanceSession = null; + return base.OnExiting(e); } @@ -463,6 +475,10 @@ namespace osu.Game.Screens.Play if (scheduledPushPlayer != null) return; + // Now that everything's been loaded, we can safely switch to a higher performance session without incurring too much overhead. + // Doing this prior to the game being pushed gives us a bit of time to stabilise into the high performance mode before gameplay starts. + highPerformanceSession ??= highPerformanceSessionManager?.BeginSession(); + scheduledPushPlayer = Scheduler.AddDelayed(() => { // ensure that once we have reached this "point of no return", readyForPush will be false for all future checks (until a new player instance is prepared). From d6622c1756c57569f85a1b1df25f7042e7515a8a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 22:24:35 +0800 Subject: [PATCH 614/915] Add test coverage of fast menu keypresses failing to register --- .../Navigation/TestSceneButtonSystemNavigation.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs index c6d67f2bc6..43b160250c 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs @@ -28,6 +28,21 @@ namespace osu.Game.Tests.Visual.Navigation AddAssert("state is top level", () => buttons.State == ButtonSystemState.TopLevel); } + [Test] + public void TestFastShortcutKeys() + { + AddAssert("state is initial", () => buttons.State == ButtonSystemState.Initial); + + AddStep("press P three times", () => + { + InputManager.Key(Key.P); + InputManager.Key(Key.P); + InputManager.Key(Key.P); + }); + + AddAssert("entered song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect); + } + [Test] public void TestShortcutKeys() { From 4c6e8a606fbb669c5949910bc2026435180e3eb8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Feb 2024 22:22:43 +0800 Subject: [PATCH 615/915] Fix main menu eating keys if user presses too fast --- osu.Game/Screens/Menu/MainMenuButton.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index 422599a4a8..1dc79e9b1a 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -64,6 +64,10 @@ namespace osu.Game.Screens.Menu private Sample? sampleHover; private SampleChannel? sampleChannel; + public override bool IsPresent => base.IsPresent + // Allow keyboard interaction based on state rather than waiting for delayed animations. + || state == ButtonState.Expanded; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => box.ReceivePositionalInputAt(screenSpacePos); public MainMenuButton(LocalisableString text, string sampleName, IconUsage symbol, Color4 colour, Action? clickAction = null, float extraWidth = 0, params Key[] triggerKeys) From 8032ce9225950f5fc5d6dba911833e9b3f8afa93 Mon Sep 17 00:00:00 2001 From: Detze <92268414+Detze@users.noreply.github.com> Date: Mon, 26 Feb 2024 18:37:27 +0100 Subject: [PATCH 616/915] Match stable's slider border thickness perfectly --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 6bf6776617..af82a81e08 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -26,8 +26,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private const float shadow_portion = 1 - (OsuLegacySkinTransformer.LEGACY_CIRCLE_RADIUS / OsuHitObject.OBJECT_RADIUS); protected new float CalculatedBorderPortion - // Roughly matches osu!stable's slider border portions. - => base.CalculatedBorderPortion * 0.84f; + // Matches osu!stable's slider border portions. + => 0.109375f; protected override Color4 ColourAt(float position) { From 2b73d816a70fab655cdf7a9f716d6630b333ed54 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 26 Feb 2024 21:26:35 +0300 Subject: [PATCH 617/915] Bring back mod setting tracker in `BeatmapAttributesDisplay` --- osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs | 12 +++++++++++- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 7 +------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 7035af1594..c58cf710bd 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -13,6 +13,7 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -43,6 +44,8 @@ namespace osu.Game.Overlays.Mods public BindableBool Collapsed { get; } = new BindableBool(true); + private ModSettingChangeTracker? modSettingChangeTracker; + [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } = null!; @@ -97,7 +100,14 @@ namespace osu.Game.Overlays.Mods { base.LoadComplete(); - Mods.BindValueChanged(_ => updateValues()); + Mods.BindValueChanged(_ => + { + modSettingChangeTracker?.Dispose(); + modSettingChangeTracker = new ModSettingChangeTracker(Mods.Value); + modSettingChangeTracker.SettingChanged += _ => updateValues(); + updateValues(); + }, true); + BeatmapInfo.BindValueChanged(_ => updateValues()); Collapsed.BindValueChanged(_ => diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index bf43dc3d9c..b7e2f744fa 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -468,12 +468,7 @@ namespace osu.Game.Overlays.Mods } if (beatmapAttributesDisplay != null) - { - if (!ReferenceEquals(beatmapAttributesDisplay.Mods.Value, mods)) - beatmapAttributesDisplay.Mods.Value = mods; - else - beatmapAttributesDisplay.Mods.TriggerChange(); // mods list may be same but a mod setting has changed, trigger change in that case. - } + beatmapAttributesDisplay.Mods.Value = mods; } private void updateCustomisation() From 3f9fbb931849a5f6276de638e621a1e341149cc3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 26 Feb 2024 22:25:04 +0300 Subject: [PATCH 618/915] Introduce the concept of `ActiveMods` in mod select overlay and rewrite once more --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 37 +++++++++++++------ .../OnlinePlay/Match/RoomModSelectOverlay.cs | 21 +++-------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index b7e2f744fa..6b80ff6e44 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -42,6 +42,14 @@ namespace osu.Game.Overlays.Mods [Cached] public Bindable> SelectedMods { get; private set; } = new Bindable>(Array.Empty()); + /// + /// Contains a list of mods which should read from to display effects on the selected beatmap. + /// + /// + /// This is different from in screens like online-play rooms, where there are required mods activated from the playlist. + /// + public Bindable> ActiveMods { get; private set; } = new Bindable>(Array.Empty()); + /// /// Contains a dictionary with the current of all mods applicable for the current ruleset. /// @@ -313,22 +321,29 @@ namespace osu.Game.Overlays.Mods if (AllowCustomisation) ((IBindable>)modSettingsArea.SelectedMods).BindTo(SelectedMods); - SelectedMods.BindValueChanged(_ => + SelectedMods.BindValueChanged(mods => { - UpdateOverlayInformation(SelectedMods.Value); + var newMods = ActiveMods.Value.Except(mods.OldValue).Concat(mods.NewValue).ToList(); + ActiveMods.Value = newMods; + updateFromExternalSelection(); updateCustomisation(); + }, true); + + ActiveMods.BindValueChanged(_ => + { + updateOverlayInformation(); modSettingChangeTracker?.Dispose(); if (AllowCustomisation) { - // Importantly, use SelectedMods.Value here (and not the ValueChanged NewValue) as the latter can + // Importantly, use ActiveMods.Value here (and not the ValueChanged NewValue) as the latter can // potentially be stale, due to complexities in the way change trackers work. // // See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988 - modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); - modSettingChangeTracker.SettingChanged += _ => UpdateOverlayInformation(SelectedMods.Value); + modSettingChangeTracker = new ModSettingChangeTracker(ActiveMods.Value); + modSettingChangeTracker.SettingChanged += _ => updateOverlayInformation(); } }, true); @@ -451,24 +466,24 @@ namespace osu.Game.Overlays.Mods } /// - /// Updates any information displayed on the overlay regarding the effects of the selected mods. + /// Updates any information displayed on the overlay regarding the effects of the active mods. + /// This reads from instead of . /// - /// The list of mods to show effect from. This can be overriden to include effect of mods that are not part of the bindable (e.g. room mods in multiplayer/playlists). - protected virtual void UpdateOverlayInformation(IReadOnlyList mods) + private void updateOverlayInformation() { if (rankingInformationDisplay != null) { double multiplier = 1.0; - foreach (var mod in mods) + foreach (var mod in ActiveMods.Value) multiplier *= mod.ScoreMultiplier; rankingInformationDisplay.ModMultiplier.Value = multiplier; - rankingInformationDisplay.Ranked.Value = mods.All(m => m.Ranked); + rankingInformationDisplay.Ranked.Value = ActiveMods.Value.All(m => m.Ranked); } if (beatmapAttributesDisplay != null) - beatmapAttributesDisplay.Mods.Value = mods; + beatmapAttributesDisplay.Mods.Value = ActiveMods.Value; } private void updateCustomisation() diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs index db7cfe980c..d3fd6de911 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.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.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; @@ -10,7 +9,6 @@ using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; namespace osu.Game.Screens.OnlinePlay.Match { @@ -22,8 +20,6 @@ namespace osu.Game.Screens.OnlinePlay.Match [Resolved] private RulesetStore rulesets { get; set; } = null!; - private readonly List roomMods = new List(); - public RoomModSelectOverlay() : base(OverlayColourScheme.Plum) { @@ -33,22 +29,17 @@ namespace osu.Game.Screens.OnlinePlay.Match { base.LoadComplete(); - selectedItem.BindValueChanged(_ => + selectedItem.BindValueChanged(v => { - roomMods.Clear(); - - if (selectedItem.Value is PlaylistItem item) + if (v.NewValue is PlaylistItem item) { var rulesetInstance = rulesets.GetRuleset(item.RulesetID)?.CreateInstance(); Debug.Assert(rulesetInstance != null); - roomMods.AddRange(item.RequiredMods.Select(m => m.ToMod(rulesetInstance))); + ActiveMods.Value = item.RequiredMods.Select(m => m.ToMod(rulesetInstance)).Concat(SelectedMods.Value).ToList(); } - - SelectedMods.TriggerChange(); - }); + else + ActiveMods.Value = SelectedMods.Value; + }, true); } - - protected override void UpdateOverlayInformation(IReadOnlyList mods) - => base.UpdateOverlayInformation(roomMods.Concat(mods).ToList()); } } From 2151e0a2947e4c2cc4b5b071c2af1fce852359b5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 26 Feb 2024 22:25:20 +0300 Subject: [PATCH 619/915] Improve test coverage --- .../TestSceneMultiplayerMatchSubScreen.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 4bedc31f38..bdfe01ba09 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -22,6 +22,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.Dialog; using osu.Game.Overlays.Mods; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Taiko; @@ -303,7 +304,6 @@ namespace osu.Game.Tests.Visual.Multiplayer AllowedMods = new[] { new APIMod(new OsuModFlashlight()), - new APIMod(new OsuModHardRock()), } }); }); @@ -312,8 +312,14 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for join", () => RoomJoined); ClickButtonWhenEnabled(); - AddAssert("mod select shows unranked", () => this.ChildrenOfType().Single().Ranked.Value == false); - AddAssert("mod select shows different multiplier", () => !this.ChildrenOfType().Single().ModMultiplier.IsDefault); + AddAssert("mod select shows unranked", () => screen.UserModsSelectOverlay.ChildrenOfType().Single().Ranked.Value == false); + AddAssert("score multiplier = 1.20", () => screen.UserModsSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value, () => Is.EqualTo(1.2).Within(0.01)); + + AddStep("select flashlight", () => screen.UserModsSelectOverlay.ChildrenOfType().Single(m => m.Mod is ModFlashlight).TriggerClick()); + AddAssert("score multiplier = 1.35", () => screen.UserModsSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value, () => Is.EqualTo(1.35).Within(0.01)); + + AddStep("change flashlight setting", () => ((OsuModFlashlight)screen.UserModsSelectOverlay.SelectedMods.Value.Single()).FollowDelay.Value = 1200); + AddAssert("score multiplier = 1.20", () => screen.UserModsSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value, () => Is.EqualTo(1.2).Within(0.01)); } private partial class TestMultiplayerMatchSubScreen : MultiplayerMatchSubScreen From 8363c39da86b4dde7f700ebf3c3a908a4dca945e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Feb 2024 01:30:20 +0300 Subject: [PATCH 620/915] Revert "Match stable's slider border thickness perfectly" This reverts commit 8032ce9225950f5fc5d6dba911833e9b3f8afa93. --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index af82a81e08..6bf6776617 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -26,8 +26,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private const float shadow_portion = 1 - (OsuLegacySkinTransformer.LEGACY_CIRCLE_RADIUS / OsuHitObject.OBJECT_RADIUS); protected new float CalculatedBorderPortion - // Matches osu!stable's slider border portions. - => 0.109375f; + // Roughly matches osu!stable's slider border portions. + => base.CalculatedBorderPortion * 0.84f; protected override Color4 ColourAt(float position) { From e01722a266e887b6032b520ca3f0fcd0011df51e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Feb 2024 01:30:20 +0300 Subject: [PATCH 621/915] Revert "Match stable's slider border thickness more closely" This reverts commit 3502ec456d0131f4f6c1c9faabf01e6197a16ee1. --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 6bf6776617..b39092a467 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy protected new float CalculatedBorderPortion // Roughly matches osu!stable's slider border portions. - => base.CalculatedBorderPortion * 0.84f; + => base.CalculatedBorderPortion * 0.77f; protected override Color4 ColourAt(float position) { From 81e6a6d96a0f62f0ce015e232217ee8b207ea76f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Feb 2024 02:11:32 +0300 Subject: [PATCH 622/915] Rewrite `LegacySliderBody` rendering to perfectly match stable --- .../Skinning/Legacy/LegacySliderBody.cs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index b39092a467..264bb3145d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -23,29 +23,29 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private partial class LegacyDrawableSliderPath : DrawableSliderPath { - private const float shadow_portion = 1 - (OsuLegacySkinTransformer.LEGACY_CIRCLE_RADIUS / OsuHitObject.OBJECT_RADIUS); - - protected new float CalculatedBorderPortion - // Roughly matches osu!stable's slider border portions. - => base.CalculatedBorderPortion * 0.77f; - protected override Color4 ColourAt(float position) { - float realBorderPortion = shadow_portion + CalculatedBorderPortion; - float realGradientPortion = 1 - realBorderPortion; - - if (position <= shadow_portion) - return new Color4(0f, 0f, 0f, 0.25f * position / shadow_portion); - - if (position <= realBorderPortion) - return BorderColour; - - position -= realBorderPortion; + const float aa_width = 0.5f / 64f; + const float shadow_portion = 1 - (OsuLegacySkinTransformer.LEGACY_CIRCLE_RADIUS / OsuHitObject.OBJECT_RADIUS); + const float border_portion = 0.1875f; + Color4 shadow = new Color4(0, 0, 0, 0.25f); Color4 outerColour = AccentColour.Darken(0.1f); Color4 innerColour = lighten(AccentColour, 0.5f); - return LegacyUtils.InterpolateNonLinear(position / realGradientPortion, outerColour, innerColour, 0, 1); + if (position <= shadow_portion - aa_width) + return LegacyUtils.InterpolateNonLinear(position, Color4.Black.Opacity(0f), shadow, 0, shadow_portion - aa_width); + + if (position <= shadow_portion + aa_width) + return LegacyUtils.InterpolateNonLinear(position, shadow, BorderColour, shadow_portion - aa_width, shadow_portion + aa_width); + + if (position <= border_portion - aa_width) + return BorderColour; + + if (position <= border_portion + aa_width) + return LegacyUtils.InterpolateNonLinear(position, BorderColour, outerColour, border_portion - aa_width, border_portion + aa_width); + + return LegacyUtils.InterpolateNonLinear(position, outerColour, innerColour, border_portion + aa_width, 1); } /// From 2f547751826c391b765b9f0096f7f18b5649a5d8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Feb 2024 02:16:16 +0300 Subject: [PATCH 623/915] Add stable code references --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 264bb3145d..fa2b7863db 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -25,14 +25,17 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { protected override Color4 ColourAt(float position) { + // https://github.com/peppy/osu-stable-reference/blob/3ea48705eb67172c430371dcfc8a16a002ed0d3d/osu!/Graphics/Renderers/MmSliderRendererGL.cs#L99 const float aa_width = 0.5f / 64f; - const float shadow_portion = 1 - (OsuLegacySkinTransformer.LEGACY_CIRCLE_RADIUS / OsuHitObject.OBJECT_RADIUS); - const float border_portion = 0.1875f; Color4 shadow = new Color4(0, 0, 0, 0.25f); Color4 outerColour = AccentColour.Darken(0.1f); Color4 innerColour = lighten(AccentColour, 0.5f); + // https://github.com/peppy/osu-stable-reference/blob/3ea48705eb67172c430371dcfc8a16a002ed0d3d/osu!/Graphics/Renderers/MmSliderRendererGL.cs#L59-L70 + const float shadow_portion = 1 - (OsuLegacySkinTransformer.LEGACY_CIRCLE_RADIUS / OsuHitObject.OBJECT_RADIUS); + const float border_portion = 0.1875f; + if (position <= shadow_portion - aa_width) return LegacyUtils.InterpolateNonLinear(position, Color4.Black.Opacity(0f), shadow, 0, shadow_portion - aa_width); From 18e26e39feb2fb386b433595724a4970ac841617 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Feb 2024 02:20:34 +0300 Subject: [PATCH 624/915] Remove `SliderBorderSize` for simplicity --- osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs | 1 - osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs index fb31f88d3c..bda1e6cf41 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs @@ -44,7 +44,6 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default SnakingOut.BindTo(configSnakingOut); - BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? 1; BorderColour = skin.GetConfig(OsuSkinColour.SliderBorder)?.Value ?? Color4.White; } diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs index 77fea9d8f7..9685ab685d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs @@ -5,7 +5,6 @@ namespace osu.Game.Rulesets.Osu.Skinning { public enum OsuSkinConfiguration { - SliderBorderSize, SliderPathRadius, CursorCentre, CursorExpand, From 83af9dfb39d222a02fa45c726f1e50d43b27867f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Feb 2024 02:43:02 +0300 Subject: [PATCH 625/915] Fix `aa_width` being incorrect --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index fa2b7863db..a00014ab88 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy protected override Color4 ColourAt(float position) { // https://github.com/peppy/osu-stable-reference/blob/3ea48705eb67172c430371dcfc8a16a002ed0d3d/osu!/Graphics/Renderers/MmSliderRendererGL.cs#L99 - const float aa_width = 0.5f / 64f; + const float aa_width = 3f / 256f; Color4 shadow = new Color4(0, 0, 0, 0.25f); Color4 outerColour = AccentColour.Darken(0.1f); From f2d52fbaa2656b1a334d32b8142b56ff44c5bbb1 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 27 Feb 2024 17:33:24 +0900 Subject: [PATCH 626/915] Make class not overrideable --- osu.Game/OsuGame.cs | 4 +--- osu.Game/Performance/HighPerformanceSessionManager.cs | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f23a78d2dc..13e80e0707 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -792,8 +792,6 @@ namespace osu.Game protected virtual UpdateManager CreateUpdateManager() => new UpdateManager(); - protected virtual HighPerformanceSessionManager CreateHighPerformanceSessionManager() => new HighPerformanceSessionManager(); - protected override Container CreateScalingContainer() => new ScalingContainer(ScalingMode.Everything); #region Beatmap progression @@ -1088,7 +1086,7 @@ namespace osu.Game loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); - loadComponentSingleFile(CreateHighPerformanceSessionManager(), Add, true); + loadComponentSingleFile(new HighPerformanceSessionManager(), Add, true); loadComponentSingleFile(new BackgroundDataStoreProcessor(), Add); diff --git a/osu.Game/Performance/HighPerformanceSessionManager.cs b/osu.Game/Performance/HighPerformanceSessionManager.cs index c5146933b7..22c929083c 100644 --- a/osu.Game/Performance/HighPerformanceSessionManager.cs +++ b/osu.Game/Performance/HighPerformanceSessionManager.cs @@ -14,11 +14,11 @@ namespace osu.Game.Performance public IDisposable BeginSession() { - EnableHighPerformanceSession(); - return new InvokeOnDisposal(this, static m => m.DisableHighPerformanceSession()); + enableHighPerformanceSession(); + return new InvokeOnDisposal(this, static m => m.disableHighPerformanceSession()); } - protected virtual void EnableHighPerformanceSession() + private void enableHighPerformanceSession() { originalGCMode = GCSettings.LatencyMode; GCSettings.LatencyMode = GCLatencyMode.LowLatency; @@ -27,7 +27,7 @@ namespace osu.Game.Performance GC.Collect(0); } - protected virtual void DisableHighPerformanceSession() + private void disableHighPerformanceSession() { if (GCSettings.LatencyMode == GCLatencyMode.LowLatency) GCSettings.LatencyMode = originalGCMode; From dc3b41865cbf8ebb0b31f5d6d9ae042a93a14356 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 27 Feb 2024 19:17:34 +0900 Subject: [PATCH 627/915] Add logging --- osu.Game/Performance/HighPerformanceSessionManager.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Performance/HighPerformanceSessionManager.cs b/osu.Game/Performance/HighPerformanceSessionManager.cs index 22c929083c..304ab44975 100644 --- a/osu.Game/Performance/HighPerformanceSessionManager.cs +++ b/osu.Game/Performance/HighPerformanceSessionManager.cs @@ -5,6 +5,7 @@ using System; using System.Runtime; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Logging; namespace osu.Game.Performance { @@ -20,6 +21,8 @@ namespace osu.Game.Performance private void enableHighPerformanceSession() { + Logger.Log("Starting high performance session"); + originalGCMode = GCSettings.LatencyMode; GCSettings.LatencyMode = GCLatencyMode.LowLatency; @@ -29,6 +32,8 @@ namespace osu.Game.Performance private void disableHighPerformanceSession() { + Logger.Log("Ending high performance session"); + if (GCSettings.LatencyMode == GCLatencyMode.LowLatency) GCSettings.LatencyMode = originalGCMode; From 069b400dd08e21ce8e52369e5708721680b2c1f4 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 27 Feb 2024 19:36:03 +0900 Subject: [PATCH 628/915] Move manager to desktop game --- osu.Desktop/OsuGameDesktop.cs | 6 ++++++ .../Performance/HighPerformanceSessionManager.cs | 6 +++--- osu.Game/OsuGame.cs | 3 --- .../Performance/IHighPerformanceSessionManager.cs | 12 ++++++++++++ osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 5 files changed, 22 insertions(+), 7 deletions(-) rename {osu.Game => osu.Desktop}/Performance/HighPerformanceSessionManager.cs (90%) create mode 100644 osu.Game/Performance/IHighPerformanceSessionManager.cs diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index a0db896f46..5b5f5c2167 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -7,6 +7,7 @@ using System.IO; using System.Reflection; using System.Runtime.Versioning; using Microsoft.Win32; +using osu.Desktop.Performance; using osu.Desktop.Security; using osu.Framework.Platform; using osu.Game; @@ -15,9 +16,11 @@ using osu.Framework; using osu.Framework.Logging; using osu.Game.Updater; using osu.Desktop.Windows; +using osu.Framework.Allocation; using osu.Game.IO; using osu.Game.IPC; using osu.Game.Online.Multiplayer; +using osu.Game.Performance; using osu.Game.Utils; using SDL2; @@ -28,6 +31,9 @@ namespace osu.Desktop private OsuSchemeLinkIPCChannel? osuSchemeLinkIPCChannel; private ArchiveImportIPCChannel? archiveImportIPCChannel; + [Cached(typeof(IHighPerformanceSessionManager))] + private readonly HighPerformanceSessionManager highPerformanceSessionManager = new HighPerformanceSessionManager(); + public OsuGameDesktop(string[]? args = null) : base(args) { diff --git a/osu.Game/Performance/HighPerformanceSessionManager.cs b/osu.Desktop/Performance/HighPerformanceSessionManager.cs similarity index 90% rename from osu.Game/Performance/HighPerformanceSessionManager.cs rename to osu.Desktop/Performance/HighPerformanceSessionManager.cs index 304ab44975..eb2b3be5b9 100644 --- a/osu.Game/Performance/HighPerformanceSessionManager.cs +++ b/osu.Desktop/Performance/HighPerformanceSessionManager.cs @@ -4,12 +4,12 @@ using System; using System.Runtime; using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Logging; +using osu.Game.Performance; -namespace osu.Game.Performance +namespace osu.Desktop.Performance { - public partial class HighPerformanceSessionManager : Component + public class HighPerformanceSessionManager : IHighPerformanceSessionManager { private GCLatencyMode originalGCMode; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 13e80e0707..f65557c6bb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -55,7 +55,6 @@ using osu.Game.Overlays.Notifications; using osu.Game.Overlays.SkinEditor; using osu.Game.Overlays.Toolbar; using osu.Game.Overlays.Volume; -using osu.Game.Performance; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens; @@ -1086,8 +1085,6 @@ namespace osu.Game loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); - loadComponentSingleFile(new HighPerformanceSessionManager(), Add, true); - loadComponentSingleFile(new BackgroundDataStoreProcessor(), Add); Add(difficultyRecommender); diff --git a/osu.Game/Performance/IHighPerformanceSessionManager.cs b/osu.Game/Performance/IHighPerformanceSessionManager.cs new file mode 100644 index 0000000000..826a0a04f5 --- /dev/null +++ b/osu.Game/Performance/IHighPerformanceSessionManager.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Performance +{ + public interface IHighPerformanceSessionManager + { + IDisposable BeginSession(); + } +} diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index fe235dd56d..00a4a86c71 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -156,7 +156,7 @@ namespace osu.Game.Screens.Play private BatteryInfo? batteryInfo { get; set; } [Resolved] - private HighPerformanceSessionManager? highPerformanceSessionManager { get; set; } + private IHighPerformanceSessionManager? highPerformanceSessionManager { get; set; } public PlayerLoader(Func createPlayer) { From bbdd85020cc755ee75d8227468bc27c06bb67505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 27 Feb 2024 11:45:03 +0100 Subject: [PATCH 629/915] Fix slider tails sometimes not dimming correctly Originally noticed during review of another change: https://github.com/ppy/osu/pull/27369#issuecomment-1966140198. `DrawableOsuHitObject` tries to solve the initial dimming of objects by applying transform to a list of dimmable parts. For plain drawables this is safe, but if one of the parts is a DHO, it is not safe, because drawable transforms can be cleared at will. In particular, on first use of a drawable slider, `UpdateInitialTransforms()` would fire via `LoadComplete()` on the `DrawableSlider`, but *then*, also via `LoadComplete()`, the `DrawableSliderTail` would update its own state and by doing so inadvertently clear the dim transform just added by the slider. To fix, ensure dim transforms are applied to DHOs via `ApplyCustomUpdateState`. --- .../Objects/Drawables/DrawableOsuHitObject.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 5271c03e08..35cab6459b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -80,6 +80,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.UpdateInitialTransforms(); foreach (var piece in DimmablePieces) + { + // if the specified dimmable piece is a DHO, it is generally not safe to tack transforms onto it directly + // as they may be cleared via the `updateState()` DHO flow, + // so use `ApplyCustomUpdateState` instead. which does not have this pitfall. + if (piece is DrawableHitObject drawableObjectPiece) + drawableObjectPiece.ApplyCustomUpdateState += (dho, _) => applyDim(dho); + else + applyDim(piece); + } + + void applyDim(Drawable piece) { piece.FadeColour(new Color4(195, 195, 195, 255)); using (piece.BeginDelayedSequence(InitialLifetimeOffset - OsuHitWindows.MISS_WINDOW)) From 189c680555e82222bf7115305b5156cb12d3adc8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 Feb 2024 20:46:25 +0800 Subject: [PATCH 630/915] Add basic xmldoc on interface type --- .../Performance/IHighPerformanceSessionManager.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Performance/IHighPerformanceSessionManager.cs b/osu.Game/Performance/IHighPerformanceSessionManager.cs index 826a0a04f5..d3d1fda8fc 100644 --- a/osu.Game/Performance/IHighPerformanceSessionManager.cs +++ b/osu.Game/Performance/IHighPerformanceSessionManager.cs @@ -5,8 +5,19 @@ using System; namespace osu.Game.Performance { + /// + /// Allows creating a temporary "high performance" session, with the goal of optimising runtime + /// performance for gameplay purposes. + /// + /// On desktop platforms, this will set a low latency GC mode which collects more frequently to avoid + /// GC spikes. + /// public interface IHighPerformanceSessionManager { + /// + /// Start a new high performance session. + /// + /// An which will end the session when disposed. IDisposable BeginSession(); } } From 87509fbf6efc9e14979a97fdb14b5fc6b56bdf16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 27 Feb 2024 13:47:19 +0100 Subject: [PATCH 631/915] Privatise registry-related constants Don't see any reason for them to be public. --- .../Windows/WindowsAssociationManager.cs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 2a1aeba7e0..c784d52a4f 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -15,27 +15,27 @@ namespace osu.Desktop.Windows [SupportedOSPlatform("windows")] public static class WindowsAssociationManager { - public const string SOFTWARE_CLASSES = @"Software\Classes"; + private const string software_classes = @"Software\Classes"; /// /// Sub key for setting the icon. /// https://learn.microsoft.com/en-us/windows/win32/com/defaulticon /// - public const string DEFAULT_ICON = @"DefaultIcon"; + private const string default_icon = @"DefaultIcon"; /// /// Sub key for setting the command line that the shell invokes. /// https://learn.microsoft.com/en-us/windows/win32/com/shell /// - public const string SHELL_OPEN_COMMAND = @"Shell\Open\Command"; + internal const string SHELL_OPEN_COMMAND = @"Shell\Open\Command"; - public static readonly string EXE_PATH = Path.ChangeExtension(typeof(WindowsAssociationManager).Assembly.Location, ".exe").Replace('/', '\\'); + private static readonly string exe_path = Path.ChangeExtension(typeof(WindowsAssociationManager).Assembly.Location, ".exe").Replace('/', '\\'); /// /// Program ID prefix used for file associations. Should be relatively short since the full program ID has a 39 character limit, /// see https://learn.microsoft.com/en-us/windows/win32/com/-progid--key. /// - public const string PROGRAM_ID_PREFIX = "osu.File"; + private const string program_id_prefix = "osu.File"; private static readonly FileAssociation[] file_associations = { @@ -177,24 +177,24 @@ namespace osu.Desktop.Windows private record FileAssociation(string Extension, LocalisableString Description, string IconPath) { - private string programId => $@"{PROGRAM_ID_PREFIX}{Extension}"; + private string programId => $@"{program_id_prefix}{Extension}"; /// /// Installs a file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key /// public void Install() { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true); if (classes == null) return; // register a program id for the given extension using (var programKey = classes.CreateSubKey(programId)) { - using (var defaultIconKey = programKey.CreateSubKey(DEFAULT_ICON)) + using (var defaultIconKey = programKey.CreateSubKey(default_icon)) defaultIconKey.SetValue(null, IconPath); using (var openCommandKey = programKey.CreateSubKey(SHELL_OPEN_COMMAND)) - openCommandKey.SetValue(null, $@"""{EXE_PATH}"" ""%1"""); + openCommandKey.SetValue(null, $@"""{exe_path}"" ""%1"""); } using (var extensionKey = classes.CreateSubKey(Extension)) @@ -211,7 +211,7 @@ namespace osu.Desktop.Windows public void UpdateDescription(string description) { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true); if (classes == null) return; using (var programKey = classes.OpenSubKey(programId, true)) @@ -223,7 +223,7 @@ namespace osu.Desktop.Windows /// public void Uninstall() { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true); if (classes == null) return; using (var extensionKey = classes.OpenSubKey(Extension, true)) @@ -254,24 +254,24 @@ namespace osu.Desktop.Windows /// public void Install() { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true); if (classes == null) return; using (var protocolKey = classes.CreateSubKey(Protocol)) { protocolKey.SetValue(URL_PROTOCOL, string.Empty); - using (var defaultIconKey = protocolKey.CreateSubKey(DEFAULT_ICON)) + using (var defaultIconKey = protocolKey.CreateSubKey(default_icon)) defaultIconKey.SetValue(null, IconPath); using (var openCommandKey = protocolKey.CreateSubKey(SHELL_OPEN_COMMAND)) - openCommandKey.SetValue(null, $@"""{EXE_PATH}"" ""%1"""); + openCommandKey.SetValue(null, $@"""{exe_path}"" ""%1"""); } } public void UpdateDescription(string description) { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true); if (classes == null) return; using (var protocolKey = classes.OpenSubKey(Protocol, true)) @@ -280,7 +280,7 @@ namespace osu.Desktop.Windows public void Uninstall() { - using var classes = Registry.CurrentUser.OpenSubKey(SOFTWARE_CLASSES, true); + using var classes = Registry.CurrentUser.OpenSubKey(software_classes, true); classes?.DeleteSubKeyTree(Protocol, throwOnMissingSubKey: false); } } From 09dee50372f85c38a9432edd76ef3e4f7c5ad1fa Mon Sep 17 00:00:00 2001 From: Gabriel Del Nero <43073074+Gabixel@users.noreply.github.com> Date: Tue, 27 Feb 2024 15:35:51 +0100 Subject: [PATCH 632/915] Change initial scroll animation to mod columns Starting from the end (which should be fine with the current number of columns, even on different/wider screen resolutions), and with a custom decay value when it reaches zero offset. --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ce1d0d27a3..a5fc75aea3 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -341,12 +341,12 @@ namespace osu.Game.Overlays.Mods column.SearchTerm = query.NewValue; }, true); - // Start scrolled slightly to the right to give the user a sense that + // Start scrolling from the end, to give the user a sense that // there is more horizontal content available. ScheduleAfterChildren(() => { - columnScroll.ScrollTo(200, false); - columnScroll.ScrollToStart(); + columnScroll.ScrollToEnd(false); + columnScroll.ScrollTo(0, true, 0.0055); }); } From b3aa9e25d2f3ca99eda2f3e0ac6d7a3dedbd1f61 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 27 Feb 2024 23:18:11 +0300 Subject: [PATCH 633/915] Disable legacy slider AA for now --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index a00014ab88..b54bb44f94 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -26,7 +26,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy protected override Color4 ColourAt(float position) { // https://github.com/peppy/osu-stable-reference/blob/3ea48705eb67172c430371dcfc8a16a002ed0d3d/osu!/Graphics/Renderers/MmSliderRendererGL.cs#L99 - const float aa_width = 3f / 256f; + // float aaWidth = Math.Min(Math.Max(0.5f / PathRadius, 3.0f / 256.0f), 1.0f / 16.0f); + // applying the aa_width constant from stable makes sliders blurry, especially on CS>5. set to zero for now. + // this might be related to SmoothPath applying AA internally, but disabling that does not seem to have much of an effect. + const float aa_width = 0f; Color4 shadow = new Color4(0, 0, 0, 0.25f); Color4 outerColour = AccentColour.Darken(0.1f); From e053c08f6b137dcf5b62850ad5c17052780c4f71 Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 27 Feb 2024 16:23:36 -0500 Subject: [PATCH 634/915] Hide social interactions while in Do Not Disturb --- osu.Desktop/DiscordRichPresence.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 1944a73c0a..e118b3d6c0 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -95,8 +95,10 @@ namespace osu.Desktop if (activity.Value != null) { bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited; + bool hideInteractions = status.Value == UserStatus.DoNotDisturb && activity.Value is UserActivity.InLobby; + presence.State = truncate(activity.Value.GetStatus(hideIdentifiableInformation)); - presence.Details = truncate(activity.Value.GetDetails(hideIdentifiableInformation) ?? string.Empty); + presence.Details = truncate(activity.Value.GetDetails(hideIdentifiableInformation || hideInteractions) ?? string.Empty); if (getBeatmapID(activity.Value) is int beatmapId && beatmapId > 0) { From d83aeb73e4186219e1143ba7a289b02efff1c59a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 28 Feb 2024 01:02:34 +0300 Subject: [PATCH 635/915] Fix menu cursor tracing rotation while override by gameplay cursor --- osu.Game/Graphics/Cursor/MenuCursorContainer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs index 8cf47006ab..7e42d45191 100644 --- a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs @@ -220,12 +220,16 @@ namespace osu.Game.Graphics.Cursor { activeCursor.FadeTo(1, 250, Easing.OutQuint); activeCursor.ScaleTo(1, 400, Easing.OutQuint); + activeCursor.RotateTo(0, 400, Easing.OutQuint); + dragRotationState = DragRotationState.NotDragging; } protected override void PopOut() { activeCursor.FadeTo(0, 250, Easing.OutQuint); activeCursor.ScaleTo(0.6f, 250, Easing.In); + activeCursor.RotateTo(0, 400, Easing.OutQuint); + dragRotationState = DragRotationState.NotDragging; } private void playTapSample(double baseFrequency = 1f) From c69c881cd373175859d97ce5a536a8827e6a0ddb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 28 Feb 2024 07:58:02 +0300 Subject: [PATCH 636/915] Combine conditionals and remove "InLobby" check --- osu.Desktop/DiscordRichPresence.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index e118b3d6c0..f0da708766 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -94,11 +94,10 @@ namespace osu.Desktop if (activity.Value != null) { - bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited; - bool hideInteractions = status.Value == UserStatus.DoNotDisturb && activity.Value is UserActivity.InLobby; + bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; presence.State = truncate(activity.Value.GetStatus(hideIdentifiableInformation)); - presence.Details = truncate(activity.Value.GetDetails(hideIdentifiableInformation || hideInteractions) ?? string.Empty); + presence.Details = truncate(activity.Value.GetDetails(hideIdentifiableInformation) ?? string.Empty); if (getBeatmapID(activity.Value) is int beatmapId && beatmapId > 0) { From 351160f94e34712103cc7d16d2ee21ee007660a6 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 27 Feb 2024 22:41:49 -0800 Subject: [PATCH 637/915] Move back/quit button from bottom left to fail overlay when spectating --- osu.Game/Screens/Play/FailOverlay.cs | 17 +---------------- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 10 ++++++++++ osu.Game/Screens/Play/PauseOverlay.cs | 10 +--------- osu.Game/Screens/Play/Player.cs | 4 ++-- osu.Game/Screens/Play/SpectatorPlayer.cs | 2 -- 5 files changed, 14 insertions(+), 29 deletions(-) diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index 210ae5ceb6..f14cdfc213 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -6,10 +6,8 @@ using System; using System.Threading.Tasks; using osu.Game.Scoring; -using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osuTK; -using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -26,22 +24,9 @@ namespace osu.Game.Screens.Play public override LocalisableString Header => GameplayMenuOverlayStrings.FailedHeader; - private readonly bool showButtons; - - public FailOverlay(bool showButtons = true) - { - this.showButtons = showButtons; - } - [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - if (showButtons) - { - AddButton(GameplayMenuOverlayStrings.Retry, colours.YellowDark, () => OnRetry?.Invoke()); - AddButton(GameplayMenuOverlayStrings.Quit, new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); - } - // from #10339 maybe this is a better visual effect Add(new Container { diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 440b8d37b9..be4b8ff9fe 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -38,6 +38,7 @@ namespace osu.Game.Screens.Play public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + public Action? OnResume; public Action? OnRetry; public Action? OnQuit; @@ -129,6 +130,15 @@ namespace osu.Game.Screens.Play }, }; + if (OnResume != null) + AddButton(GameplayMenuOverlayStrings.Continue, colours.Green, () => OnResume.Invoke()); + + if (OnRetry != null) + AddButton(GameplayMenuOverlayStrings.Retry, colours.YellowDark, () => OnRetry.Invoke()); + + if (OnQuit != null) + AddButton(GameplayMenuOverlayStrings.Quit, new Color4(170, 27, 39, 255), () => OnQuit.Invoke()); + State.ValueChanged += _ => InternalButtons.Deselect(); updateInfoText(); diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index 2aa2793fd4..c8e8275641 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -11,18 +11,14 @@ using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Audio; -using osu.Game.Graphics; using osu.Game.Input.Bindings; using osu.Game.Localisation; using osu.Game.Skinning; -using osuTK.Graphics; namespace osu.Game.Screens.Play { public partial class PauseOverlay : GameplayMenuOverlay { - public Action OnResume; - public override bool IsPresent => base.IsPresent || pauseLoop.IsPlaying; public override LocalisableString Header => GameplayMenuOverlayStrings.PausedHeader; @@ -38,12 +34,8 @@ namespace osu.Game.Screens.Play }; [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - AddButton(GameplayMenuOverlayStrings.Continue, colours.Green, () => OnResume?.Invoke()); - AddButton(GameplayMenuOverlayStrings.Retry, colours.YellowDark, () => OnRetry?.Invoke()); - AddButton(GameplayMenuOverlayStrings.Quit, new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); - AddInternal(pauseLoop = new SkinnableSound(new SampleInfo("Gameplay/pause-loop")) { Looping = true, diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 11ff5fdbef..88f6ae9e71 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -278,10 +278,10 @@ namespace osu.Game.Screens.Play createGameplayComponents(Beatmap.Value) } }, - FailOverlay = new FailOverlay(Configuration.AllowUserInteraction) + FailOverlay = new FailOverlay { SaveReplay = async () => await prepareAndImportScoreAsync(true).ConfigureAwait(false), - OnRetry = () => Restart(), + OnRetry = Configuration.AllowUserInteraction ? () => Restart() : null, OnQuit = () => PerformExit(true), }, new HotkeyExitOverlay diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index 2faead0ee1..d1404ac184 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -25,8 +25,6 @@ namespace osu.Game.Screens.Play private readonly Score score; - public override bool AllowBackButton => true; - protected override bool CheckModsAllowFailure() { if (!allowFail) From dee57c7e72275fb87fabacbbc802775418e95185 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 27 Feb 2024 22:42:36 -0800 Subject: [PATCH 638/915] Refactor test to only allow init of actions --- .../Gameplay/TestSceneGameplayMenuOverlay.cs | 43 ++++++------------- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 6 +-- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index aa5e5985c3..73028e6df9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -3,7 +3,6 @@ #nullable disable -using System; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -26,6 +25,8 @@ namespace osu.Game.Tests.Visual.Gameplay private GlobalActionContainer globalActionContainer; + private bool triggeredRetryButton; + [BackgroundDependencyLoader] private void load(OsuGameBase game) { @@ -35,12 +36,18 @@ namespace osu.Game.Tests.Visual.Gameplay [SetUp] public void SetUp() => Schedule(() => { + triggeredRetryButton = false; + globalActionContainer.Children = new Drawable[] { pauseOverlay = new PauseOverlay { OnResume = () => Logger.Log(@"Resume"), - OnRetry = () => Logger.Log(@"Retry"), + OnRetry = () => + { + Logger.Log(@"Retry"); + triggeredRetryButton = true; + }, OnQuit = () => Logger.Log(@"Quit"), }, failOverlay = new FailOverlay @@ -224,17 +231,9 @@ namespace osu.Game.Tests.Visual.Gameplay { showOverlay(); - bool triggered = false; - AddStep("Click retry button", () => - { - var lastAction = pauseOverlay.OnRetry; - pauseOverlay.OnRetry = () => triggered = true; + AddStep("Click retry button", () => getButton(1).TriggerClick()); - getButton(1).TriggerClick(); - pauseOverlay.OnRetry = lastAction; - }); - - AddAssert("Action was triggered", () => triggered); + AddAssert("Retry was triggered", () => triggeredRetryButton); AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden); } @@ -252,25 +251,9 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.Key(Key.Down); }); - bool triggered = false; - Action lastAction = null; - AddStep("Press enter", () => - { - lastAction = pauseOverlay.OnRetry; - pauseOverlay.OnRetry = () => triggered = true; - InputManager.Key(Key.Enter); - }); + AddStep("Press enter", () => InputManager.Key(Key.Enter)); - AddAssert("Action was triggered", () => - { - if (lastAction != null) - { - pauseOverlay.OnRetry = lastAction; - lastAction = null; - } - - return triggered; - }); + AddAssert("Retry was triggered", () => triggeredRetryButton); AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden); } diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index be4b8ff9fe..da239d585e 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -38,9 +38,9 @@ namespace osu.Game.Screens.Play public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; - public Action? OnResume; - public Action? OnRetry; - public Action? OnQuit; + public Action? OnResume { get; init; } + public Action? OnRetry { get; init; } + public Action? OnQuit { get; init; } /// /// Action that is invoked when is triggered. From e8a106177771cc23112f8f42e6cc9adb725736cc Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 27 Feb 2024 23:16:20 -0800 Subject: [PATCH 639/915] Add test for spectator player exit --- osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 1c7ede2b19..caf3a05518 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -25,6 +25,7 @@ using osu.Game.Tests.Gameplay; using osu.Game.Tests.Visual.Multiplayer; using osu.Game.Tests.Visual.Spectator; using osuTK; +using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { @@ -214,6 +215,9 @@ namespace osu.Game.Tests.Visual.Gameplay checkPaused(false); // Should continue playing until out of frames checkPaused(true); // And eventually stop after running out of frames and fail. // Todo: Should check for + display a failed message. + + AddStep("exit player", () => InputManager.Key(Key.Escape)); + AddAssert("player exited", () => Stack.CurrentScreen is SoloSpectatorScreen); } [Test] From 8e462fbb38e4ffb41f3cf7cf9e7775978d03464b Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 27 Feb 2024 23:24:04 -0800 Subject: [PATCH 640/915] Apply NRT to touched files --- .../Gameplay/TestSceneGameplayMenuOverlay.cs | 8 +++----- .../Visual/Gameplay/TestSceneSpectator.cs | 20 +++++++++---------- osu.Game/Screens/Play/FailOverlay.cs | 4 +--- osu.Game/Screens/Play/PauseOverlay.cs | 4 +--- .../Screens/Play/SaveFailedScoreButton.cs | 17 ++++++++++------ osu.Game/Screens/Play/SoloSpectatorPlayer.cs | 3 +-- osu.Game/Screens/Play/SpectatorPlayer.cs | 11 ++++------ 7 files changed, 30 insertions(+), 37 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index 73028e6df9..3501c1a521 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -20,10 +18,10 @@ namespace osu.Game.Tests.Visual.Gameplay [Description("player pause/fail screens")] public partial class TestSceneGameplayMenuOverlay : OsuManualInputManagerTestScene { - private FailOverlay failOverlay; - private PauseOverlay pauseOverlay; + private FailOverlay failOverlay = null!; + private PauseOverlay pauseOverlay = null!; - private GlobalActionContainer globalActionContainer; + private GlobalActionContainer globalActionContainer = null!; private bool triggeredRetryButton; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index caf3a05518..c8356cd191 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -40,13 +38,13 @@ namespace osu.Game.Tests.Visual.Gameplay protected override bool UseOnlineAPI => true; [Resolved] - private OsuGameBase game { get; set; } + private OsuGameBase game { get; set; } = null!; private TestSpectatorClient spectatorClient => dependenciesScreen.SpectatorClient; - private DependenciesScreen dependenciesScreen; - private SoloSpectatorScreen spectatorScreen; + private DependenciesScreen dependenciesScreen = null!; + private SoloSpectatorScreen spectatorScreen = null!; - private BeatmapSetInfo importedBeatmap; + private BeatmapSetInfo importedBeatmap = null!; private int importedBeatmapId; [SetUpSteps] @@ -189,7 +187,7 @@ namespace osu.Game.Tests.Visual.Gameplay waitForPlayerCurrent(); - Player lastPlayer = null; + Player lastPlayer = null!; AddStep("store first player", () => lastPlayer = player); start(); @@ -282,7 +280,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestFinalFrameInBundleHasHeader() { - FrameDataBundle lastBundle = null; + FrameDataBundle? lastBundle = null; AddStep("bind to client", () => spectatorClient.OnNewFrames += (_, bundle) => lastBundle = bundle); @@ -291,8 +289,8 @@ namespace osu.Game.Tests.Visual.Gameplay finish(); AddUntilStep("bundle received", () => lastBundle != null); - AddAssert("first frame does not have header", () => lastBundle.Frames[0].Header == null); - AddAssert("last frame has header", () => lastBundle.Frames[^1].Header != null); + AddAssert("first frame does not have header", () => lastBundle?.Frames[0].Header == null); + AddAssert("last frame has header", () => lastBundle?.Frames[^1].Header != null); } [Test] @@ -387,7 +385,7 @@ namespace osu.Game.Tests.Visual.Gameplay } private OsuFramedReplayInputHandler replayHandler => - (OsuFramedReplayInputHandler)Stack.ChildrenOfType().First().ReplayInputHandler; + (OsuFramedReplayInputHandler)Stack.ChildrenOfType().First().ReplayInputHandler!; private Player player => this.ChildrenOfType().Single(); diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index f14cdfc213..4a0a6f573c 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Threading.Tasks; using osu.Game.Scoring; @@ -20,7 +18,7 @@ namespace osu.Game.Screens.Play { public partial class FailOverlay : GameplayMenuOverlay { - public Func> SaveReplay; + public Func>? SaveReplay; public override LocalisableString Header => GameplayMenuOverlayStrings.FailedHeader; diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index c8e8275641..3a471acba4 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -23,7 +21,7 @@ namespace osu.Game.Screens.Play public override LocalisableString Header => GameplayMenuOverlayStrings.PausedHeader; - private SkinnableSound pauseLoop; + private SkinnableSound pauseLoop = null!; protected override Action BackAction => () => { diff --git a/osu.Game/Screens/Play/SaveFailedScoreButton.cs b/osu.Game/Screens/Play/SaveFailedScoreButton.cs index b97c140250..ef27aac1b9 100644 --- a/osu.Game/Screens/Play/SaveFailedScoreButton.cs +++ b/osu.Game/Screens/Play/SaveFailedScoreButton.cs @@ -30,13 +30,13 @@ namespace osu.Game.Screens.Play private readonly Bindable state = new Bindable(); - private readonly Func> importFailedScore; + private readonly Func>? importFailedScore; private ScoreInfo? importedScore; private DownloadButton button = null!; - public SaveFailedScoreButton(Func> importFailedScore) + public SaveFailedScoreButton(Func>? importFailedScore) { Size = new Vector2(50, 30); @@ -60,11 +60,16 @@ namespace osu.Game.Screens.Play case DownloadState.NotDownloaded: state.Value = DownloadState.Importing; - Task.Run(importFailedScore).ContinueWith(t => + + if (importFailedScore != null) { - importedScore = realm.Run(r => r.Find(t.GetResultSafely().ID)?.Detach()); - Schedule(() => state.Value = importedScore != null ? DownloadState.LocallyAvailable : DownloadState.NotDownloaded); - }).FireAndForget(); + Task.Run(importFailedScore).ContinueWith(t => + { + importedScore = realm.Run(r => r.Find(t.GetResultSafely().ID)?.Detach()); + Schedule(() => state.Value = importedScore != null ? DownloadState.LocallyAvailable : DownloadState.NotDownloaded); + }).FireAndForget(); + } + break; } } diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index 8d25a0148d..3dafd5f752 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -50,8 +50,7 @@ namespace osu.Game.Screens.Play { base.Dispose(isDisposing); - if (SpectatorClient != null) - SpectatorClient.OnUserBeganPlaying -= userBeganPlaying; + SpectatorClient.OnUserBeganPlaying -= userBeganPlaying; } } } diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index d1404ac184..520fb43445 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -21,7 +19,7 @@ namespace osu.Game.Screens.Play public abstract partial class SpectatorPlayer : Player { [Resolved] - protected SpectatorClient SpectatorClient { get; private set; } + protected SpectatorClient SpectatorClient { get; private set; } = null!; private readonly Score score; @@ -35,7 +33,7 @@ namespace osu.Game.Screens.Play private bool allowFail; - protected SpectatorPlayer(Score score, PlayerConfiguration configuration = null) + protected SpectatorPlayer(Score score, PlayerConfiguration? configuration = null) : base(configuration) { this.score = score; @@ -98,7 +96,7 @@ namespace osu.Game.Screens.Play foreach (var frame in bundle.Frames) { - IConvertibleReplayFrame convertibleFrame = GameplayState.Ruleset.CreateConvertibleReplayFrame(); + IConvertibleReplayFrame convertibleFrame = GameplayState.Ruleset.CreateConvertibleReplayFrame()!; Debug.Assert(convertibleFrame != null); convertibleFrame.FromLegacy(frame, GameplayState.Beatmap); @@ -134,8 +132,7 @@ namespace osu.Game.Screens.Play { base.Dispose(isDisposing); - if (SpectatorClient != null) - SpectatorClient.OnNewFrames -= userSentFrames; + SpectatorClient.OnNewFrames -= userSentFrames; } } } From 6e03384c6bffba55b403c20cb566bf88c7252b12 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 28 Feb 2024 00:01:16 -0800 Subject: [PATCH 641/915] Apply NRT to `SoloSpectatorPlayer` --- osu.Game/Screens/Play/SoloSpectatorPlayer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index 3dafd5f752..2cc1c4a368 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Online.Spectator; From 3fb2662d74a16bf7258d0b38777e599558d214a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 28 Feb 2024 12:05:33 +0100 Subject: [PATCH 642/915] Update framework Mainly for the sake of https://github.com/ppy/osu-framework/pull/6196. --- 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 30037c868c..1b395a7c83 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index 463a726856..747d6059da 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From b5ce2642aacc33cd47879d72a18e51714936e11b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 28 Feb 2024 13:20:41 +0100 Subject: [PATCH 643/915] Fix subscribing to `ApplyCustomUpdateState` too much --- .../Objects/Drawables/DrawableOsuHitObject.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 35cab6459b..5f5deca1ba 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -85,7 +85,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // as they may be cleared via the `updateState()` DHO flow, // so use `ApplyCustomUpdateState` instead. which does not have this pitfall. if (piece is DrawableHitObject drawableObjectPiece) - drawableObjectPiece.ApplyCustomUpdateState += (dho, _) => applyDim(dho); + { + // this method can be called multiple times, and we don't want to subscribe to the event more than once, + // so this is what it is going to have to be... + drawableObjectPiece.ApplyCustomUpdateState -= applyDimToDrawableHitObject; + drawableObjectPiece.ApplyCustomUpdateState += applyDimToDrawableHitObject; + } else applyDim(piece); } @@ -96,6 +101,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables using (piece.BeginDelayedSequence(InitialLifetimeOffset - OsuHitWindows.MISS_WINDOW)) piece.FadeColour(Color4.White, 100); } + + void applyDimToDrawableHitObject(DrawableHitObject dho, ArmedState _) => applyDim(dho); } protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; From ce994a7a733eacd1bd5b1c30aacda217b071e8b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 28 Feb 2024 13:31:06 +0100 Subject: [PATCH 644/915] Fix wireframe misalignment in argon accuracy counter - Closes https://github.com/ppy/osu/issues/27385. - Supersedes / closes https://github.com/ppy/osu/pull/27392. --- osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs | 6 +++--- osu.Game/Screens/Play/HUD/ArgonComboCounter.cs | 5 ++++- .../Screens/Play/HUD/ArgonCounterTextComponent.cs | 15 ++++++++++++--- osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs | 6 ++++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs index ca00ab12c7..4cc04e1485 100644 --- a/osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs @@ -75,21 +75,21 @@ namespace osu.Game.Screens.Play.HUD AutoSizeAxes = Axes.Both, Child = wholePart = new ArgonCounterTextComponent(Anchor.TopRight, BeatmapsetsStrings.ShowScoreboardHeadersAccuracy.ToUpper()) { - RequiredDisplayDigits = { Value = 3 }, WireframeOpacity = { BindTarget = WireframeOpacity }, + WireframeTemplate = @"###", ShowLabel = { BindTarget = ShowLabel }, } }, fractionPart = new ArgonCounterTextComponent(Anchor.TopLeft) { - RequiredDisplayDigits = { Value = 2 }, WireframeOpacity = { BindTarget = WireframeOpacity }, + WireframeTemplate = @".##", Scale = new Vector2(0.5f), }, percentText = new ArgonCounterTextComponent(Anchor.TopLeft) { Text = @"%", - RequiredDisplayDigits = { Value = 1 }, + WireframeTemplate = @"#", WireframeOpacity = { BindTarget = WireframeOpacity } }, } diff --git a/osu.Game/Screens/Play/HUD/ArgonComboCounter.cs b/osu.Game/Screens/Play/HUD/ArgonComboCounter.cs index 369c753cb0..3f187650b2 100644 --- a/osu.Game/Screens/Play/HUD/ArgonComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonComboCounter.cs @@ -68,7 +68,10 @@ namespace osu.Game.Screens.Play.HUD private void updateWireframe() { - text.RequiredDisplayDigits.Value = getDigitsRequiredForDisplayCount(); + int digitsRequiredForDisplayCount = getDigitsRequiredForDisplayCount(); + + if (digitsRequiredForDisplayCount != text.WireframeTemplate.Length) + text.WireframeTemplate = new string('#', digitsRequiredForDisplayCount); } private int getDigitsRequiredForDisplayCount() diff --git a/osu.Game/Screens/Play/HUD/ArgonCounterTextComponent.cs b/osu.Game/Screens/Play/HUD/ArgonCounterTextComponent.cs index f8c82feddd..efb4d2108e 100644 --- a/osu.Game/Screens/Play/HUD/ArgonCounterTextComponent.cs +++ b/osu.Game/Screens/Play/HUD/ArgonCounterTextComponent.cs @@ -25,7 +25,6 @@ namespace osu.Game.Screens.Play.HUD private readonly OsuSpriteText labelText; public IBindable WireframeOpacity { get; } = new BindableFloat(); - public Bindable RequiredDisplayDigits { get; } = new BindableInt(); public Bindable ShowLabel { get; } = new BindableBool(); public Container NumberContainer { get; private set; } @@ -36,6 +35,18 @@ namespace osu.Game.Screens.Play.HUD set => textPart.Text = value; } + /// + /// The template for the wireframe displayed behind the . + /// Any character other than a dot is interpreted to mean a full segmented display "wireframe". + /// + public string WireframeTemplate + { + get => wireframeTemplate; + set => wireframesPart.Text = wireframeTemplate = value; + } + + private string wireframeTemplate = string.Empty; + public ArgonCounterTextComponent(Anchor anchor, LocalisableString? label = null) { Anchor = anchor; @@ -69,8 +80,6 @@ namespace osu.Game.Screens.Play.HUD } } }; - - RequiredDisplayDigits.BindValueChanged(digits => wireframesPart.Text = new string('#', digits.NewValue)); } private string textLookup(char c) diff --git a/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs b/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs index 44b9fb3123..7e0dd161dc 100644 --- a/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs @@ -58,8 +58,10 @@ namespace osu.Game.Screens.Play.HUD private void updateWireframe() { - scoreText.RequiredDisplayDigits.Value = - Math.Max(RequiredDisplayDigits.Value, getDigitsRequiredForDisplayCount()); + int digitsRequiredForDisplayCount = Math.Max(RequiredDisplayDigits.Value, getDigitsRequiredForDisplayCount()); + + if (digitsRequiredForDisplayCount != scoreText.WireframeTemplate.Length) + scoreText.WireframeTemplate = new string('#', Math.Max(RequiredDisplayDigits.Value, digitsRequiredForDisplayCount)); } private int getDigitsRequiredForDisplayCount() From f49aa4d8157eb6368263f919c662dd0afdaca1d0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 28 Feb 2024 22:01:39 +0800 Subject: [PATCH 645/915] Parse points and segments for path string --- .../Objects/Legacy/ConvertHitObjectParser.cs | 57 ++++++++++++------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index f9e32fe26f..30e4101a84 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -266,30 +266,49 @@ namespace osu.Game.Rulesets.Objects.Legacy // This code takes on the responsibility of handling explicit segments of the path ("X" & "Y" from above). Implicit segments are handled by calls to convertPoints(). string[] pointSplit = pointString.Split('|'); - var controlPoints = new List>(); - int startIndex = 0; - int endIndex = 0; - bool first = true; + Span points = stackalloc Vector2[pointSplit.Length]; + Span<(PathType Type, int StartIndex)> segments = stackalloc (PathType Type, int StartIndex)[pointSplit.Length]; + int pointsCount = 0; + int segmentsCount = 0; - while (++endIndex < pointSplit.Length) + foreach (string s in pointSplit) { - // Keep incrementing endIndex while it's not the start of a new segment (indicated by having an alpha character at position 0). - if (!char.IsLetter(pointSplit[endIndex][0])) - continue; - - // Multi-segmented sliders DON'T contain the end point as part of the current segment as it's assumed to be the start of the next segment. - // The start of the next segment is the index after the type descriptor. - string endPoint = endIndex < pointSplit.Length - 1 ? pointSplit[endIndex + 1] : null; - - controlPoints.AddRange(convertPoints(pointSplit.AsMemory().Slice(startIndex, endIndex - startIndex), endPoint, first, offset)); - startIndex = endIndex; - first = false; + if (char.IsLetter(s[0])) + { + // The start of a new segment(indicated by having an alpha character at position 0). + var pathType = convertPathType(s); + segments[segmentsCount++] = (pathType, pointsCount); + } + else + { + points[pointsCount++] = readPoint(s, offset); + } } - if (endIndex > startIndex) - controlPoints.AddRange(convertPoints(pointSplit.AsMemory().Slice(startIndex, endIndex - startIndex), null, first, offset)); + var controlPoints = new List(pointsCount); - return mergePointsLists(controlPoints); + for (int i = 0; i < segmentsCount; i++) + { + int startIndex = segments[i].StartIndex; + int endIndex = i < segmentsCount - 1 ? segments[i + 1].StartIndex : pointsCount; + Vector2? endPoint = i < segmentsCount - 1 ? points[endIndex] : null; + controlPoints.AddRange(convertPoints(segments[i].Type, points[startIndex..endIndex], endPoint)); + } + + return controlPoints.ToArray(); + + static Vector2 readPoint(string value, Vector2 startPos) + { + string[] vertexSplit = value.Split(':'); + + Vector2 pos = new Vector2((int)Parsing.ParseDouble(vertexSplit[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseDouble(vertexSplit[1], Parsing.MAX_COORDINATE_VALUE)) - startPos; + return pos; + } + } + + private IEnumerable convertPoints(PathType type, ReadOnlySpan points, Vector2? endPoint) + { + throw new NotImplementedException(); } /// From 4bff54d35dbd60aab7cd8a255977fe95e5c3bde7 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 28 Feb 2024 22:37:14 +0800 Subject: [PATCH 646/915] Add ToString on PathControlPoint for debugging --- osu.Game/Rulesets/Objects/PathControlPoint.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs index ae9fa08085..1f8e63b269 100644 --- a/osu.Game/Rulesets/Objects/PathControlPoint.cs +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -76,5 +76,9 @@ namespace osu.Game.Rulesets.Objects } public bool Equals(PathControlPoint other) => Position == other?.Position && Type == other.Type; + + public override string ToString() => type is null + ? $"Position={Position}" + : $"Position={Position}, Type={type}"; } } From fe34577ee2938c45d295800405a309ad3d55ac3e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 28 Feb 2024 22:42:08 +0800 Subject: [PATCH 647/915] Update parsing. --- .../Objects/Legacy/ConvertHitObjectParser.cs | 86 ++++++------------- 1 file changed, 24 insertions(+), 62 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 30e4101a84..2d4d2865e6 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -278,6 +278,10 @@ namespace osu.Game.Rulesets.Objects.Legacy // The start of a new segment(indicated by having an alpha character at position 0). var pathType = convertPathType(s); segments[segmentsCount++] = (pathType, pointsCount); + + // First segment is prepended by an extra zero point + if (pointsCount == 0) + points[pointsCount++] = Vector2.Zero; } else { @@ -306,47 +310,30 @@ namespace osu.Game.Rulesets.Objects.Legacy } } - private IEnumerable convertPoints(PathType type, ReadOnlySpan points, Vector2? endPoint) - { - throw new NotImplementedException(); - } - /// /// Converts a given point list into a set of path segments. /// + /// The path type of the point list. /// The point list. /// Any extra endpoint to consider as part of the points. This will NOT be returned. - /// Whether this is the first segment in the set. If true the first of the returned segments will contain a zero point. - /// The positional offset to apply to the control points. - /// The set of points contained by as one or more segments of the path, prepended by an extra zero point if is true. - private IEnumerable> convertPoints(ReadOnlyMemory points, string endPoint, bool first, Vector2 offset) + /// The set of points contained by as one or more segments of the path. + private IEnumerable convertPoints(PathType type, ReadOnlySpan points, Vector2? endPoint) { - PathType type = convertPathType(points.Span[0]); - - int readOffset = first ? 1 : 0; // First control point is zero for the first segment. - int readablePoints = points.Length - 1; // Total points readable from the base point span. - int endPointLength = endPoint != null ? 1 : 0; // Extra length if an endpoint is given that lies outside the base point span. - - var vertices = new PathControlPoint[readOffset + readablePoints + endPointLength]; - - // Fill any non-read points. - for (int i = 0; i < readOffset; i++) - vertices[i] = new PathControlPoint(); + var vertices = new PathControlPoint[points.Length]; + var result = new List(); // Parse into control points. - for (int i = 1; i < points.Length; i++) - readPoint(points.Span[i], offset, out vertices[readOffset + i - 1]); - - // If an endpoint is given, add it to the end. - if (endPoint != null) - readPoint(endPoint, offset, out vertices[^1]); + for (int i = 0; i < points.Length; i++) + vertices[i] = new PathControlPoint { Position = points[i] }; // Edge-case rules (to match stable). if (type == PathType.PERFECT_CURVE) { - if (vertices.Length != 3) + int endPointLength = endPoint is null ? 0 : 1; + + if (vertices.Length + endPointLength != 3) type = PathType.BEZIER; - else if (isLinear(vertices)) + else if (isLinear(stackalloc[] { points[0], points[1], endPoint ?? points[2] })) { // osu-stable special-cased colinear perfect curves to a linear path type = PathType.LINEAR; @@ -365,7 +352,7 @@ namespace osu.Game.Rulesets.Objects.Legacy int startIndex = 0; int endIndex = 0; - while (++endIndex < vertices.Length - endPointLength) + while (++endIndex < vertices.Length) { // Keep incrementing while an implicit segment doesn't need to be started. if (vertices[endIndex].Position != vertices[endIndex - 1].Position) @@ -378,50 +365,25 @@ namespace osu.Game.Rulesets.Objects.Legacy continue; // The last control point of each segment is not allowed to start a new implicit segment. - if (endIndex == vertices.Length - endPointLength - 1) + if (endIndex == vertices.Length - 1) continue; // Force a type on the last point, and return the current control point set as a segment. vertices[endIndex - 1].Type = type; - yield return vertices.AsMemory().Slice(startIndex, endIndex - startIndex); + for (int i = startIndex; i < endIndex; i++) + result.Add(vertices[i]); // Skip the current control point - as it's the same as the one that's just been returned. startIndex = endIndex + 1; } - if (endIndex > startIndex) - yield return vertices.AsMemory().Slice(startIndex, endIndex - startIndex); + for (int i = startIndex; i < endIndex; i++) + result.Add(vertices[i]); - static void readPoint(string value, Vector2 startPos, out PathControlPoint point) - { - string[] vertexSplit = value.Split(':'); + return result; - Vector2 pos = new Vector2((int)Parsing.ParseDouble(vertexSplit[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseDouble(vertexSplit[1], Parsing.MAX_COORDINATE_VALUE)) - startPos; - point = new PathControlPoint { Position = pos }; - } - - static bool isLinear(PathControlPoint[] p) => Precision.AlmostEquals(0, (p[1].Position.Y - p[0].Position.Y) * (p[2].Position.X - p[0].Position.X) - - (p[1].Position.X - p[0].Position.X) * (p[2].Position.Y - p[0].Position.Y)); - } - - private PathControlPoint[] mergePointsLists(List> controlPointList) - { - int totalCount = 0; - - foreach (var arr in controlPointList) - totalCount += arr.Length; - - var mergedArray = new PathControlPoint[totalCount]; - var mergedArrayMemory = mergedArray.AsMemory(); - int copyIndex = 0; - - foreach (var arr in controlPointList) - { - arr.CopyTo(mergedArrayMemory.Slice(copyIndex)); - copyIndex += arr.Length; - } - - return mergedArray; + static bool isLinear(ReadOnlySpan p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) + - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); } /// From bcb91f348d746bd4470240c23c72ec812fc54113 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 28 Feb 2024 22:51:36 +0800 Subject: [PATCH 648/915] Use ArrayPool instead of stackalloc --- .../Objects/Legacy/ConvertHitObjectParser.cs | 82 ++++++++++--------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 2d4d2865e6..a3ca719ff9 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -18,6 +18,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Legacy; using osu.Game.Skinning; using osu.Game.Utils; +using System.Buffers; namespace osu.Game.Rulesets.Objects.Legacy { @@ -266,41 +267,49 @@ namespace osu.Game.Rulesets.Objects.Legacy // This code takes on the responsibility of handling explicit segments of the path ("X" & "Y" from above). Implicit segments are handled by calls to convertPoints(). string[] pointSplit = pointString.Split('|'); - Span points = stackalloc Vector2[pointSplit.Length]; - Span<(PathType Type, int StartIndex)> segments = stackalloc (PathType Type, int StartIndex)[pointSplit.Length]; + var points = ArrayPool.Shared.Rent(pointSplit.Length); + var segments = ArrayPool<(PathType Type, int StartIndex)>.Shared.Rent(pointSplit.Length); int pointsCount = 0; int segmentsCount = 0; - - foreach (string s in pointSplit) + try { - if (char.IsLetter(s[0])) - { - // The start of a new segment(indicated by having an alpha character at position 0). - var pathType = convertPathType(s); - segments[segmentsCount++] = (pathType, pointsCount); - // First segment is prepended by an extra zero point - if (pointsCount == 0) - points[pointsCount++] = Vector2.Zero; - } - else + foreach (string s in pointSplit) { - points[pointsCount++] = readPoint(s, offset); + if (char.IsLetter(s[0])) + { + // The start of a new segment(indicated by having an alpha character at position 0). + var pathType = convertPathType(s); + segments[segmentsCount++] = (pathType, pointsCount); + + // First segment is prepended by an extra zero point + if (pointsCount == 0) + points[pointsCount++] = Vector2.Zero; + } + else + { + points[pointsCount++] = readPoint(s, offset); + } } + + var controlPoints = new List>(pointsCount); + + for (int i = 0; i < segmentsCount; i++) + { + int startIndex = segments[i].StartIndex; + int endIndex = i < segmentsCount - 1 ? segments[i + 1].StartIndex : pointsCount; + Vector2? endPoint = i < segmentsCount - 1 ? points[endIndex] : null; + controlPoints.AddRange(convertPoints(segments[i].Type, new ArraySegment(points, startIndex, endIndex - startIndex), endPoint)); + } + + return controlPoints.SelectMany(s => s).ToArray(); } - - var controlPoints = new List(pointsCount); - - for (int i = 0; i < segmentsCount; i++) + finally { - int startIndex = segments[i].StartIndex; - int endIndex = i < segmentsCount - 1 ? segments[i + 1].StartIndex : pointsCount; - Vector2? endPoint = i < segmentsCount - 1 ? points[endIndex] : null; - controlPoints.AddRange(convertPoints(segments[i].Type, points[startIndex..endIndex], endPoint)); + ArrayPool.Shared.Return(points); + ArrayPool<(PathType Type, int StartIndex)>.Shared.Return(segments); } - return controlPoints.ToArray(); - static Vector2 readPoint(string value, Vector2 startPos) { string[] vertexSplit = value.Split(':'); @@ -317,13 +326,12 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The point list. /// Any extra endpoint to consider as part of the points. This will NOT be returned. /// The set of points contained by as one or more segments of the path. - private IEnumerable convertPoints(PathType type, ReadOnlySpan points, Vector2? endPoint) + private IEnumerable> convertPoints(PathType type, ArraySegment points, Vector2? endPoint) { - var vertices = new PathControlPoint[points.Length]; - var result = new List(); + var vertices = new PathControlPoint[points.Count]; // Parse into control points. - for (int i = 0; i < points.Length; i++) + for (int i = 0; i < points.Count; i++) vertices[i] = new PathControlPoint { Position = points[i] }; // Edge-case rules (to match stable). @@ -333,7 +341,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (vertices.Length + endPointLength != 3) type = PathType.BEZIER; - else if (isLinear(stackalloc[] { points[0], points[1], endPoint ?? points[2] })) + else if (isLinear(points[0], points[1], endPoint ?? points[2])) { // osu-stable special-cased colinear perfect curves to a linear path type = PathType.LINEAR; @@ -370,20 +378,18 @@ namespace osu.Game.Rulesets.Objects.Legacy // Force a type on the last point, and return the current control point set as a segment. vertices[endIndex - 1].Type = type; - for (int i = startIndex; i < endIndex; i++) - result.Add(vertices[i]); + yield return new ArraySegment(vertices, startIndex, endIndex - startIndex); // Skip the current control point - as it's the same as the one that's just been returned. startIndex = endIndex + 1; } - for (int i = startIndex; i < endIndex; i++) - result.Add(vertices[i]); + if (startIndex < endIndex) + yield return new ArraySegment(vertices, startIndex, endIndex - startIndex); - return result; - - static bool isLinear(ReadOnlySpan p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); + static bool isLinear(Vector2 p0, Vector2 p1, Vector2 p2) + => Precision.AlmostEquals(0, (p1.Y - p0.Y) * (p2.X - p0.X) + - (p1.X - p0.X) * (p2.Y - p0.Y)); } /// From c10ba6ece9aea6d4325482563ae64fbc8261a65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 28 Feb 2024 15:59:22 +0100 Subject: [PATCH 649/915] Fix right mouse scroll clamping not going along well with padding Co-authored-by: Joseph Madamba --- osu.Game/Graphics/Containers/OsuScrollContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 124becc35a..ffd28957ef 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -127,7 +127,7 @@ namespace osu.Game.Graphics.Containers } protected virtual void ScrollFromMouseEvent(MouseEvent e) => - ScrollTo(Clamp(ToLocalSpace(e.ScreenSpaceMousePosition)[ScrollDim] / DrawSize[ScrollDim]) * Content.DrawSize[ScrollDim], true, DistanceDecayOnRightMouseScrollbar); + ScrollTo(Clamp(ToLocalSpace(e.ScreenSpaceMousePosition)[ScrollDim] / DrawSize[ScrollDim] * Content.DrawSize[ScrollDim]), true, DistanceDecayOnRightMouseScrollbar); protected override ScrollbarContainer CreateScrollbar(Direction direction) => new OsuScrollbar(direction); From 470d2be2e1b4043953e067ef91e4c997138cc0ef Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 29 Feb 2024 00:07:00 +0800 Subject: [PATCH 650/915] The overhead of LINQ is not ignorable --- .../Objects/Legacy/ConvertHitObjectParser.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index a3ca719ff9..72053648a0 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -302,7 +302,7 @@ namespace osu.Game.Rulesets.Objects.Legacy controlPoints.AddRange(convertPoints(segments[i].Type, new ArraySegment(points, startIndex, endIndex - startIndex), endPoint)); } - return controlPoints.SelectMany(s => s).ToArray(); + return mergePointsLists(controlPoints); } finally { @@ -392,6 +392,25 @@ namespace osu.Game.Rulesets.Objects.Legacy - (p1.X - p0.X) * (p2.Y - p0.Y)); } + private PathControlPoint[] mergePointsLists(List> controlPointList) + { + int totalCount = 0; + + foreach (var arr in controlPointList) + totalCount += arr.Count; + + var mergedArray = new PathControlPoint[totalCount]; + int copyIndex = 0; + + foreach (var arr in controlPointList) + { + arr.AsSpan().CopyTo(mergedArray.AsSpan(copyIndex)); + copyIndex += arr.Count; + } + + return mergedArray; + } + /// /// Creates a legacy Hit-type hit object. /// From e86ebd6cdba85e506a771aeab0fdeb0a71d74fab Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 29 Feb 2024 00:24:24 +0800 Subject: [PATCH 651/915] Fix formatting --- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 72053648a0..f042e6ba26 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -271,9 +271,9 @@ namespace osu.Game.Rulesets.Objects.Legacy var segments = ArrayPool<(PathType Type, int StartIndex)>.Shared.Rent(pointSplit.Length); int pointsCount = 0; int segmentsCount = 0; + try { - foreach (string s in pointSplit) { if (char.IsLetter(s[0])) From 5ca6e8c68a54c0341fc1e0debac5c6e3ebb9739e Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 28 Feb 2024 11:03:09 -0800 Subject: [PATCH 652/915] Fix some NRT changes --- osu.Game/Screens/Play/SoloSpectatorPlayer.cs | 4 +++- osu.Game/Screens/Play/SpectatorPlayer.cs | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index 2cc1c4a368..be83a4c6b5 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Screens; using osu.Game.Online.Spectator; using osu.Game.Scoring; @@ -48,7 +49,8 @@ namespace osu.Game.Screens.Play { base.Dispose(isDisposing); - SpectatorClient.OnUserBeganPlaying -= userBeganPlaying; + if (SpectatorClient.IsNotNull()) + SpectatorClient.OnUserBeganPlaying -= userBeganPlaying; } } } diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index 520fb43445..b2ac946642 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -1,8 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Diagnostics; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -97,7 +97,6 @@ namespace osu.Game.Screens.Play foreach (var frame in bundle.Frames) { IConvertibleReplayFrame convertibleFrame = GameplayState.Ruleset.CreateConvertibleReplayFrame()!; - Debug.Assert(convertibleFrame != null); convertibleFrame.FromLegacy(frame, GameplayState.Beatmap); var convertedFrame = (ReplayFrame)convertibleFrame; @@ -132,7 +131,8 @@ namespace osu.Game.Screens.Play { base.Dispose(isDisposing); - SpectatorClient.OnNewFrames -= userSentFrames; + if (SpectatorClient.IsNotNull()) + SpectatorClient.OnNewFrames -= userSentFrames; } } } From 232ca5778fc7fb86144f7bb74ee93ee2ac462549 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 00:09:48 +0300 Subject: [PATCH 653/915] Improve spectator fail test --- osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index c8356cd191..0de2b6a980 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -10,6 +10,7 @@ using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Osu; @@ -23,7 +24,6 @@ using osu.Game.Tests.Gameplay; using osu.Game.Tests.Visual.Multiplayer; using osu.Game.Tests.Visual.Spectator; using osuTK; -using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay { @@ -214,7 +214,9 @@ namespace osu.Game.Tests.Visual.Gameplay checkPaused(true); // And eventually stop after running out of frames and fail. // Todo: Should check for + display a failed message. - AddStep("exit player", () => InputManager.Key(Key.Escape)); + AddAssert("fail overlay present", () => player.ChildrenOfType().Single().IsPresent); + AddAssert("overlay can only quit", () => player.ChildrenOfType().Single().Buttons.Single().Text == GameplayMenuOverlayStrings.Quit); + AddStep("press quit button", () => player.ChildrenOfType().Single().Buttons.Single().TriggerClick()); AddAssert("player exited", () => Stack.CurrentScreen is SoloSpectatorScreen); } From 4a4ef91bc96c9cab11102156c429a778237cdcbf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 00:42:52 +0300 Subject: [PATCH 654/915] Simplify active mods computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 9 +++++---- .../OnlinePlay/Match/RoomModSelectOverlay.cs | 14 +++++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 6b80ff6e44..9605c0b2fe 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -104,6 +104,8 @@ namespace osu.Game.Overlays.Mods protected virtual IReadOnlyList ComputeNewModsFromSelection(IReadOnlyList oldSelection, IReadOnlyList newSelection) => newSelection; + protected virtual IReadOnlyList ComputeActiveMods() => SelectedMods.Value; + protected virtual IEnumerable CreateFooterButtons() { if (AllowCustomisation) @@ -321,13 +323,12 @@ namespace osu.Game.Overlays.Mods if (AllowCustomisation) ((IBindable>)modSettingsArea.SelectedMods).BindTo(SelectedMods); - SelectedMods.BindValueChanged(mods => + SelectedMods.BindValueChanged(_ => { - var newMods = ActiveMods.Value.Except(mods.OldValue).Concat(mods.NewValue).ToList(); - ActiveMods.Value = newMods; - updateFromExternalSelection(); updateCustomisation(); + + ActiveMods.Value = ComputeActiveMods(); }, true); ActiveMods.BindValueChanged(_ => diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs index d3fd6de911..55e077df0f 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.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.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; @@ -9,6 +10,7 @@ using osu.Game.Online.Rooms; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; namespace osu.Game.Screens.OnlinePlay.Match { @@ -20,6 +22,8 @@ namespace osu.Game.Screens.OnlinePlay.Match [Resolved] private RulesetStore rulesets { get; set; } = null!; + private readonly List roomRequiredMods = new List(); + public RoomModSelectOverlay() : base(OverlayColourScheme.Plum) { @@ -31,15 +35,19 @@ namespace osu.Game.Screens.OnlinePlay.Match selectedItem.BindValueChanged(v => { + roomRequiredMods.Clear(); + if (v.NewValue is PlaylistItem item) { var rulesetInstance = rulesets.GetRuleset(item.RulesetID)?.CreateInstance(); Debug.Assert(rulesetInstance != null); - ActiveMods.Value = item.RequiredMods.Select(m => m.ToMod(rulesetInstance)).Concat(SelectedMods.Value).ToList(); + roomRequiredMods.AddRange(item.RequiredMods.Select(m => m.ToMod(rulesetInstance))); } - else - ActiveMods.Value = SelectedMods.Value; + + ActiveMods.Value = ComputeActiveMods(); }, true); } + + protected override IReadOnlyList ComputeActiveMods() => roomRequiredMods.Concat(base.ComputeActiveMods()).ToList(); } } From c3a7e998497b136e5ca97b6729de4661cc28c2d5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 01:01:55 +0300 Subject: [PATCH 655/915] Remove unnecessary max operation --- osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs b/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs index 7e0dd161dc..a14ab3cbcd 100644 --- a/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Play.HUD int digitsRequiredForDisplayCount = Math.Max(RequiredDisplayDigits.Value, getDigitsRequiredForDisplayCount()); if (digitsRequiredForDisplayCount != scoreText.WireframeTemplate.Length) - scoreText.WireframeTemplate = new string('#', Math.Max(RequiredDisplayDigits.Value, digitsRequiredForDisplayCount)); + scoreText.WireframeTemplate = new string('#', digitsRequiredForDisplayCount); } private int getDigitsRequiredForDisplayCount() From de48c51715c072adb1ed75d7717a93e7af334e56 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 01:11:01 +0300 Subject: [PATCH 656/915] Apply renaming in remaining usages --- ...atisticsWatcher.cs => TestSceneUserStatisticsWatcher.cs} | 2 +- .../Toolbar/TransientUserStatisticsUpdateDisplay.cs | 6 +++--- osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs | 6 +++--- osu.Game/Users/UserRankPanel.cs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) rename osu.Game.Tests/Visual/Online/{TestSceneSoloStatisticsWatcher.cs => TestSceneUserStatisticsWatcher.cs} (99%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs b/osu.Game.Tests/Visual/Online/TestSceneUserStatisticsWatcher.cs similarity index 99% rename from osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs rename to osu.Game.Tests/Visual/Online/TestSceneUserStatisticsWatcher.cs index 733769b9f3..0b1f50b66f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSoloStatisticsWatcher.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserStatisticsWatcher.cs @@ -21,7 +21,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Online { [HeadlessTest] - public partial class TestSceneSoloStatisticsWatcher : OsuTestScene + public partial class TestSceneUserStatisticsWatcher : OsuTestScene { protected override bool UseOnlineAPI => false; diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index e7a78f8b80..21d91ef53f 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Toolbar private Statistic pp = null!; [BackgroundDependencyLoader] - private void load(UserStatisticsWatcher? soloStatisticsWatcher) + private void load(UserStatisticsWatcher? userStatisticsWatcher) { RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; @@ -47,8 +47,8 @@ namespace osu.Game.Overlays.Toolbar } }; - if (soloStatisticsWatcher != null) - ((IBindable)LatestUpdate).BindTo(soloStatisticsWatcher.LatestUpdate); + if (userStatisticsWatcher != null) + ((IBindable)LatestUpdate).BindTo(userStatisticsWatcher.LatestUpdate); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs index 7f8c12ddab..c37eb1914b 100644 --- a/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs @@ -28,11 +28,11 @@ namespace osu.Game.Screens.Ranking.Statistics } [BackgroundDependencyLoader] - private void load(UserStatisticsWatcher? soloStatisticsWatcher) + private void load(UserStatisticsWatcher? userStatisticsWatcher) { - if (soloStatisticsWatcher != null) + if (userStatisticsWatcher != null) { - latestGlobalStatisticsUpdate = soloStatisticsWatcher.LatestUpdate.GetBoundCopy(); + latestGlobalStatisticsUpdate = userStatisticsWatcher.LatestUpdate.GetBoundCopy(); latestGlobalStatisticsUpdate.BindValueChanged(update => { if (update.NewValue?.Score.MatchesOnlineID(achievedScore) == true) diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index b440261a4c..0d57b7bb7d 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -168,7 +168,7 @@ namespace osu.Game.Users Title = UsersStrings.ShowRankGlobalSimple, // TODO: implement highest rank tooltip // `RankHighest` resides in `APIUser`, but `api.LocalUser` doesn't update - // maybe move to `UserStatistics` in api, so `SoloStatisticsWatcher` can update the value + // maybe move to `UserStatistics` in api, so `UserStatisticsWatcher` can update the value }, countryRankDisplay = new ProfileValueDisplay(true) { From 8f97f0503f1107d06576390eb014cb5dfaed4b0b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 01:13:31 +0300 Subject: [PATCH 657/915] Move away from `Solo` namespace --- osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs | 2 +- osu.Game.Tests/Visual/Online/TestSceneUserStatisticsWatcher.cs | 2 +- osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs | 2 +- osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs | 2 +- osu.Game/Online/{Solo => }/UserStatisticsUpdate.cs | 2 +- osu.Game/Online/{Solo => }/UserStatisticsWatcher.cs | 2 +- osu.Game/OsuGame.cs | 1 - .../Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs | 2 +- osu.Game/Screens/Play/SubmittingPlayer.cs | 2 +- osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs | 2 +- osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs | 2 +- osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs | 2 +- 12 files changed, 11 insertions(+), 12 deletions(-) rename osu.Game/Online/{Solo => }/UserStatisticsUpdate.cs (97%) rename osu.Game/Online/{Solo => }/UserStatisticsWatcher.cs (99%) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs index 41ce739c2f..1a4ca65975 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarUserButton.cs @@ -8,8 +8,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; +using osu.Game.Online; using osu.Game.Online.API; -using osu.Game.Online.Solo; using osu.Game.Overlays.Toolbar; using osu.Game.Scoring; using osu.Game.Users; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserStatisticsWatcher.cs b/osu.Game.Tests/Visual/Online/TestSceneUserStatisticsWatcher.cs index 0b1f50b66f..e7ad07041c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserStatisticsWatcher.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserStatisticsWatcher.cs @@ -8,10 +8,10 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Models; +using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Solo; using osu.Game.Online.Spectator; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs b/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs index ee0ab0c880..ffc7d88a34 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneOverallRanking.cs @@ -3,7 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; -using osu.Game.Online.Solo; +using osu.Game.Online; using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics.User; using osu.Game.Users; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs index ecb8073a88..acfa519c81 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs @@ -13,7 +13,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Online.Solo; +using osu.Game.Online; using osu.Game.Rulesets; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Online/Solo/UserStatisticsUpdate.cs b/osu.Game/Online/UserStatisticsUpdate.cs similarity index 97% rename from osu.Game/Online/Solo/UserStatisticsUpdate.cs rename to osu.Game/Online/UserStatisticsUpdate.cs index 03f3abbb66..f85b219ef0 100644 --- a/osu.Game/Online/Solo/UserStatisticsUpdate.cs +++ b/osu.Game/Online/UserStatisticsUpdate.cs @@ -4,7 +4,7 @@ using osu.Game.Scoring; using osu.Game.Users; -namespace osu.Game.Online.Solo +namespace osu.Game.Online { /// /// Contains data about the change in a user's profile statistics after completing a score. diff --git a/osu.Game/Online/Solo/UserStatisticsWatcher.cs b/osu.Game/Online/UserStatisticsWatcher.cs similarity index 99% rename from osu.Game/Online/Solo/UserStatisticsWatcher.cs rename to osu.Game/Online/UserStatisticsWatcher.cs index 2fff92fe0f..af32e86ae4 100644 --- a/osu.Game/Online/Solo/UserStatisticsWatcher.cs +++ b/osu.Game/Online/UserStatisticsWatcher.cs @@ -15,7 +15,7 @@ using osu.Game.Online.Spectator; using osu.Game.Scoring; using osu.Game.Users; -namespace osu.Game.Online.Solo +namespace osu.Game.Online { /// /// A persistent component that binds to the spectator server and API in order to deliver updates about the logged in user's gameplay statistics. diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 419e31bacd..44d1e7fad6 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -47,7 +47,6 @@ using osu.Game.Localisation; using osu.Game.Online; using osu.Game.Online.Chat; using osu.Game.Online.Rooms; -using osu.Game.Online.Solo; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; using osu.Game.Overlays.Music; diff --git a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs index 21d91ef53f..c6f373d55f 100644 --- a/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs +++ b/osu.Game/Overlays/Toolbar/TransientUserStatisticsUpdateDisplay.cs @@ -13,7 +13,7 @@ using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.Solo; +using osu.Game.Online; using osu.Game.Resources.Localisation.Web; using osuTK; diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index ee88171789..62226c46dd 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -14,10 +14,10 @@ using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Database; +using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; -using osu.Game.Online.Solo; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; diff --git a/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs b/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs index 5c96a2b6c3..1e60e09486 100644 --- a/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs +++ b/osu.Game/Screens/Ranking/Statistics/User/OverallRanking.cs @@ -6,7 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.Solo; +using osu.Game.Online; namespace osu.Game.Screens.Ranking.Statistics.User { diff --git a/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs b/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs index a477f38cd1..e5f07d9891 100644 --- a/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs +++ b/osu.Game/Screens/Ranking/Statistics/User/RankingChangeRow.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Online.Solo; +using osu.Game.Online; using osu.Game.Users; using osuTK; diff --git a/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs index c37eb1914b..fa3bb1a375 100644 --- a/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/UserStatisticsPanel.cs @@ -8,7 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Extensions; -using osu.Game.Online.Solo; +using osu.Game.Online; using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics.User; From 7f5f3804f1695e130a2ab41d5e4fda092a32ed1d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 05:39:36 +0300 Subject: [PATCH 658/915] Expose beatmap storyboard as part of `GameplayState` --- osu.Game/Screens/Play/GameplayState.cs | 9 ++++++++- osu.Game/Screens/Play/Player.cs | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayState.cs b/osu.Game/Screens/Play/GameplayState.cs index cc399a0fbe..8b0207a340 100644 --- a/osu.Game/Screens/Play/GameplayState.cs +++ b/osu.Game/Screens/Play/GameplayState.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Storyboards; namespace osu.Game.Screens.Play { @@ -40,6 +41,11 @@ namespace osu.Game.Screens.Play public readonly ScoreProcessor ScoreProcessor; + /// + /// The storyboard associated with the beatmap. + /// + public readonly Storyboard Storyboard; + /// /// Whether gameplay completed without the user failing. /// @@ -62,7 +68,7 @@ namespace osu.Game.Screens.Play private readonly Bindable lastJudgementResult = new Bindable(); - public GameplayState(IBeatmap beatmap, Ruleset ruleset, IReadOnlyList? mods = null, Score? score = null, ScoreProcessor? scoreProcessor = null) + public GameplayState(IBeatmap beatmap, Ruleset ruleset, IReadOnlyList? mods = null, Score? score = null, ScoreProcessor? scoreProcessor = null, Storyboard? storyboard = null) { Beatmap = beatmap; Ruleset = ruleset; @@ -76,6 +82,7 @@ namespace osu.Game.Screens.Play }; Mods = mods ?? Array.Empty(); ScoreProcessor = scoreProcessor ?? ruleset.CreateScoreProcessor(); + Storyboard = storyboard ?? new Storyboard(); } /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 88f6ae9e71..10ada09be7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -255,7 +255,7 @@ namespace osu.Game.Screens.Play Score.ScoreInfo.Ruleset = ruleset.RulesetInfo; Score.ScoreInfo.Mods = gameplayMods; - dependencies.CacheAs(GameplayState = new GameplayState(playableBeatmap, ruleset, gameplayMods, Score, ScoreProcessor)); + dependencies.CacheAs(GameplayState = new GameplayState(playableBeatmap, ruleset, gameplayMods, Score, ScoreProcessor, Beatmap.Value.Storyboard)); var rulesetSkinProvider = new RulesetSkinProvidingContainer(ruleset, playableBeatmap, Beatmap.Value.Skin); @@ -397,7 +397,7 @@ namespace osu.Game.Screens.Play protected virtual GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart) => new MasterGameplayClockContainer(beatmap, gameplayStart); private Drawable createUnderlayComponents() => - DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard, GameplayState.Mods) { RelativeSizeAxes = Axes.Both }; + DimmableStoryboard = new DimmableStoryboard(GameplayState.Storyboard, GameplayState.Mods) { RelativeSizeAxes = Axes.Both }; private Drawable createGameplayComponents(IWorkingBeatmap working) => new ScalingContainer(ScalingMode.Gameplay) { @@ -456,7 +456,7 @@ namespace osu.Game.Screens.Play { RequestSkip = performUserRequestedSkip }, - skipOutroOverlay = new SkipOverlay(Beatmap.Value.Storyboard.LatestEventTime ?? 0) + skipOutroOverlay = new SkipOverlay(GameplayState.Storyboard.LatestEventTime ?? 0) { RequestSkip = () => progressToResults(false), Alpha = 0 @@ -1088,7 +1088,7 @@ namespace osu.Game.Screens.Play DimmableStoryboard.IsBreakTime.BindTo(breakTracker.IsBreakTime); - storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable; + storyboardReplacesBackground.Value = GameplayState.Storyboard.ReplacesBackground && GameplayState.Storyboard.HasDrawable; foreach (var mod in GameplayState.Mods.OfType()) mod.ApplyToPlayer(this); From 847a8ead4fbdd86149b10fad884ed664a94e5352 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 05:39:59 +0300 Subject: [PATCH 659/915] Hide taiko scroller when beatmap has storyboard --- .../UI/DrawableTaikoRuleset.cs | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 77b2b06c0e..ff969c3f74 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -5,6 +5,8 @@ using System; using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -22,7 +24,9 @@ using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osu.Game.Skinning; +using osu.Game.Storyboards; using osuTK; namespace osu.Game.Rulesets.Taiko.UI @@ -39,6 +43,7 @@ namespace osu.Game.Rulesets.Taiko.UI protected override bool UserScrollSpeedAdjustment => false; + [CanBeNull] private SkinnableDrawable scroller; public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) @@ -48,16 +53,24 @@ namespace osu.Game.Rulesets.Taiko.UI VisualisationMethod = ScrollVisualisationMethod.Overlapping; } - [BackgroundDependencyLoader] - private void load() + [BackgroundDependencyLoader(true)] + private void load(GameplayState gameplayState) { new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar)); - FrameStableComponents.Add(scroller = new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.Scroller), _ => Empty()) + var spriteElements = gameplayState.Storyboard.Layers.Where(l => l.Name != @"Overlay") + .SelectMany(l => l.Elements) + .OfType() + .DistinctBy(e => e.Path); + + if (spriteElements.Count() < 10) { - RelativeSizeAxes = Axes.X, - Depth = float.MaxValue - }); + FrameStableComponents.Add(scroller = new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.Scroller), _ => Empty()) + { + RelativeSizeAxes = Axes.X, + Depth = float.MaxValue, + }); + } KeyBindingInputManager.Add(new DrumTouchInputArea()); } @@ -76,7 +89,9 @@ namespace osu.Game.Rulesets.Taiko.UI base.UpdateAfterChildren(); var playfieldScreen = Playfield.ScreenSpaceDrawQuad; - scroller.Height = ToLocalSpace(playfieldScreen.TopLeft + new Vector2(0, playfieldScreen.Height / 20)).Y; + + if (scroller != null) + scroller.Height = ToLocalSpace(playfieldScreen.TopLeft + new Vector2(0, playfieldScreen.Height / 20)).Y; } public MultiplierControlPoint ControlPointAt(double time) From f28f19ed7eeee1ecacc909f0f4f35edb07c7b8cb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 29 Feb 2024 10:47:16 +0800 Subject: [PATCH 660/915] Fix method indent size Co-authored-by: Salman Ahmed --- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index f042e6ba26..db1fbe3fa4 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -389,7 +389,7 @@ namespace osu.Game.Rulesets.Objects.Legacy static bool isLinear(Vector2 p0, Vector2 p1, Vector2 p2) => Precision.AlmostEquals(0, (p1.Y - p0.Y) * (p2.X - p0.X) - - (p1.X - p0.X) * (p2.Y - p0.Y)); + - (p1.X - p0.X) * (p2.Y - p0.Y)); } private PathControlPoint[] mergePointsLists(List> controlPointList) From 4b0b0735a81aec44fe0725eac3be8ece7b733854 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 06:03:57 +0300 Subject: [PATCH 661/915] Add test coverage --- .../TestSceneTaikoPlayerScroller.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerScroller.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerScroller.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerScroller.cs new file mode 100644 index 0000000000..c2aa819c3a --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerScroller.cs @@ -0,0 +1,57 @@ +// 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.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Taiko.Skinning.Legacy; +using osu.Game.Storyboards; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public partial class TestSceneTaikoPlayerScroller : LegacySkinPlayerTestScene + { + private Storyboard? currentStoryboard; + + protected override bool HasCustomSteps => true; + + [Test] + public void TestForegroundSpritesHidesScroller() + { + AddStep("load storyboard", () => + { + currentStoryboard = new Storyboard(); + + for (int i = 0; i < 10; i++) + currentStoryboard.GetLayer("Foreground").Add(new StoryboardSprite($"test{i}", Anchor.Centre, Vector2.Zero)); + }); + + CreateTest(); + AddAssert("taiko scroller not present", () => !this.ChildrenOfType().Any()); + } + + [Test] + public void TestOverlaySpritesKeepsScroller() + { + AddStep("load storyboard", () => + { + currentStoryboard = new Storyboard(); + + for (int i = 0; i < 10; i++) + currentStoryboard.GetLayer("Overlay").Add(new StoryboardSprite($"test{i}", Anchor.Centre, Vector2.Zero)); + }); + + CreateTest(); + AddAssert("taiko scroller present", () => this.ChildrenOfType().Single().IsPresent); + } + + protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset(); + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null) + => base.CreateWorkingBeatmap(beatmap, currentStoryboard ?? storyboard); + } +} From dac8f98ea6b7d6f039d5fbe9b86b17a4303969cb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 29 Feb 2024 07:13:32 +0300 Subject: [PATCH 662/915] Fix `GameplayState` not handled as nullable --- osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index ff969c3f74..b8e76be89e 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -54,14 +54,14 @@ namespace osu.Game.Rulesets.Taiko.UI } [BackgroundDependencyLoader(true)] - private void load(GameplayState gameplayState) + private void load([CanBeNull] GameplayState gameplayState) { new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar)); - var spriteElements = gameplayState.Storyboard.Layers.Where(l => l.Name != @"Overlay") + var spriteElements = gameplayState?.Storyboard.Layers.Where(l => l.Name != @"Overlay") .SelectMany(l => l.Elements) .OfType() - .DistinctBy(e => e.Path); + .DistinctBy(e => e.Path) ?? Enumerable.Empty(); if (spriteElements.Count() < 10) { From 5495c2090a76bfd6f6a5efd0fd61530395cc6a68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Feb 2024 14:15:29 +0800 Subject: [PATCH 663/915] Add test coverage of gameplay only running forwards --- .../Visual/Gameplay/TestScenePause.cs | 66 ++++++++++++------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 73aa3be73d..030f2592ed 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -16,6 +16,7 @@ using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Rulesets; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osu.Game.Skinning; using osuTK; @@ -31,6 +32,9 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Container Content => content; + private bool gameplayClockAlwaysGoingForward = true; + private double lastForwardCheckTime; + public TestScenePause() { base.Content.Add(content = new GlobalCursorDisplay { RelativeSizeAxes = Axes.Both }); @@ -67,12 +71,20 @@ namespace osu.Game.Tests.Visual.Gameplay confirmPausedWithNoOverlay(); } + [Test] + public void TestForwardPlaybackGuarantee() + { + hookForwardPlaybackCheck(); + + AddUntilStep("wait for forward playback", () => Player.GameplayClockContainer.CurrentTime > 1000); + AddStep("seek before gameplay", () => Player.GameplayClockContainer.Seek(-5000)); + + checkForwardPlayback(); + } + [Test] public void TestPauseWithLargeOffset() { - double lastStopTime; - bool alwaysGoingForward = true; - AddStep("force large offset", () => { var offset = (BindableDouble)LocalConfig.GetBindable(OsuSetting.AudioOffset); @@ -82,25 +94,7 @@ namespace osu.Game.Tests.Visual.Gameplay offset.Value = -5000; }); - AddStep("add time forward check hook", () => - { - lastStopTime = double.MinValue; - alwaysGoingForward = true; - - Player.OnUpdate += _ => - { - var masterClock = (MasterGameplayClockContainer)Player.GameplayClockContainer; - - double currentTime = masterClock.CurrentTime; - - bool goingForward = currentTime >= lastStopTime; - - alwaysGoingForward &= goingForward; - - if (!goingForward) - Logger.Log($"Went too far backwards (last stop: {lastStopTime:N1} current: {currentTime:N1})"); - }; - }); + hookForwardPlaybackCheck(); AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10))); @@ -108,11 +102,37 @@ namespace osu.Game.Tests.Visual.Gameplay resumeAndConfirm(); - AddAssert("time didn't go too far backwards", () => alwaysGoingForward); + checkForwardPlayback(); AddStep("reset offset", () => LocalConfig.SetValue(OsuSetting.AudioOffset, 0.0)); } + private void checkForwardPlayback() => AddAssert("time didn't go too far backwards", () => gameplayClockAlwaysGoingForward); + + private void hookForwardPlaybackCheck() + { + AddStep("add time forward check hook", () => + { + lastForwardCheckTime = double.MinValue; + gameplayClockAlwaysGoingForward = true; + + Player.OnUpdate += _ => + { + var frameStableClock = Player.ChildrenOfType().Single().Clock; + + double currentTime = frameStableClock.CurrentTime; + + bool goingForward = currentTime >= lastForwardCheckTime; + lastForwardCheckTime = currentTime; + + gameplayClockAlwaysGoingForward &= goingForward; + + if (!goingForward) + Logger.Log($"Went too far backwards (last stop: {lastForwardCheckTime:N1} current: {currentTime:N1})"); + }; + }); + } + [Test] public void TestPauseResume() { From 76e8aee9ccc13637691918de7c98d0cfaa8d1a7d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Feb 2024 13:45:46 +0800 Subject: [PATCH 664/915] Disallow backwards seeks during frame stable operation when a replay is not attached --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 8c9cb262af..4011034396 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -150,6 +150,17 @@ namespace osu.Game.Rulesets.UI state = PlaybackState.NotValid; } + // This is a hotfix for https://github.com/ppy/osu/issues/26879 while we figure how the hell time is seeking + // backwards by 11,850 ms for some users during gameplay. + // + // It basically says that "while we're running in frame stable mode, and don't have a replay attached, + // time should never go backwards". If it does, we stop running gameplay until it returns to normal. + if (!hasReplayAttached && FrameStablePlayback && proposedTime > referenceClock.CurrentTime) + { + state = PlaybackState.NotValid; + return; + } + // if the proposed time is the same as the current time, assume that the clock will continue progressing in the same direction as previously. // this avoids spurious flips in direction from -1 to 1 during rewinds. if (state == PlaybackState.Valid && proposedTime != manualClock.CurrentTime) From caad89a4ddd6b773df83e46d2da9c3ac4a81f0f8 Mon Sep 17 00:00:00 2001 From: Detze <92268414+Detze@users.noreply.github.com> Date: Thu, 29 Feb 2024 07:36:35 +0100 Subject: [PATCH 665/915] Fix test failure on leap years --- .../NonVisual/Filtering/FilterQueryParserTest.cs | 2 +- osu.Game/Screens/Select/FilterQueryParser.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 12d6060351..bf888348ee 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -538,7 +538,7 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.That(filterCriteria.LastPlayed.Max, Is.Not.Null); // the parser internally references `DateTimeOffset.Now`, so to not make things too annoying for tests, just assume some tolerance // (irrelevant in proportion to the actual filter proscribed). - Assert.That(filterCriteria.LastPlayed.Min, Is.EqualTo(DateTimeOffset.Now.AddYears(-1).AddMonths(-6)).Within(TimeSpan.FromSeconds(5))); + Assert.That(filterCriteria.LastPlayed.Min, Is.EqualTo(DateTimeOffset.Now.AddMonths(-6).AddYears(-1)).Within(TimeSpan.FromSeconds(5))); Assert.That(filterCriteria.LastPlayed.Max, Is.EqualTo(DateTimeOffset.Now.AddMonths(-3)).Within(TimeSpan.FromSeconds(5))); } diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 2c4077dacf..1ee8b9bc05 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -402,19 +402,19 @@ namespace osu.Game.Screens.Select // we'll want to flip the operator, such that `>5d` means "more than five days ago", as in "*before* five days ago", // as intended by the user. case Operator.Less: - op = Operator.Greater; - break; - - case Operator.LessOrEqual: op = Operator.GreaterOrEqual; break; + case Operator.LessOrEqual: + op = Operator.Greater; + break; + case Operator.Greater: - op = Operator.Less; + op = Operator.LessOrEqual; break; case Operator.GreaterOrEqual: - op = Operator.LessOrEqual; + op = Operator.Less; break; } From 9f2ea1e936e84d092cf9d2f5733b72abb43f3553 Mon Sep 17 00:00:00 2001 From: Detze <92268414+Detze@users.noreply.github.com> Date: Thu, 29 Feb 2024 08:15:49 +0100 Subject: [PATCH 666/915] Revert incorrect change (I deserve to be shot) --- osu.Game/Screens/Select/FilterQueryParser.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 1ee8b9bc05..2c4077dacf 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -402,19 +402,19 @@ namespace osu.Game.Screens.Select // we'll want to flip the operator, such that `>5d` means "more than five days ago", as in "*before* five days ago", // as intended by the user. case Operator.Less: - op = Operator.GreaterOrEqual; - break; - - case Operator.LessOrEqual: op = Operator.Greater; break; + case Operator.LessOrEqual: + op = Operator.GreaterOrEqual; + break; + case Operator.Greater: - op = Operator.LessOrEqual; + op = Operator.Less; break; case Operator.GreaterOrEqual: - op = Operator.Less; + op = Operator.LessOrEqual; break; } From 7b28a66fc074a869d3af3f86ca2cf5c1d5e463d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 29 Feb 2024 11:11:30 +0100 Subject: [PATCH 667/915] Add failing test case --- .../TestSceneSliderInput.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 12be74c4cc..286e4bd775 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -457,6 +457,33 @@ namespace osu.Game.Rulesets.Osu.Tests assertMidSliderJudgementFail(); } + [Test] + public void TestRewindHandling() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(175, 0), Actions = { OsuAction.LeftButton }, Time = 3250 }, + new OsuReplayFrame { Position = new Vector2(175, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_end }, + }, new Slider + { + StartTime = time_slider_start, + Position = new Vector2(0, 0), + Path = new SliderPath(PathType.PERFECT_CURVE, new[] + { + Vector2.Zero, + new Vector2(250, 0), + }, 250), + }); + + AddUntilStep("wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); + AddAssert("no miss judgements recorded", () => judgementResults.All(r => r.Type.IsHit())); + + AddStep("rewind to middle of slider", () => currentPlayer.Seek(time_during_slide_4)); + AddUntilStep("wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); + AddAssert("no miss judgements recorded", () => judgementResults.All(r => r.Type.IsHit())); + } + private void assertAllMaxJudgements() { AddAssert("All judgements max", () => From 3355764a68535facc627433f7c58d1040f3928e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Feb 2024 18:21:44 +0800 Subject: [PATCH 668/915] "Fix" tests --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 4011034396..487c12830f 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; +using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; @@ -155,7 +156,7 @@ namespace osu.Game.Rulesets.UI // // It basically says that "while we're running in frame stable mode, and don't have a replay attached, // time should never go backwards". If it does, we stop running gameplay until it returns to normal. - if (!hasReplayAttached && FrameStablePlayback && proposedTime > referenceClock.CurrentTime) + if (!hasReplayAttached && FrameStablePlayback && proposedTime > referenceClock.CurrentTime && !DebugUtils.IsNUnitRunning) { state = PlaybackState.NotValid; return; From 3a780e2b676eee99f0b0e845c12348977df22695 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Feb 2024 18:27:28 +0800 Subject: [PATCH 669/915] Add logging when workaround is hit --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 487c12830f..03f3b8788f 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; using osu.Framework.Timing; using osu.Game.Input.Handlers; using osu.Game.Screens.Play; @@ -158,6 +159,7 @@ namespace osu.Game.Rulesets.UI // time should never go backwards". If it does, we stop running gameplay until it returns to normal. if (!hasReplayAttached && FrameStablePlayback && proposedTime > referenceClock.CurrentTime && !DebugUtils.IsNUnitRunning) { + Logger.Log($"Denying backwards seek during gameplay (reference: {referenceClock.CurrentTime:N2} stable: {proposedTime:N2})"); state = PlaybackState.NotValid; return; } From d05b31933fabb30da23e90cad95f3ea91ac40e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 29 Feb 2024 11:44:14 +0100 Subject: [PATCH 670/915] Fix slider tracking state not restoring correctly in all cases on rewind --- .../Objects/Drawables/SliderInputManager.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs index 148cf79337..58fa04bb4c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs @@ -5,11 +5,13 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables @@ -21,6 +23,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// public bool Tracking { get; private set; } + [Resolved] + private IGameplayClock? gameplayClock { get; set; } + + private readonly Stack<(double time, bool tracking)> trackingHistory = new Stack<(double, bool)>(); + /// /// The point in time after which we can accept any key for tracking. Before this time, we may need to restrict tracking to the key used to hit the head circle. /// @@ -208,6 +215,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// Whether the current mouse position is valid to begin tracking. private void updateTracking(bool isValidTrackingPosition) { + if (gameplayClock?.IsRewinding == true) + { + while (trackingHistory.TryPeek(out var historyEntry) && Time.Current < historyEntry.time) + trackingHistory.Pop(); + + Debug.Assert(trackingHistory.Count > 0); + + Tracking = trackingHistory.Peek().tracking; + return; + } + + bool wasTracking = Tracking; + // from the point at which the head circle is hit, this will be non-null. // it may be null if the head circle was missed. OsuAction? headCircleHitAction = getInitialHitAction(); @@ -247,6 +267,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables && isValidTrackingPosition // valid action && validTrackingAction; + + if (wasTracking != Tracking) + trackingHistory.Push((Time.Current, Tracking)); } private OsuAction? getInitialHitAction() => slider.HeadCircle?.HitAction; From 1d1db951f08731604676bcca3c470a8416e23dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 29 Feb 2024 11:54:42 +0100 Subject: [PATCH 671/915] Reset slider input manager state completely on new object application Kind of scary this wasn't happening already. Mirrors `SpinnerRotationTracker`. --- .../Objects/Drawables/SliderInputManager.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs index 58fa04bb4c..5daf8ed972 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Screens.Play; using osuTK; @@ -56,6 +57,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public SliderInputManager(DrawableSlider slider) { this.slider = slider; + this.slider.HitObjectApplied += resetState; } /// @@ -287,5 +289,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return action == OsuAction.LeftButton || action == OsuAction.RightButton; } + + private void resetState(DrawableHitObject obj) + { + Tracking = false; + trackingHistory.Clear(); + trackingHistory.Push((double.NegativeInfinity, false)); + timeToAcceptAnyKeyAfter = null; + lastPressedActions.Clear(); + screenSpaceMousePosition = null; + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + slider.HitObjectApplied -= resetState; + } } } From 876b80642357996f90e8469cc25eb1e490f1f224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 29 Feb 2024 12:11:50 +0100 Subject: [PATCH 672/915] Store tracking history to slider judgement result instead --- .../Judgements/OsuSliderJudgementResult.cs | 20 +++++++++++++++++++ .../Objects/Drawables/DrawableSlider.cs | 6 ++++++ .../Objects/Drawables/SliderInputManager.cs | 7 ++----- 3 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Judgements/OsuSliderJudgementResult.cs diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuSliderJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuSliderJudgementResult.cs new file mode 100644 index 0000000000..f52294cdd7 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Judgements/OsuSliderJudgementResult.cs @@ -0,0 +1,20 @@ +// 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 osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Osu.Judgements +{ + public class OsuSliderJudgementResult : OsuJudgementResult + { + public readonly Stack<(double time, bool tracking)> TrackingHistory = new Stack<(double, bool)>(); + + public OsuSliderJudgementResult(HitObject hitObject, Judgement judgement) + : base(hitObject, judgement) + { + TrackingHistory.Push((double.NegativeInfinity, false)); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index b7ce712e2c..e519e51562 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -14,8 +14,10 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Layout; using osu.Game.Audio; using osu.Game.Graphics.Containers; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; @@ -27,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public new Slider HitObject => (Slider)base.HitObject; + public new OsuSliderJudgementResult Result => (OsuSliderJudgementResult)base.Result; + public DrawableSliderHead HeadCircle => headContainer.Child; public DrawableSliderTail TailCircle => tailContainer.Child; @@ -134,6 +138,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, true); } + protected override JudgementResult CreateResult(Judgement judgement) => new OsuSliderJudgementResult(HitObject, judgement); + protected override void OnApply() { base.OnApply(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs index 5daf8ed972..c75ae35a1a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/SliderInputManager.cs @@ -27,8 +27,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables [Resolved] private IGameplayClock? gameplayClock { get; set; } - private readonly Stack<(double time, bool tracking)> trackingHistory = new Stack<(double, bool)>(); - /// /// The point in time after which we can accept any key for tracking. Before this time, we may need to restrict tracking to the key used to hit the head circle. /// @@ -219,6 +217,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { if (gameplayClock?.IsRewinding == true) { + var trackingHistory = slider.Result.TrackingHistory; while (trackingHistory.TryPeek(out var historyEntry) && Time.Current < historyEntry.time) trackingHistory.Pop(); @@ -271,7 +270,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables && validTrackingAction; if (wasTracking != Tracking) - trackingHistory.Push((Time.Current, Tracking)); + slider.Result.TrackingHistory.Push((Time.Current, Tracking)); } private OsuAction? getInitialHitAction() => slider.HeadCircle?.HitAction; @@ -293,8 +292,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private void resetState(DrawableHitObject obj) { Tracking = false; - trackingHistory.Clear(); - trackingHistory.Push((double.NegativeInfinity, false)); timeToAcceptAnyKeyAfter = null; lastPressedActions.Clear(); screenSpaceMousePosition = null; From a11e63b184acc5030e3d167f13d85a3691f0b7dc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 29 Feb 2024 20:02:04 +0800 Subject: [PATCH 673/915] Make the code more clear --- .../Objects/Legacy/ConvertHitObjectParser.cs | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index db1fbe3fa4..2b058d5e1f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -265,49 +265,59 @@ namespace osu.Game.Rulesets.Objects.Legacy private PathControlPoint[] convertPathString(string pointString, Vector2 offset) { // This code takes on the responsibility of handling explicit segments of the path ("X" & "Y" from above). Implicit segments are handled by calls to convertPoints(). - string[] pointSplit = pointString.Split('|'); + string[] pointStringSplit = pointString.Split('|'); - var points = ArrayPool.Shared.Rent(pointSplit.Length); - var segments = ArrayPool<(PathType Type, int StartIndex)>.Shared.Rent(pointSplit.Length); - int pointsCount = 0; - int segmentsCount = 0; + var pointsBuffer = ArrayPool.Shared.Rent(pointStringSplit.Length); + var segmentsBuffer = ArrayPool<(PathType Type, int StartIndex)>.Shared.Rent(pointStringSplit.Length); + int currentPointsIndex = 0; + int currentSegmentsIndex = 0; try { - foreach (string s in pointSplit) + foreach (string s in pointStringSplit) { if (char.IsLetter(s[0])) { // The start of a new segment(indicated by having an alpha character at position 0). var pathType = convertPathType(s); - segments[segmentsCount++] = (pathType, pointsCount); + segmentsBuffer[currentSegmentsIndex++] = (pathType, currentPointsIndex); // First segment is prepended by an extra zero point - if (pointsCount == 0) - points[pointsCount++] = Vector2.Zero; + if (currentPointsIndex == 0) + pointsBuffer[currentPointsIndex++] = Vector2.Zero; } else { - points[pointsCount++] = readPoint(s, offset); + pointsBuffer[currentPointsIndex++] = readPoint(s, offset); } } + int pointsCount = currentPointsIndex; + int segmentsCount = currentSegmentsIndex; var controlPoints = new List>(pointsCount); + var allPoints = new ArraySegment(pointsBuffer, 0, pointsCount); for (int i = 0; i < segmentsCount; i++) { - int startIndex = segments[i].StartIndex; - int endIndex = i < segmentsCount - 1 ? segments[i + 1].StartIndex : pointsCount; - Vector2? endPoint = i < segmentsCount - 1 ? points[endIndex] : null; - controlPoints.AddRange(convertPoints(segments[i].Type, new ArraySegment(points, startIndex, endIndex - startIndex), endPoint)); + if (i < segmentsCount - 1) + { + int startIndex = segmentsBuffer[i].StartIndex; + int endIndex = segmentsBuffer[i + 1].StartIndex; + controlPoints.AddRange(convertPoints(segmentsBuffer[i].Type, allPoints[startIndex..endIndex], pointsBuffer[endIndex])); + } + else + { + int startIndex = segmentsBuffer[i].StartIndex; + controlPoints.AddRange(convertPoints(segmentsBuffer[i].Type, allPoints[startIndex..], null)); + } } return mergePointsLists(controlPoints); } finally { - ArrayPool.Shared.Return(points); - ArrayPool<(PathType Type, int StartIndex)>.Shared.Return(segments); + ArrayPool.Shared.Return(pointsBuffer); + ArrayPool<(PathType, int)>.Shared.Return(segmentsBuffer); } static Vector2 readPoint(string value, Vector2 startPos) From 4184a5c1ef380318dae27492c0f68c4ba211aa0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Feb 2024 20:34:38 +0800 Subject: [PATCH 674/915] Add flag to allow backwards seeks in tests --- .../TestSceneTimingBasedNoteColouring.cs | 21 ++++++++++++------- .../NonVisual/FirstAvailableHitWindowsTest.cs | 1 + .../TestSceneCompletionCancellation.cs | 2 ++ .../TestSceneFrameStabilityContainer.cs | 3 +++ .../TestSceneGameplaySamplePlayback.cs | 2 ++ .../TestSceneGameplaySampleTriggerSource.cs | 2 ++ .../Visual/Gameplay/TestSceneHitErrorMeter.cs | 1 + .../Gameplay/TestScenePoolingRuleset.cs | 1 + .../Gameplay/TestSceneStoryboardWithOutro.cs | 2 ++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 20 ++++++++++++++++++ .../Rulesets/UI/FrameStabilityContainer.cs | 5 +++-- osu.Game/Tests/Visual/PlayerTestScene.cs | 12 ++++++++++- 12 files changed, 61 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs index 81557c198d..b5b265792b 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs @@ -34,16 +34,21 @@ namespace osu.Game.Rulesets.Mania.Tests [SetUpSteps] public void SetUpSteps() { - AddStep("setup hierarchy", () => Child = new Container + AddStep("setup hierarchy", () => { - Clock = new FramedClock(clock = new ManualClock()), - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new[] + Child = new Container { - drawableRuleset = (DrawableManiaRuleset)Ruleset.Value.CreateInstance().CreateDrawableRulesetWith(createTestBeatmap()) - } + Clock = new FramedClock(clock = new ManualClock()), + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new[] + { + drawableRuleset = (DrawableManiaRuleset)Ruleset.Value.CreateInstance().CreateDrawableRulesetWith(createTestBeatmap()) + } + }; + + drawableRuleset.AllowBackwardsSeeks = true; }); AddStep("retrieve config bindable", () => { diff --git a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs index 0bdd0ceae6..d4b69c1be2 100644 --- a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs +++ b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs @@ -100,6 +100,7 @@ namespace osu.Game.Tests.NonVisual public override Container FrameStableComponents { get; } public override IFrameStableClock FrameStableClock { get; } internal override bool FrameStablePlayback { get; set; } + public override bool AllowBackwardsSeeks { get; set; } public override IReadOnlyList Mods { get; } public override double GameplayStartTime { get; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs index 434d853992..f19f4b6690 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -29,6 +29,8 @@ namespace osu.Game.Tests.Visual.Gameplay protected override bool AllowFail => false; + protected override bool AllowBackwardsSeeks => true; + [SetUpSteps] public override void SetUpSteps() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs index 98a97e1d23..0cff675b28 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs @@ -131,6 +131,9 @@ namespace osu.Game.Tests.Visual.Gameplay private void createStabilityContainer(double gameplayStartTime = double.MinValue) => AddStep("create container", () => mainContainer.Child = new FrameStabilityContainer(gameplayStartTime) + { + AllowBackwardsSeeks = true, + } .WithChild(consumer = new ClockConsumingChild())); private void seekManualTo(double time) => AddStep($"seek manual clock to {time}", () => manualClock.CurrentTime = time); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs index 3d35860fef..057197e819 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs @@ -16,6 +16,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public partial class TestSceneGameplaySamplePlayback : PlayerTestScene { + protected override bool AllowBackwardsSeeks => true; + [Test] public void TestAllSamplesStopDuringSeek() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index 3cbd5eefac..6981591193 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -28,6 +28,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public partial class TestSceneGameplaySampleTriggerSource : PlayerTestScene { + protected override bool AllowBackwardsSeeks => true; + private TestGameplaySampleTriggerSource sampleTriggerSource = null!; protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index 56900a0549..e57177498d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -288,6 +288,7 @@ namespace osu.Game.Tests.Visual.Gameplay public override Container FrameStableComponents { get; } public override IFrameStableClock FrameStableClock { get; } internal override bool FrameStablePlayback { get; set; } + public override bool AllowBackwardsSeeks { get; set; } public override IReadOnlyList Mods { get; } public override double GameplayStartTime { get; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs index b567e8de8d..88effb4a7b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs @@ -269,6 +269,7 @@ namespace osu.Game.Tests.Visual.Gameplay drawableRuleset = (TestDrawablePoolingRuleset)ruleset.CreateDrawableRulesetWith(CreateWorkingBeatmap(beatmap).GetPlayableBeatmap(ruleset.RulesetInfo)); drawableRuleset.FrameStablePlayback = true; + drawableRuleset.AllowBackwardsSeeks = true; drawableRuleset.PoolSize = poolSize; Child = new Container diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 98825b27d4..f532921d63 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -31,6 +31,8 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override bool HasCustomSteps => true; + protected override bool AllowBackwardsSeeks => true; + protected new OutroPlayer Player => (OutroPlayer)base.Player; private double currentBeatmapDuration; diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 4aeb3d4862..13e28279e6 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -81,6 +81,19 @@ namespace osu.Game.Rulesets.UI public override IFrameStableClock FrameStableClock => frameStabilityContainer; + private bool allowBackwardsSeeks; + + public override bool AllowBackwardsSeeks + { + get => allowBackwardsSeeks; + set + { + allowBackwardsSeeks = value; + if (frameStabilityContainer != null) + frameStabilityContainer.AllowBackwardsSeeks = value; + } + } + private bool frameStablePlayback = true; internal override bool FrameStablePlayback @@ -178,6 +191,7 @@ namespace osu.Game.Rulesets.UI InternalChild = frameStabilityContainer = new FrameStabilityContainer(GameplayStartTime) { FrameStablePlayback = FrameStablePlayback, + AllowBackwardsSeeks = AllowBackwardsSeeks, Children = new Drawable[] { FrameStableComponents, @@ -463,6 +477,12 @@ namespace osu.Game.Rulesets.UI /// internal abstract bool FrameStablePlayback { get; set; } + /// + /// When a replay is not attached, we usually block any backwards seeks. + /// This will bypass the check. Should only be used for tests. + /// + public abstract bool AllowBackwardsSeeks { get; set; } + /// /// The mods which are to be applied. /// diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 03f3b8788f..ab48711955 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; -using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Logging; @@ -26,6 +25,8 @@ namespace osu.Game.Rulesets.UI { public ReplayInputHandler? ReplayInputHandler { get; set; } + public bool AllowBackwardsSeeks { get; set; } + /// /// The number of CPU milliseconds to spend at most during seek catch-up. /// @@ -157,7 +158,7 @@ namespace osu.Game.Rulesets.UI // // It basically says that "while we're running in frame stable mode, and don't have a replay attached, // time should never go backwards". If it does, we stop running gameplay until it returns to normal. - if (!hasReplayAttached && FrameStablePlayback && proposedTime > referenceClock.CurrentTime && !DebugUtils.IsNUnitRunning) + if (!hasReplayAttached && FrameStablePlayback && proposedTime > referenceClock.CurrentTime && !AllowBackwardsSeeks) { Logger.Log($"Denying backwards seek during gameplay (reference: {referenceClock.CurrentTime:N2} stable: {proposedTime:N2})"); state = PlaybackState.NotValid; diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index ee184c1f35..43d779261c 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -70,10 +70,20 @@ namespace osu.Game.Tests.Visual AddStep($"Load player for {CreatePlayerRuleset().Description}", LoadPlayer); AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1); + + if (AllowBackwardsSeeks) + { + AddStep("allow backwards seeking", () => + { + Player.DrawableRuleset.AllowBackwardsSeeks = AllowBackwardsSeeks; + }); + } } protected virtual bool AllowFail => false; + protected virtual bool AllowBackwardsSeeks => false; + protected virtual bool Autoplay => false; protected void LoadPlayer() => LoadPlayer(Array.Empty()); @@ -126,6 +136,6 @@ namespace osu.Game.Tests.Visual protected sealed override Ruleset CreateRuleset() => CreatePlayerRuleset(); - protected virtual TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false); + protected virtual TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false, AllowBackwardsSeeks); } } From cc8b838bd45d5df2be723b6cb1ddd82bec5622b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Feb 2024 23:03:27 +0800 Subject: [PATCH 675/915] Add comprehensive log output to help figure out problematic clocks --- osu.Game/Beatmaps/FramedBeatmapClock.cs | 26 ++++++++++++++++++- .../Rulesets/UI/FrameStabilityContainer.cs | 7 +++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/FramedBeatmapClock.cs b/osu.Game/Beatmaps/FramedBeatmapClock.cs index 49dff96ff1..af7be235fc 100644 --- a/osu.Game/Beatmaps/FramedBeatmapClock.cs +++ b/osu.Game/Beatmaps/FramedBeatmapClock.cs @@ -38,6 +38,7 @@ namespace osu.Game.Beatmaps private IDisposable? beatmapOffsetSubscription; private readonly DecouplingFramedClock decoupledTrack; + private readonly InterpolatingFramedClock interpolatedTrack; [Resolved] private OsuConfigManager config { get; set; } = null!; @@ -58,7 +59,7 @@ namespace osu.Game.Beatmaps // An interpolating clock is used to ensure precise time values even when the host audio subsystem is not reporting // high precision times (on windows there's generally only 5-10ms reporting intervals, as an example). - var interpolatedTrack = new InterpolatingFramedClock(decoupledTrack); + interpolatedTrack = new InterpolatingFramedClock(decoupledTrack); if (applyOffsets) { @@ -190,5 +191,28 @@ namespace osu.Game.Beatmaps base.Dispose(isDisposing); beatmapOffsetSubscription?.Dispose(); } + + public string GetSnapshot() + { + return + $"originalSource: {output(Source)}\n" + + $"userGlobalOffsetClock: {output(userGlobalOffsetClock)}\n" + + $"platformOffsetClock: {output(platformOffsetClock)}\n" + + $"userBeatmapOffsetClock: {output(userBeatmapOffsetClock)}\n" + + $"interpolatedTrack: {output(interpolatedTrack)}\n" + + $"decoupledTrack: {output(decoupledTrack)}\n" + + $"finalClockSource: {output(finalClockSource)}\n"; + + string output(IClock? clock) + { + if (clock == null) + return "null"; + + if (clock is IFrameBasedClock framed) + return $"current: {clock.CurrentTime:N2} running: {clock.IsRunning} rate: {clock.Rate} elapsed: {framed.ElapsedFrameTime:N2}"; + + return $"current: {clock.CurrentTime:N2} running: {clock.IsRunning} rate: {clock.Rate}"; + } + } } } diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index ab48711955..c09018e8ca 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -3,13 +3,16 @@ using System; using System.Diagnostics; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Logging; +using osu.Framework.Testing; using osu.Framework.Timing; +using osu.Game.Beatmaps; using osu.Game.Input.Handlers; using osu.Game.Screens.Play; @@ -161,6 +164,10 @@ namespace osu.Game.Rulesets.UI if (!hasReplayAttached && FrameStablePlayback && proposedTime > referenceClock.CurrentTime && !AllowBackwardsSeeks) { Logger.Log($"Denying backwards seek during gameplay (reference: {referenceClock.CurrentTime:N2} stable: {proposedTime:N2})"); + + if (parentGameplayClock is GameplayClockContainer gcc) + Logger.Log($"{gcc.ChildrenOfType().Single().GetSnapshot()}"); + state = PlaybackState.NotValid; return; } From 59b9d29a79c2520cda4b1fca7d2b8373e501c71d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Feb 2024 23:29:50 +0800 Subject: [PATCH 676/915] Fix formatting? --- .../Visual/Gameplay/TestSceneFrameStabilityContainer.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs index 0cff675b28..c2999e3f5a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs @@ -130,11 +130,12 @@ namespace osu.Game.Tests.Visual.Gameplay } private void createStabilityContainer(double gameplayStartTime = double.MinValue) => AddStep("create container", () => + { mainContainer.Child = new FrameStabilityContainer(gameplayStartTime) - { - AllowBackwardsSeeks = true, - } - .WithChild(consumer = new ClockConsumingChild())); + { + AllowBackwardsSeeks = true, + }.WithChild(consumer = new ClockConsumingChild()); + }); private void seekManualTo(double time) => AddStep($"seek manual clock to {time}", () => manualClock.CurrentTime = time); From eb0933c3a5aa2de47820d020d34cabaf7552e7e6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 29 Feb 2024 20:35:20 +0300 Subject: [PATCH 677/915] Fix allocations in EffectPointVisualisation --- .../Summary/Parts/EffectPointVisualisation.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs index d92beba38a..bf87470e01 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.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.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -53,7 +52,18 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts // for changes. ControlPointInfo needs a refactor to make this flow better, but it should do for now. Scheduler.AddDelayed(() => { - var next = beatmap.ControlPointInfo.EffectPoints.FirstOrDefault(c => c.Time > effect.Time); + EffectControlPoint? next = null; + + for (int i = 0; i < beatmap.ControlPointInfo.EffectPoints.Count; i++) + { + var point = beatmap.ControlPointInfo.EffectPoints[i]; + + if (point.Time > effect.Time) + { + next = point; + break; + } + } if (!ReferenceEquals(nextControlPoint, next)) { From 61cc5d6f29606c3513f6c5b699849ef155be2f1f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Mar 2024 11:24:12 +0800 Subject: [PATCH 678/915] Fix typos in xmldoc --- osu.Desktop/Windows/WindowsAssociationManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index c784d52a4f..181403d287 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -180,7 +180,7 @@ namespace osu.Desktop.Windows private string programId => $@"{program_id_prefix}{Extension}"; /// - /// Installs a file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key + /// Installs a file extension association in accordance with https://learn.microsoft.com/en-us/windows/win32/com/-progid--key /// public void Install() { @@ -219,7 +219,7 @@ namespace osu.Desktop.Windows } /// - /// Uninstalls the file extenstion association in accordance with https://learn.microsoft.com/en-us/windows/win32/shell/fa-file-types#deleting-registry-information-during-uninstallation + /// Uninstalls the file extension association in accordance with https://learn.microsoft.com/en-us/windows/win32/shell/fa-file-types#deleting-registry-information-during-uninstallation /// public void Uninstall() { From 00527da27d97ceba51f6d8bd46f4ec94542916a5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Mar 2024 11:42:35 +0800 Subject: [PATCH 679/915] When discord is set to privacy mode, don't show beatmap being edited --- osu.Game/Users/UserActivity.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 1b09666df6..404ed141b9 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -151,7 +151,11 @@ namespace osu.Game.Users public EditingBeatmap() { } public override string GetStatus(bool hideIdentifiableInformation = false) => @"Editing a beatmap"; - public override string GetDetails(bool hideIdentifiableInformation = false) => BeatmapDisplayTitle; + + public override string GetDetails(bool hideIdentifiableInformation = false) => hideIdentifiableInformation + // For now let's assume that showing the beatmap a user is editing could reveal unwanted information. + ? string.Empty + : BeatmapDisplayTitle; } [MessagePackObject] From 4ad8bbb9e2d17c6c35fb26f37004c077af87dddf Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 1 Mar 2024 13:20:37 +0900 Subject: [PATCH 680/915] remove useless DrawablePool --- osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 0f2f9dc323..8bb5ee3617 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -107,8 +107,6 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters JudgementSpacing.BindValueChanged(_ => updateMetrics(), true); } - private readonly DrawablePool judgementLinePool = new DrawablePool(50); - public void Push(HitErrorShape shape) { Add(shape); From 19ed78eef57828c1da4210e5796bd5e7b7fcdb48 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Mar 2024 12:34:21 +0800 Subject: [PATCH 681/915] Log backwards seeks to sentry --- osu.Game/OsuGame.cs | 3 +++ .../Rulesets/UI/FrameStabilityContainer.cs | 15 ++++++++++--- .../Utils/SentryOnlyDiagnosticsException.cs | 21 +++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Utils/SentryOnlyDiagnosticsException.cs diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7d128a808a..eb1219f183 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1190,6 +1190,9 @@ namespace osu.Game { if (entry.Level < LogLevel.Important || entry.Target > LoggingTarget.Database || entry.Target == null) return; + if (entry.Exception is SentryOnlyDiagnosticsException) + return; + const int short_term_display_limit = 3; if (recentLogCount < short_term_display_limit) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index c09018e8ca..884310e44c 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -15,6 +15,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Input.Handlers; using osu.Game.Screens.Play; +using osu.Game.Utils; namespace osu.Game.Rulesets.UI { @@ -29,6 +30,7 @@ namespace osu.Game.Rulesets.UI public ReplayInputHandler? ReplayInputHandler { get; set; } public bool AllowBackwardsSeeks { get; set; } + private double? lastBackwardsSeekLogTime; /// /// The number of CPU milliseconds to spend at most during seek catch-up. @@ -163,10 +165,17 @@ namespace osu.Game.Rulesets.UI // time should never go backwards". If it does, we stop running gameplay until it returns to normal. if (!hasReplayAttached && FrameStablePlayback && proposedTime > referenceClock.CurrentTime && !AllowBackwardsSeeks) { - Logger.Log($"Denying backwards seek during gameplay (reference: {referenceClock.CurrentTime:N2} stable: {proposedTime:N2})"); + if (lastBackwardsSeekLogTime == null || Math.Abs(Clock.CurrentTime - lastBackwardsSeekLogTime.Value) > 1000) + { + lastBackwardsSeekLogTime = Clock.CurrentTime; - if (parentGameplayClock is GameplayClockContainer gcc) - Logger.Log($"{gcc.ChildrenOfType().Single().GetSnapshot()}"); + string loggableContent = $"Denying backwards seek during gameplay (reference: {referenceClock.CurrentTime:N2} stable: {proposedTime:N2})"; + + if (parentGameplayClock is GameplayClockContainer gcc) + loggableContent += $"\n{gcc.ChildrenOfType().Single().GetSnapshot()}"; + + Logger.Error(new SentryOnlyDiagnosticsException("backwards seek"), loggableContent); + } state = PlaybackState.NotValid; return; diff --git a/osu.Game/Utils/SentryOnlyDiagnosticsException.cs b/osu.Game/Utils/SentryOnlyDiagnosticsException.cs new file mode 100644 index 0000000000..1659b8a213 --- /dev/null +++ b/osu.Game/Utils/SentryOnlyDiagnosticsException.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Utils +{ + /// + /// Log to sentry without showing an error notification to the user. + /// + /// + /// This can be used to convey important diagnostics to us developers without + /// getting in the user's way. Should be used sparingly. + internal class SentryOnlyDiagnosticsException : Exception + { + public SentryOnlyDiagnosticsException(string message) + : base(message) + { + } + } +} From 060e17e9898256128632ab1a524ab33c87d0b9c2 Mon Sep 17 00:00:00 2001 From: jvyden Date: Thu, 29 Feb 2024 19:57:32 -0500 Subject: [PATCH 682/915] Support Discord game invites in multiplayer lobbies --- osu.Desktop/DiscordRichPresence.cs | 83 +++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index f0da708766..b85abdb4fe 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -9,10 +9,13 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Logging; +using osu.Game; using osu.Game.Configuration; using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Users; using LogLevel = osu.Framework.Logging.LogLevel; @@ -22,6 +25,7 @@ namespace osu.Desktop internal partial class DiscordRichPresence : Component { private const string client_id = "367827983903490050"; + public const string DISCORD_PROTOCOL = $"discord-{client_id}://"; private DiscordRpcClient client = null!; @@ -33,6 +37,12 @@ namespace osu.Desktop [Resolved] private IAPIProvider api { get; set; } = null!; + [Resolved] + private OsuGame game { get; set; } = null!; + + [Resolved] + private MultiplayerClient multiplayerClient { get; set; } = null!; + private readonly IBindable status = new Bindable(); private readonly IBindable activity = new Bindable(); @@ -40,7 +50,12 @@ namespace osu.Desktop private readonly RichPresence presence = new RichPresence { - Assets = new Assets { LargeImageKey = "osu_logo_lazer", } + Assets = new Assets { LargeImageKey = "osu_logo_lazer" }, + Secrets = new Secrets + { + JoinSecret = null, + SpectateSecret = null, + }, }; [BackgroundDependencyLoader] @@ -52,8 +67,14 @@ namespace osu.Desktop }; client.OnReady += onReady; + client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network, LogLevel.Error); - client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network); + // set up stuff for spectate/join + // first, we register a uri scheme for when osu! isn't running and a user clicks join/spectate + // the rpc library we use also happens to _require_ that we do this + client.RegisterUriScheme(); + client.Subscribe(EventType.Join); // we have to explicitly tell discord to send us join events. + client.OnJoin += onJoin; config.BindWith(OsuSetting.DiscordRichPresence, privacyMode); @@ -114,6 +135,28 @@ namespace osu.Desktop { presence.Buttons = null; } + + if (!hideIdentifiableInformation && multiplayerClient.Room != null) + { + MultiplayerRoom room = multiplayerClient.Room; + presence.Party = new Party + { + Privacy = string.IsNullOrEmpty(room.Settings.Password) ? Party.PrivacySetting.Public : Party.PrivacySetting.Private, + ID = room.RoomID.ToString(), + // technically lobbies can have infinite users, but Discord needs this to be set to something. + // 1024 just happens to look nice. + // https://discord.com/channels/188630481301012481/188630652340404224/1212967974793642034 + Max = 1024, + Size = room.Users.Count, + }; + + presence.Secrets.JoinSecret = $"{room.RoomID}:{room.Settings.Password}"; + } + else + { + presence.Party = null; + presence.Secrets.JoinSecret = null; + } } else { @@ -139,6 +182,22 @@ namespace osu.Desktop client.SetPresence(presence); } + private void onJoin(object sender, JoinMessage args) + { + game.Window?.Raise(); // users will expect to be brought back to osu! when joining a lobby from discord + + if (!tryParseRoomSecret(args.Secret, out long roomId, out string? password)) + Logger.Log("Failed to parse the room secret Discord gave us", LoggingTarget.Network, LogLevel.Error); + + var request = new GetRoomRequest(roomId); + request.Success += room => Schedule(() => + { + game.PresentMultiplayerMatch(room, password); + }); + request.Failure += _ => Logger.Log("Couldn't find the room Discord gave us", LoggingTarget.Network, LogLevel.Error); + api.Queue(request); + } + private static readonly int ellipsis_length = Encoding.UTF8.GetByteCount(new[] { '…' }); private string truncate(string str) @@ -160,6 +219,26 @@ namespace osu.Desktop }); } + private static bool tryParseRoomSecret(ReadOnlySpan secret, out long roomId, out string? password) + { + roomId = 0; + password = null; + + int roomSecretSplitIndex = secret.IndexOf(':'); + + if (roomSecretSplitIndex == -1) + return false; + + if (!long.TryParse(secret[..roomSecretSplitIndex], out roomId)) + return false; + + // just convert to string here, we're going to have to alloc it later anyways + password = secret[(roomSecretSplitIndex + 1)..].ToString(); + if (password.Length == 0) password = null; + + return true; + } + private int? getBeatmapID(UserActivity activity) { switch (activity) From 92235e7789271da1080f6f8f635e52f5f8490002 Mon Sep 17 00:00:00 2001 From: jvyden Date: Fri, 1 Mar 2024 00:02:20 -0500 Subject: [PATCH 683/915] Make truncate and getBeatmapID static Code quality was complaining about hidden variables so I opted for this solution. --- osu.Desktop/DiscordRichPresence.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index b85abdb4fe..91f7f6e1da 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -200,7 +200,7 @@ namespace osu.Desktop private static readonly int ellipsis_length = Encoding.UTF8.GetByteCount(new[] { '…' }); - private string truncate(string str) + private static string truncate(string str) { if (Encoding.UTF8.GetByteCount(str) <= 128) return str; @@ -239,7 +239,7 @@ namespace osu.Desktop return true; } - private int? getBeatmapID(UserActivity activity) + private static int? getBeatmapID(UserActivity activity) { switch (activity) { From 963c0af8143654e20910ed4f6b48ebce5845ad4e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Mar 2024 16:43:47 +0800 Subject: [PATCH 684/915] Fix beatmap information still showing when testing a beatmap --- osu.Game/Users/UserActivity.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 404ed141b9..a5dd2cb37c 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -119,10 +119,10 @@ namespace osu.Game.Users } [MessagePackObject] - public class TestingBeatmap : InGame + public class TestingBeatmap : EditingBeatmap { public TestingBeatmap(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset) - : base(beatmapInfo, ruleset) + : base(beatmapInfo) { } From c6201ea5de4bc0ad9943fd5e5f83783e6172205d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Mar 2024 20:28:52 +0800 Subject: [PATCH 685/915] Remove unused ruleset parameter when testing beatmap in editor --- osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs | 3 +-- osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs | 2 +- osu.Game/Users/UserActivity.cs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 4df34e6244..91942c391a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -14,7 +14,6 @@ using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Rulesets; -using osu.Game.Rulesets.Osu; using osu.Game.Scoring; using osu.Game.Tests.Beatmaps; using osu.Game.Users; @@ -142,7 +141,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap()); AddStep("editing beatmap", () => activity.Value = new UserActivity.EditingBeatmap(new BeatmapInfo())); AddStep("modding beatmap", () => activity.Value = new UserActivity.ModdingBeatmap(new BeatmapInfo())); - AddStep("testing beatmap", () => activity.Value = new UserActivity.TestingBeatmap(new BeatmapInfo(), new OsuRuleset().RulesetInfo)); + AddStep("testing beatmap", () => activity.Value = new UserActivity.TestingBeatmap(new BeatmapInfo())); } [Test] diff --git a/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs b/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs index 7dff05667d..55607cbb7c 100644 --- a/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs +++ b/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Edit.GameplayTest private readonly Editor editor; private readonly EditorState editorState; - protected override UserActivity InitialActivity => new UserActivity.TestingBeatmap(Beatmap.Value.BeatmapInfo, Ruleset.Value); + protected override UserActivity InitialActivity => new UserActivity.TestingBeatmap(Beatmap.Value.BeatmapInfo); [Resolved] private MusicController musicController { get; set; } = null!; diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index a5dd2cb37c..a431b204bc 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -121,7 +121,7 @@ namespace osu.Game.Users [MessagePackObject] public class TestingBeatmap : EditingBeatmap { - public TestingBeatmap(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset) + public TestingBeatmap(IBeatmapInfo beatmapInfo) : base(beatmapInfo) { } From 3df32638c2235029625d929c41ce6237c646e75c Mon Sep 17 00:00:00 2001 From: Susko3 Date: Fri, 1 Mar 2024 16:06:30 +0100 Subject: [PATCH 686/915] Fix association descriptions never being written on update --- osu.Desktop/Windows/WindowsAssociationManager.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Desktop/Windows/WindowsAssociationManager.cs b/osu.Desktop/Windows/WindowsAssociationManager.cs index 181403d287..11b5c19ca1 100644 --- a/osu.Desktop/Windows/WindowsAssociationManager.cs +++ b/osu.Desktop/Windows/WindowsAssociationManager.cs @@ -82,6 +82,10 @@ namespace osu.Desktop.Windows try { updateAssociations(); + + // TODO: Remove once UpdateDescriptions() is called as specified in the xmldoc. + updateDescriptions(null); // always write default descriptions, in case of updating from an older version in which file associations were not implemented/installed + NotifyShellUpdate(); } catch (Exception e) From 77b3055978bdd3b872d4297f1b70ba05f6164c05 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 29 Feb 2024 23:23:57 +0300 Subject: [PATCH 687/915] Improve sb sprite end time guessing --- osu.Game/Storyboards/CommandTimelineGroup.cs | 41 ++-------------- osu.Game/Storyboards/StoryboardSprite.cs | 50 ++++++++++++++++++-- 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index 0b96db6861..c899cf77d3 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.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; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; @@ -46,32 +45,10 @@ namespace osu.Game.Storyboards } [JsonIgnore] - public double CommandsStartTime - { - get - { - double min = double.MaxValue; - - for (int i = 0; i < timelines.Length; i++) - min = Math.Min(min, timelines[i].StartTime); - - return min; - } - } + public double CommandsStartTime => timelines.Min(static t => t.StartTime); [JsonIgnore] - public double CommandsEndTime - { - get - { - double max = double.MinValue; - - for (int i = 0; i < timelines.Length; i++) - max = Math.Max(max, timelines[i].EndTime); - - return max; - } - } + public double CommandsEndTime => timelines.Max(static t => t.EndTime); [JsonIgnore] public double CommandsDuration => CommandsEndTime - CommandsStartTime; @@ -83,19 +60,7 @@ namespace osu.Game.Storyboards public virtual double EndTime => CommandsEndTime; [JsonIgnore] - public bool HasCommands - { - get - { - for (int i = 0; i < timelines.Length; i++) - { - if (timelines[i].HasCommands) - return true; - } - - return false; - } - } + public bool HasCommands => timelines.Any(static t => t.HasCommands); public virtual IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) { diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 982185d51b..350438942e 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -85,12 +85,56 @@ namespace osu.Game.Storyboards { get { - double latestEndTime = TimelineGroup.EndTime; + double latestEndTime = double.MaxValue; + + // Ignore the whole setup if there are loops. In theory they can be handled here too, however the logic will be overly complex. + if (loops.Count == 0) + { + // Here we are starting from maximum value and trying to minimise the end time on each step. + // There are few solid guesses we can make using which sprite's end time can be minimised: alpha = 0, scale = 0, colour.a = 0. + double[] deathTimes = + { + double.MaxValue, // alpha + double.MaxValue, // colour alpha + double.MaxValue, // scale + double.MaxValue, // scale x + double.MaxValue, // scale y + }; + + // The loops below are following the same pattern. + // We could be using TimelineGroup.EndValue here, however it's possible to have multiple commands with 0 value in a row + // so we are saving the earliest of them. + foreach (var alphaCommand in TimelineGroup.Alpha.Commands) + { + deathTimes[0] = alphaCommand.EndValue == 0 + ? Math.Min(alphaCommand.EndTime, deathTimes[0]) // commands are ordered by the start time, however end time may vary. Save the earliest. + : double.MaxValue; // If value isn't 0 (sprite becomes visible again), revert the saved state. + } + + foreach (var colourCommand in TimelineGroup.Colour.Commands) + deathTimes[1] = colourCommand.EndValue.A == 0 ? Math.Min(colourCommand.EndTime, deathTimes[1]) : double.MaxValue; + + foreach (var scaleCommand in TimelineGroup.Scale.Commands) + deathTimes[2] = scaleCommand.EndValue == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[2]) : double.MaxValue; + + foreach (var scaleCommand in TimelineGroup.VectorScale.Commands) + { + deathTimes[3] = scaleCommand.EndValue.X == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[3]) : double.MaxValue; + deathTimes[4] = scaleCommand.EndValue.Y == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[4]) : double.MaxValue; + } + + // Take the minimum time of all the potential "death" reasons. + latestEndTime = deathTimes.Min(); + } + + // If the logic above fails to find anything or discarded by the fact that there are loops present, latestEndTime will be double.MaxValue + // and thus conservativeEndTime will be used. + double conservativeEndTime = TimelineGroup.EndTime; foreach (var l in loops) - latestEndTime = Math.Max(latestEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations); + conservativeEndTime = Math.Max(conservativeEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations); - return latestEndTime; + return Math.Min(latestEndTime, conservativeEndTime); } } From 37e7a4dea7f957231a4eb2aaf9e95654ab4d711e Mon Sep 17 00:00:00 2001 From: Jayden Date: Fri, 1 Mar 2024 14:32:44 -0500 Subject: [PATCH 688/915] Fix yapping Co-authored-by: Salman Ahmed --- osu.Desktop/DiscordRichPresence.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 91f7f6e1da..035add8044 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -25,7 +25,6 @@ namespace osu.Desktop internal partial class DiscordRichPresence : Component { private const string client_id = "367827983903490050"; - public const string DISCORD_PROTOCOL = $"discord-{client_id}://"; private DiscordRpcClient client = null!; @@ -69,11 +68,9 @@ namespace osu.Desktop client.OnReady += onReady; client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network, LogLevel.Error); - // set up stuff for spectate/join - // first, we register a uri scheme for when osu! isn't running and a user clicks join/spectate - // the rpc library we use also happens to _require_ that we do this + // A URI scheme is required to support game invitations, as well as informing Discord of the game executable path to support launching the game when a user clicks on join/spectate. client.RegisterUriScheme(); - client.Subscribe(EventType.Join); // we have to explicitly tell discord to send us join events. + client.Subscribe(EventType.Join); client.OnJoin += onJoin; config.BindWith(OsuSetting.DiscordRichPresence, privacyMode); @@ -184,7 +181,7 @@ namespace osu.Desktop private void onJoin(object sender, JoinMessage args) { - game.Window?.Raise(); // users will expect to be brought back to osu! when joining a lobby from discord + game.Window?.Raise(); if (!tryParseRoomSecret(args.Secret, out long roomId, out string? password)) Logger.Log("Failed to parse the room secret Discord gave us", LoggingTarget.Network, LogLevel.Error); @@ -232,7 +229,6 @@ namespace osu.Desktop if (!long.TryParse(secret[..roomSecretSplitIndex], out roomId)) return false; - // just convert to string here, we're going to have to alloc it later anyways password = secret[(roomSecretSplitIndex + 1)..].ToString(); if (password.Length == 0) password = null; From e0c73eb36225b1e7e058b3af5cc553f791ae28b6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 1 Mar 2024 22:49:12 +0300 Subject: [PATCH 689/915] Fix osu!mania key images potentially showing gaps between columns --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs index 48b92a8486..9fd33b9963 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Rulesets.Mania.UI; @@ -49,14 +50,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy upSprite = new Sprite { Origin = Anchor.BottomCentre, - Texture = skin.GetTexture(upImage), + Texture = skin.GetTexture(upImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge), RelativeSizeAxes = Axes.X, Width = 1 }, downSprite = new Sprite { Origin = Anchor.BottomCentre, - Texture = skin.GetTexture(downImage), + Texture = skin.GetTexture(downImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge), RelativeSizeAxes = Axes.X, Width = 1, Alpha = 0 From f1b66da469ead2105e6b3f1d83e95e04b7f4ec45 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 1 Mar 2024 22:57:13 +0300 Subject: [PATCH 690/915] Add comments --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs index 9fd33b9963..6ba91fbbd5 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs @@ -50,6 +50,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy upSprite = new Sprite { Origin = Anchor.BottomCentre, + // ClampToEdge is used to avoid gaps between keys, see: https://github.com/ppy/osu/issues/27431 Texture = skin.GetTexture(upImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge), RelativeSizeAxes = Axes.X, Width = 1 @@ -57,6 +58,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy downSprite = new Sprite { Origin = Anchor.BottomCentre, + // ClampToEdge is used to avoid gaps between keys, see: https://github.com/ppy/osu/issues/27431 Texture = skin.GetTexture(downImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge), RelativeSizeAxes = Axes.X, Width = 1, From 82373ff752ab9c1d961a8c5673499ddb913bec05 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 2 Mar 2024 03:18:42 +0300 Subject: [PATCH 691/915] Add failing catch beatmap --- .../CatchBeatmapConversionTest.cs | 1 + .../Beatmaps/1041052-expected-conversion.json | 1 + .../Resources/Testing/Beatmaps/1041052.osu | 210 ++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1041052-expected-conversion.json create mode 100644 osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1041052.osu diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index d0ecb828df..81e0675aaa 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -53,6 +53,7 @@ namespace osu.Game.Rulesets.Catch.Tests [TestCase("3689906", new[] { typeof(CatchModDoubleTime), typeof(CatchModEasy) })] [TestCase("3949367", new[] { typeof(CatchModDoubleTime), typeof(CatchModEasy) })] [TestCase("112643")] + [TestCase("1041052", new[] { typeof(CatchModHardRock) })] public new void Test(string name, params Type[] mods) => base.Test(name, mods); protected override IEnumerable CreateConvertValue(HitObject hitObject) diff --git a/osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1041052-expected-conversion.json b/osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1041052-expected-conversion.json new file mode 100644 index 0000000000..01150e701d --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1041052-expected-conversion.json @@ -0,0 +1 @@ +{"Mappings":[{"StartTime":1155.0,"Objects":[{"StartTime":1155.0,"Position":208.0,"HyperDash":false},{"StartTime":1251.0,"Position":167.675858,"HyperDash":false},{"StartTime":1348.0,"Position":157.087921,"HyperDash":false},{"StartTime":1445.0,"Position":128.5,"HyperDash":false},{"StartTime":1542.0,"Position":105.912064,"HyperDash":false},{"StartTime":1620.0,"Position":102.336205,"HyperDash":false},{"StartTime":1735.0,"Position":55.0,"HyperDash":false}]},{"StartTime":2122.0,"Objects":[{"StartTime":2122.0,"Position":275.0,"HyperDash":false}]},{"StartTime":2509.0,"Objects":[{"StartTime":2509.0,"Position":269.0,"HyperDash":false}]},{"StartTime":3284.0,"Objects":[{"StartTime":3284.0,"Position":448.0,"HyperDash":false},{"StartTime":3380.0,"Position":466.562317,"HyperDash":false},{"StartTime":3477.0,"Position":477.575867,"HyperDash":false},{"StartTime":3556.0,"Position":467.440033,"HyperDash":false},{"StartTime":3671.0,"Position":481.146881,"HyperDash":false}]},{"StartTime":4058.0,"Objects":[{"StartTime":4058.0,"Position":288.0,"HyperDash":false}]},{"StartTime":5025.0,"Objects":[{"StartTime":5025.0,"Position":128.0,"HyperDash":false},{"StartTime":5121.0,"Position":94.67586,"HyperDash":false},{"StartTime":5218.0,"Position":77.08793,"HyperDash":false},{"StartTime":5315.0,"Position":51.5,"HyperDash":false},{"StartTime":5412.0,"Position":77.08794,"HyperDash":false},{"StartTime":5490.0,"Position":111.663795,"HyperDash":false},{"StartTime":5605.0,"Position":128.0,"HyperDash":false}]},{"StartTime":5800.0,"Objects":[{"StartTime":5800.0,"Position":352.0,"HyperDash":false}]},{"StartTime":5993.0,"Objects":[{"StartTime":5993.0,"Position":240.0,"HyperDash":false}]},{"StartTime":6187.0,"Objects":[{"StartTime":6187.0,"Position":336.0,"HyperDash":false}]},{"StartTime":6574.0,"Objects":[{"StartTime":6574.0,"Position":416.0,"HyperDash":false},{"StartTime":6670.0,"Position":394.697662,"HyperDash":false},{"StartTime":6767.0,"Position":365.131775,"HyperDash":false},{"StartTime":6864.0,"Position":344.5659,"HyperDash":false},{"StartTime":6961.0,"Position":314.0,"HyperDash":false},{"StartTime":7057.0,"Position":279.6977,"HyperDash":false},{"StartTime":7154.0,"Position":263.131775,"HyperDash":false},{"StartTime":7233.0,"Position":259.310059,"HyperDash":false},{"StartTime":7348.0,"Position":212.0,"HyperDash":false}]},{"StartTime":8122.0,"Objects":[{"StartTime":8122.0,"Position":488.0,"HyperDash":false},{"StartTime":8218.0,"Position":475.697662,"HyperDash":false},{"StartTime":8315.0,"Position":437.131775,"HyperDash":false},{"StartTime":8394.0,"Position":399.3101,"HyperDash":false},{"StartTime":8509.0,"Position":386.0,"HyperDash":false}]},{"StartTime":8896.0,"Objects":[{"StartTime":8896.0,"Position":457.0,"HyperDash":false},{"StartTime":8992.0,"Position":444.675873,"HyperDash":false},{"StartTime":9089.0,"Position":406.087921,"HyperDash":false},{"StartTime":9186.0,"Position":384.5,"HyperDash":false},{"StartTime":9283.0,"Position":354.912048,"HyperDash":false},{"StartTime":9361.0,"Position":330.3362,"HyperDash":false},{"StartTime":9476.0,"Position":304.0,"HyperDash":false}]},{"StartTime":10058.0,"Objects":[{"StartTime":10058.0,"Position":400.0,"HyperDash":false}]},{"StartTime":10445.0,"Objects":[{"StartTime":10445.0,"Position":304.0,"HyperDash":false},{"StartTime":10541.0,"Position":277.697662,"HyperDash":false},{"StartTime":10638.0,"Position":253.131775,"HyperDash":false},{"StartTime":10735.0,"Position":212.565887,"HyperDash":false},{"StartTime":10832.0,"Position":202.0,"HyperDash":false},{"StartTime":10928.0,"Position":208.302322,"HyperDash":false},{"StartTime":11025.0,"Position":252.868225,"HyperDash":false},{"StartTime":11104.0,"Position":286.6899,"HyperDash":false},{"StartTime":11219.0,"Position":304.0,"HyperDash":false}]},{"StartTime":11606.0,"Objects":[{"StartTime":11606.0,"Position":400.0,"HyperDash":false}]},{"StartTime":11993.0,"Objects":[{"StartTime":11993.0,"Position":240.0,"HyperDash":false},{"StartTime":12089.0,"Position":231.675858,"HyperDash":false},{"StartTime":12186.0,"Position":189.087921,"HyperDash":false},{"StartTime":12283.0,"Position":156.5,"HyperDash":false},{"StartTime":12380.0,"Position":137.912064,"HyperDash":false},{"StartTime":12458.0,"Position":136.336212,"HyperDash":false},{"StartTime":12573.0,"Position":87.0,"HyperDash":false}]},{"StartTime":13154.0,"Objects":[{"StartTime":13154.0,"Position":0.0,"HyperDash":false}]},{"StartTime":13542.0,"Objects":[{"StartTime":13542.0,"Position":112.0,"HyperDash":false},{"StartTime":13638.0,"Position":119.913734,"HyperDash":false},{"StartTime":13735.0,"Position":144.5726,"HyperDash":false},{"StartTime":13832.0,"Position":179.8026,"HyperDash":false},{"StartTime":13929.0,"Position":191.357681,"HyperDash":false},{"StartTime":14007.0,"Position":228.85704,"HyperDash":false},{"StartTime":14122.0,"Position":241.622177,"HyperDash":false}]},{"StartTime":14316.0,"Objects":[{"StartTime":14316.0,"Position":288.0,"HyperDash":false},{"StartTime":14412.0,"Position":328.324127,"HyperDash":false},{"StartTime":14509.0,"Position":338.912079,"HyperDash":false},{"StartTime":14606.0,"Position":364.5,"HyperDash":false},{"StartTime":14703.0,"Position":338.912079,"HyperDash":false},{"StartTime":14781.0,"Position":301.3362,"HyperDash":false},{"StartTime":14896.0,"Position":288.0,"HyperDash":false}]},{"StartTime":15284.0,"Objects":[{"StartTime":15284.0,"Position":192.0,"HyperDash":false},{"StartTime":15362.0,"Position":187.7823,"HyperDash":false},{"StartTime":15477.0,"Position":169.192108,"HyperDash":false}]},{"StartTime":15864.0,"Objects":[{"StartTime":15864.0,"Position":464.0,"HyperDash":false}]},{"StartTime":16638.0,"Objects":[{"StartTime":16638.0,"Position":128.0,"HyperDash":false},{"StartTime":16734.0,"Position":90.86488,"HyperDash":false},{"StartTime":16831.0,"Position":78.3134155,"HyperDash":false},{"StartTime":16928.0,"Position":73.3517761,"HyperDash":false},{"StartTime":17025.0,"Position":34.6746674,"HyperDash":false},{"StartTime":17121.0,"Position":33.0714569,"HyperDash":false},{"StartTime":17218.0,"Position":2.65127468,"HyperDash":false},{"StartTime":17315.0,"Position":19.907608,"HyperDash":false},{"StartTime":17412.0,"Position":34.674675,"HyperDash":false},{"StartTime":17508.0,"Position":56.12827,"HyperDash":false},{"StartTime":17605.0,"Position":78.0694351,"HyperDash":false},{"StartTime":17684.0,"Position":97.97488,"HyperDash":false},{"StartTime":17799.0,"Position":128.0,"HyperDash":false}]},{"StartTime":18187.0,"Objects":[{"StartTime":18187.0,"Position":224.0,"HyperDash":false},{"StartTime":18283.0,"Position":231.165024,"HyperDash":false},{"StartTime":18380.0,"Position":273.681732,"HyperDash":false},{"StartTime":18477.0,"Position":304.374176,"HyperDash":false},{"StartTime":18574.0,"Position":316.397827,"HyperDash":false},{"StartTime":18670.0,"Position":312.8548,"HyperDash":false},{"StartTime":18767.0,"Position":345.5291,"HyperDash":false},{"StartTime":18864.0,"Position":328.007355,"HyperDash":false},{"StartTime":18961.0,"Position":316.397827,"HyperDash":false},{"StartTime":19057.0,"Position":304.594452,"HyperDash":false},{"StartTime":19154.0,"Position":273.924957,"HyperDash":false},{"StartTime":19233.0,"Position":271.063354,"HyperDash":false},{"StartTime":19348.0,"Position":224.0,"HyperDash":false}]},{"StartTime":19735.0,"Objects":[{"StartTime":19735.0,"Position":128.0,"HyperDash":false},{"StartTime":19831.0,"Position":136.324142,"HyperDash":false},{"StartTime":19928.0,"Position":178.912079,"HyperDash":false},{"StartTime":20025.0,"Position":223.5,"HyperDash":false},{"StartTime":20122.0,"Position":230.087936,"HyperDash":false},{"StartTime":20200.0,"Position":260.6638,"HyperDash":false},{"StartTime":20315.0,"Position":281.0,"HyperDash":false}]},{"StartTime":20896.0,"Objects":[{"StartTime":20896.0,"Position":432.0,"HyperDash":false}]},{"StartTime":21284.0,"Objects":[{"StartTime":21284.0,"Position":328.0,"HyperDash":false},{"StartTime":21380.0,"Position":357.324127,"HyperDash":false},{"StartTime":21477.0,"Position":378.912079,"HyperDash":false},{"StartTime":21574.0,"Position":420.5,"HyperDash":false},{"StartTime":21671.0,"Position":430.087952,"HyperDash":false},{"StartTime":21749.0,"Position":447.6638,"HyperDash":false},{"StartTime":21864.0,"Position":481.0,"HyperDash":false}]},{"StartTime":22445.0,"Objects":[{"StartTime":22445.0,"Position":328.0,"HyperDash":false}]},{"StartTime":22832.0,"Objects":[{"StartTime":22832.0,"Position":224.0,"HyperDash":false},{"StartTime":22928.0,"Position":188.675858,"HyperDash":false},{"StartTime":23025.0,"Position":173.087921,"HyperDash":false},{"StartTime":23122.0,"Position":156.5,"HyperDash":false},{"StartTime":23219.0,"Position":121.912064,"HyperDash":false},{"StartTime":23297.0,"Position":91.3362045,"HyperDash":false},{"StartTime":23412.0,"Position":71.0,"HyperDash":false}]},{"StartTime":23993.0,"Objects":[{"StartTime":23993.0,"Position":224.0,"HyperDash":false}]},{"StartTime":24380.0,"Objects":[{"StartTime":24380.0,"Position":112.0,"HyperDash":false},{"StartTime":24476.0,"Position":127.324142,"HyperDash":false},{"StartTime":24573.0,"Position":162.912079,"HyperDash":false},{"StartTime":24670.0,"Position":202.5,"HyperDash":false},{"StartTime":24767.0,"Position":214.087936,"HyperDash":false},{"StartTime":24845.0,"Position":246.663788,"HyperDash":false},{"StartTime":24960.0,"Position":265.0,"HyperDash":false}]},{"StartTime":25541.0,"Objects":[{"StartTime":25541.0,"Position":416.0,"HyperDash":false}]},{"StartTime":25929.0,"Objects":[{"StartTime":25929.0,"Position":304.0,"HyperDash":false},{"StartTime":26025.0,"Position":287.9714,"HyperDash":false},{"StartTime":26122.0,"Position":274.232758,"HyperDash":false},{"StartTime":26219.0,"Position":253.164063,"HyperDash":false},{"StartTime":26316.0,"Position":274.1704,"HyperDash":false},{"StartTime":26394.0,"Position":290.949921,"HyperDash":false},{"StartTime":26509.0,"Position":303.819763,"HyperDash":false}]},{"StartTime":27090.0,"Objects":[{"StartTime":27090.0,"Position":480.0,"HyperDash":false}]},{"StartTime":27477.0,"Objects":[{"StartTime":27477.0,"Position":384.0,"HyperDash":false},{"StartTime":27573.0,"Position":351.697662,"HyperDash":false},{"StartTime":27670.0,"Position":333.0,"HyperDash":false},{"StartTime":27749.0,"Position":356.6899,"HyperDash":false},{"StartTime":27864.0,"Position":384.0,"HyperDash":false}]},{"StartTime":28058.0,"Objects":[{"StartTime":28058.0,"Position":432.0,"HyperDash":false}]},{"StartTime":28445.0,"Objects":[{"StartTime":28445.0,"Position":333.0,"HyperDash":false},{"StartTime":28541.0,"Position":305.697662,"HyperDash":false},{"StartTime":28638.0,"Position":282.0,"HyperDash":false},{"StartTime":28717.0,"Position":319.6899,"HyperDash":false},{"StartTime":28832.0,"Position":333.0,"HyperDash":false}]},{"StartTime":29025.0,"Objects":[{"StartTime":29025.0,"Position":384.0,"HyperDash":false},{"StartTime":29121.0,"Position":341.697662,"HyperDash":false},{"StartTime":29218.0,"Position":333.131775,"HyperDash":false},{"StartTime":29297.0,"Position":293.3101,"HyperDash":false},{"StartTime":29412.0,"Position":282.0,"HyperDash":false}]},{"StartTime":29606.0,"Objects":[{"StartTime":29606.0,"Position":224.0,"HyperDash":false},{"StartTime":29702.0,"Position":206.103424,"HyperDash":false},{"StartTime":29799.0,"Position":176.49205,"HyperDash":false},{"StartTime":29896.0,"Position":149.701324,"HyperDash":false},{"StartTime":29993.0,"Position":147.519775,"HyperDash":false},{"StartTime":30071.0,"Position":144.128265,"HyperDash":false},{"StartTime":30186.0,"Position":148.650436,"HyperDash":false}]},{"StartTime":30574.0,"Objects":[{"StartTime":30574.0,"Position":272.0,"HyperDash":false},{"StartTime":30670.0,"Position":303.302338,"HyperDash":false},{"StartTime":30767.0,"Position":322.868225,"HyperDash":false},{"StartTime":30846.0,"Position":351.6899,"HyperDash":false},{"StartTime":30961.0,"Position":374.0,"HyperDash":false}]},{"StartTime":31154.0,"Objects":[{"StartTime":31154.0,"Position":424.0,"HyperDash":false},{"StartTime":31250.0,"Position":439.371674,"HyperDash":false},{"StartTime":31347.0,"Position":424.705872,"HyperDash":false},{"StartTime":31444.0,"Position":417.305573,"HyperDash":false},{"StartTime":31541.0,"Position":395.3253,"HyperDash":false},{"StartTime":31619.0,"Position":372.2993,"HyperDash":false},{"StartTime":31734.0,"Position":347.633759,"HyperDash":false}]},{"StartTime":32122.0,"Objects":[{"StartTime":32122.0,"Position":224.0,"HyperDash":false},{"StartTime":32218.0,"Position":200.129822,"HyperDash":false},{"StartTime":32315.0,"Position":176.418152,"HyperDash":false},{"StartTime":32394.0,"Position":164.275757,"HyperDash":false},{"StartTime":32509.0,"Position":146.329926,"HyperDash":false}]},{"StartTime":32703.0,"Objects":[{"StartTime":32703.0,"Position":256.0,"HyperDash":false}]},{"StartTime":33284.0,"Objects":[{"StartTime":33284.0,"Position":496.0,"HyperDash":false}]},{"StartTime":33671.0,"Objects":[{"StartTime":33671.0,"Position":304.0,"HyperDash":false},{"StartTime":33767.0,"Position":297.697662,"HyperDash":false},{"StartTime":33864.0,"Position":253.0,"HyperDash":false},{"StartTime":33943.0,"Position":270.6899,"HyperDash":false},{"StartTime":34058.0,"Position":304.0,"HyperDash":false}]},{"StartTime":34251.0,"Objects":[{"StartTime":34251.0,"Position":352.0,"HyperDash":false},{"StartTime":34347.0,"Position":374.083679,"HyperDash":false},{"StartTime":34444.0,"Position":391.360016,"HyperDash":false},{"StartTime":34541.0,"Position":387.812561,"HyperDash":false},{"StartTime":34638.0,"Position":404.369629,"HyperDash":false},{"StartTime":34716.0,"Position":417.578369,"HyperDash":false},{"StartTime":34831.0,"Position":385.75708,"HyperDash":false}]},{"StartTime":35219.0,"Objects":[{"StartTime":35219.0,"Position":280.0,"HyperDash":false},{"StartTime":35315.0,"Position":277.964783,"HyperDash":false},{"StartTime":35412.0,"Position":251.783386,"HyperDash":false},{"StartTime":35491.0,"Position":238.233582,"HyperDash":false},{"StartTime":35606.0,"Position":223.420578,"HyperDash":false}]},{"StartTime":35800.0,"Objects":[{"StartTime":35800.0,"Position":272.0,"HyperDash":false},{"StartTime":35896.0,"Position":303.035217,"HyperDash":false},{"StartTime":35993.0,"Position":300.2166,"HyperDash":false},{"StartTime":36072.0,"Position":326.766418,"HyperDash":false},{"StartTime":36187.0,"Position":328.5794,"HyperDash":false}]},{"StartTime":36380.0,"Objects":[{"StartTime":36380.0,"Position":224.0,"HyperDash":false}]},{"StartTime":36767.0,"Objects":[{"StartTime":36767.0,"Position":176.0,"HyperDash":false},{"StartTime":36863.0,"Position":148.9648,"HyperDash":false},{"StartTime":36960.0,"Position":147.783386,"HyperDash":false},{"StartTime":37039.0,"Position":140.233582,"HyperDash":false},{"StartTime":37154.0,"Position":119.420578,"HyperDash":false}]},{"StartTime":37348.0,"Objects":[{"StartTime":37348.0,"Position":168.0,"HyperDash":false},{"StartTime":37444.0,"Position":170.0352,"HyperDash":false},{"StartTime":37541.0,"Position":196.216614,"HyperDash":false},{"StartTime":37620.0,"Position":195.766418,"HyperDash":false},{"StartTime":37735.0,"Position":224.579422,"HyperDash":false}]},{"StartTime":37928.0,"Objects":[{"StartTime":37928.0,"Position":120.0,"HyperDash":false}]},{"StartTime":38316.0,"Objects":[{"StartTime":38316.0,"Position":304.0,"HyperDash":false},{"StartTime":38412.0,"Position":277.697662,"HyperDash":false},{"StartTime":38509.0,"Position":253.131775,"HyperDash":false},{"StartTime":38588.0,"Position":226.310089,"HyperDash":false},{"StartTime":38703.0,"Position":202.0,"HyperDash":false}]},{"StartTime":38896.0,"Objects":[{"StartTime":38896.0,"Position":88.0,"HyperDash":false}]},{"StartTime":39477.0,"Objects":[{"StartTime":39477.0,"Position":280.0,"HyperDash":false},{"StartTime":39555.0,"Position":292.6114,"HyperDash":false},{"StartTime":39670.0,"Position":331.0,"HyperDash":false}]},{"StartTime":39864.0,"Objects":[{"StartTime":39864.0,"Position":424.0,"HyperDash":false},{"StartTime":39960.0,"Position":428.059753,"HyperDash":false},{"StartTime":40057.0,"Position":441.062134,"HyperDash":false},{"StartTime":40136.0,"Position":432.009247,"HyperDash":false},{"StartTime":40251.0,"Position":420.508881,"HyperDash":false}]},{"StartTime":40445.0,"Objects":[{"StartTime":40445.0,"Position":288.0,"HyperDash":false}]},{"StartTime":41025.0,"Objects":[{"StartTime":41025.0,"Position":32.0,"HyperDash":false}]},{"StartTime":41413.0,"Objects":[{"StartTime":41413.0,"Position":256.0,"HyperDash":false},{"StartTime":41509.0,"Position":291.8391,"HyperDash":false},{"StartTime":41606.0,"Position":302.265045,"HyperDash":false},{"StartTime":41685.0,"Position":310.9909,"HyperDash":false},{"StartTime":41800.0,"Position":352.8495,"HyperDash":false}]},{"StartTime":41993.0,"Objects":[{"StartTime":41993.0,"Position":447.0,"HyperDash":false}]},{"StartTime":42187.0,"Objects":[{"StartTime":42187.0,"Position":440.0,"HyperDash":false},{"StartTime":42283.0,"Position":403.2554,"HyperDash":false},{"StartTime":42380.0,"Position":389.7651,"HyperDash":false},{"StartTime":42459.0,"Position":365.6506,"HyperDash":false},{"StartTime":42574.0,"Position":342.9871,"HyperDash":false}]},{"StartTime":42961.0,"Objects":[{"StartTime":42961.0,"Position":248.0,"HyperDash":false},{"StartTime":43057.0,"Position":264.94986,"HyperDash":false},{"StartTime":43154.0,"Position":281.6838,"HyperDash":false},{"StartTime":43251.0,"Position":305.2995,"HyperDash":false},{"StartTime":43348.0,"Position":330.6694,"HyperDash":false},{"StartTime":43444.0,"Position":352.264221,"HyperDash":false},{"StartTime":43541.0,"Position":377.479736,"HyperDash":false},{"StartTime":43638.0,"Position":371.509277,"HyperDash":false},{"StartTime":43735.0,"Position":330.6694,"HyperDash":false},{"StartTime":43831.0,"Position":294.557373,"HyperDash":false},{"StartTime":43928.0,"Position":281.915039,"HyperDash":false},{"StartTime":44007.0,"Position":283.462677,"HyperDash":false},{"StartTime":44122.0,"Position":248.0,"HyperDash":false}]},{"StartTime":44509.0,"Objects":[{"StartTime":44509.0,"Position":144.0,"HyperDash":false},{"StartTime":44605.0,"Position":140.034851,"HyperDash":false},{"StartTime":44702.0,"Position":110.27771,"HyperDash":false},{"StartTime":44799.0,"Position":69.63604,"HyperDash":false},{"StartTime":44896.0,"Position":61.2429733,"HyperDash":false},{"StartTime":44974.0,"Position":47.09105,"HyperDash":false},{"StartTime":45089.0,"Position":14.520277,"HyperDash":false}]},{"StartTime":45284.0,"Objects":[{"StartTime":45284.0,"Position":56.0,"HyperDash":false}]},{"StartTime":45671.0,"Objects":[{"StartTime":45671.0,"Position":264.0,"HyperDash":false}]},{"StartTime":46058.0,"Objects":[{"StartTime":46058.0,"Position":264.0,"HyperDash":false},{"StartTime":46154.0,"Position":301.302338,"HyperDash":false},{"StartTime":46251.0,"Position":314.868225,"HyperDash":false},{"StartTime":46330.0,"Position":321.6899,"HyperDash":false},{"StartTime":46445.0,"Position":366.0,"HyperDash":false}]},{"StartTime":46638.0,"Objects":[{"StartTime":46638.0,"Position":416.0,"HyperDash":false},{"StartTime":46734.0,"Position":371.675873,"HyperDash":false},{"StartTime":46831.0,"Position":365.087921,"HyperDash":false},{"StartTime":46928.0,"Position":325.5,"HyperDash":false},{"StartTime":47025.0,"Position":313.912048,"HyperDash":false},{"StartTime":47103.0,"Position":306.3362,"HyperDash":false},{"StartTime":47218.0,"Position":263.0,"HyperDash":false}]},{"StartTime":47606.0,"Objects":[{"StartTime":47606.0,"Position":360.0,"HyperDash":false},{"StartTime":47702.0,"Position":324.675873,"HyperDash":false},{"StartTime":47799.0,"Position":309.087921,"HyperDash":false},{"StartTime":47896.0,"Position":293.5,"HyperDash":false},{"StartTime":47993.0,"Position":257.912048,"HyperDash":false},{"StartTime":48071.0,"Position":244.336212,"HyperDash":false},{"StartTime":48186.0,"Position":207.0,"HyperDash":false}]},{"StartTime":48380.0,"Objects":[{"StartTime":48380.0,"Position":160.0,"HyperDash":false},{"StartTime":48476.0,"Position":166.997681,"HyperDash":false},{"StartTime":48573.0,"Position":187.484192,"HyperDash":false},{"StartTime":48652.0,"Position":200.988281,"HyperDash":false},{"StartTime":48767.0,"Position":236.72261,"HyperDash":false}]},{"StartTime":49154.0,"Objects":[{"StartTime":49154.0,"Position":32.0,"HyperDash":false}]},{"StartTime":49542.0,"Objects":[{"StartTime":49542.0,"Position":248.0,"HyperDash":false},{"StartTime":49638.0,"Position":266.302338,"HyperDash":false},{"StartTime":49735.0,"Position":298.868225,"HyperDash":false},{"StartTime":49814.0,"Position":314.6899,"HyperDash":false},{"StartTime":49929.0,"Position":350.0,"HyperDash":false}]},{"StartTime":50316.0,"Objects":[{"StartTime":50316.0,"Position":256.0,"HyperDash":false},{"StartTime":50394.0,"Position":235.3886,"HyperDash":false},{"StartTime":50509.0,"Position":205.0,"HyperDash":false}]},{"StartTime":50703.0,"Objects":[{"StartTime":50703.0,"Position":256.0,"HyperDash":false},{"StartTime":50799.0,"Position":296.302338,"HyperDash":false},{"StartTime":50896.0,"Position":306.868225,"HyperDash":false},{"StartTime":50975.0,"Position":344.6899,"HyperDash":false},{"StartTime":51090.0,"Position":358.0,"HyperDash":false}]},{"StartTime":51284.0,"Objects":[{"StartTime":51284.0,"Position":440.0,"HyperDash":false}]},{"StartTime":51477.0,"Objects":[{"StartTime":51477.0,"Position":352.0,"HyperDash":false},{"StartTime":51573.0,"Position":329.697662,"HyperDash":false},{"StartTime":51670.0,"Position":301.131775,"HyperDash":false},{"StartTime":51749.0,"Position":288.3101,"HyperDash":false},{"StartTime":51864.0,"Position":250.0,"HyperDash":false}]},{"StartTime":52251.0,"Objects":[{"StartTime":52251.0,"Position":128.0,"HyperDash":false},{"StartTime":52347.0,"Position":102.275604,"HyperDash":false},{"StartTime":52444.0,"Position":77.8078156,"HyperDash":false},{"StartTime":52541.0,"Position":41.6188354,"HyperDash":false},{"StartTime":52638.0,"Position":32.3890381,"HyperDash":false},{"StartTime":52716.0,"Position":11.4332657,"HyperDash":false},{"StartTime":52831.0,"Position":4.4833107,"HyperDash":false}]},{"StartTime":53025.0,"Objects":[{"StartTime":53025.0,"Position":88.0,"HyperDash":false}]},{"StartTime":53413.0,"Objects":[{"StartTime":53413.0,"Position":168.0,"HyperDash":false},{"StartTime":53491.0,"Position":145.000992,"HyperDash":false},{"StartTime":53606.0,"Position":155.630676,"HyperDash":false}]},{"StartTime":53800.0,"Objects":[{"StartTime":53800.0,"Position":248.0,"HyperDash":false},{"StartTime":53896.0,"Position":263.12973,"HyperDash":false},{"StartTime":53993.0,"Position":290.128967,"HyperDash":false},{"StartTime":54090.0,"Position":316.20874,"HyperDash":false},{"StartTime":54187.0,"Position":340.6195,"HyperDash":false},{"StartTime":54265.0,"Position":376.1075,"HyperDash":false},{"StartTime":54380.0,"Position":385.246277,"HyperDash":false}]},{"StartTime":54574.0,"Objects":[{"StartTime":54574.0,"Position":472.0,"HyperDash":false}]},{"StartTime":54961.0,"Objects":[{"StartTime":54961.0,"Position":328.0,"HyperDash":false}]},{"StartTime":55348.0,"Objects":[{"StartTime":55348.0,"Position":224.0,"HyperDash":false},{"StartTime":55444.0,"Position":195.951981,"HyperDash":false},{"StartTime":55541.0,"Position":173.643036,"HyperDash":false},{"StartTime":55620.0,"Position":140.030609,"HyperDash":false},{"StartTime":55735.0,"Position":123.025146,"HyperDash":false}]},{"StartTime":55929.0,"Objects":[{"StartTime":55929.0,"Position":72.0,"HyperDash":false},{"StartTime":56025.0,"Position":95.8109741,"HyperDash":false},{"StartTime":56122.0,"Position":121.880394,"HyperDash":false},{"StartTime":56201.0,"Position":145.29776,"HyperDash":false},{"StartTime":56316.0,"Position":172.019226,"HyperDash":false}]},{"StartTime":56509.0,"Objects":[{"StartTime":56509.0,"Position":256.0,"HyperDash":false}]},{"StartTime":56896.0,"Objects":[{"StartTime":56896.0,"Position":328.0,"HyperDash":false},{"StartTime":56992.0,"Position":356.5922,"HyperDash":false},{"StartTime":57089.0,"Position":368.955872,"HyperDash":false},{"StartTime":57186.0,"Position":373.612579,"HyperDash":false},{"StartTime":57283.0,"Position":419.1303,"HyperDash":false},{"StartTime":57361.0,"Position":444.262817,"HyperDash":false},{"StartTime":57476.0,"Position":466.641,"HyperDash":false}]},{"StartTime":57671.0,"Objects":[{"StartTime":57671.0,"Position":416.0,"HyperDash":false},{"StartTime":57767.0,"Position":391.6712,"HyperDash":false},{"StartTime":57864.0,"Position":367.089,"HyperDash":false},{"StartTime":57943.0,"Position":328.06842,"HyperDash":false},{"StartTime":58058.0,"Position":317.924561,"HyperDash":false}]},{"StartTime":58445.0,"Objects":[{"StartTime":58445.0,"Position":144.0,"HyperDash":false}]},{"StartTime":58832.0,"Objects":[{"StartTime":58832.0,"Position":320.0,"HyperDash":false}]},{"StartTime":59219.0,"Objects":[{"StartTime":59219.0,"Position":128.0,"HyperDash":false}]},{"StartTime":59606.0,"Objects":[{"StartTime":59606.0,"Position":112.0,"HyperDash":false}]},{"StartTime":59993.0,"Objects":[{"StartTime":59993.0,"Position":224.0,"HyperDash":false},{"StartTime":60089.0,"Position":217.725632,"HyperDash":false},{"StartTime":60186.0,"Position":227.34639,"HyperDash":false},{"StartTime":60265.0,"Position":214.703522,"HyperDash":false},{"StartTime":60380.0,"Position":206.754791,"HyperDash":false}]},{"StartTime":60767.0,"Objects":[{"StartTime":60767.0,"Position":80.0,"HyperDash":false},{"StartTime":60863.0,"Position":90.79409,"HyperDash":false},{"StartTime":60960.0,"Position":75.87808,"HyperDash":false},{"StartTime":61039.0,"Position":74.4997559,"HyperDash":false},{"StartTime":61154.0,"Position":96.53038,"HyperDash":false}]},{"StartTime":61542.0,"Objects":[{"StartTime":61542.0,"Position":200.0,"HyperDash":false},{"StartTime":61638.0,"Position":196.089508,"HyperDash":false},{"StartTime":61735.0,"Position":236.445679,"HyperDash":false},{"StartTime":61814.0,"Position":270.5239,"HyperDash":false},{"StartTime":61929.0,"Position":286.4193,"HyperDash":false}]},{"StartTime":62316.0,"Objects":[{"StartTime":62316.0,"Position":376.0,"HyperDash":false},{"StartTime":62412.0,"Position":361.9105,"HyperDash":false},{"StartTime":62509.0,"Position":339.554321,"HyperDash":false},{"StartTime":62588.0,"Position":316.4761,"HyperDash":false},{"StartTime":62703.0,"Position":289.5807,"HyperDash":false}]},{"StartTime":63090.0,"Objects":[{"StartTime":63090.0,"Position":184.0,"HyperDash":false},{"StartTime":63186.0,"Position":174.5783,"HyperDash":false},{"StartTime":63283.0,"Position":191.193848,"HyperDash":false},{"StartTime":63362.0,"Position":204.138489,"HyperDash":false},{"StartTime":63477.0,"Position":198.424973,"HyperDash":false}]},{"StartTime":63864.0,"Objects":[{"StartTime":63864.0,"Position":88.0,"HyperDash":false},{"StartTime":63960.0,"Position":45.16764,"HyperDash":false},{"StartTime":64057.0,"Position":38.0766068,"HyperDash":false},{"StartTime":64154.0,"Position":12.98558,"HyperDash":false},{"StartTime":64251.0,"Position":38.0766144,"HyperDash":false},{"StartTime":64329.0,"Position":69.2529,"HyperDash":false},{"StartTime":64444.0,"Position":88.0,"HyperDash":false}]},{"StartTime":64638.0,"Objects":[{"StartTime":64638.0,"Position":312.0,"HyperDash":false}]},{"StartTime":64832.0,"Objects":[{"StartTime":64832.0,"Position":208.0,"HyperDash":false}]},{"StartTime":65025.0,"Objects":[{"StartTime":65025.0,"Position":304.0,"HyperDash":false}]},{"StartTime":65413.0,"Objects":[{"StartTime":65413.0,"Position":360.0,"HyperDash":false},{"StartTime":65491.0,"Position":361.6114,"HyperDash":false},{"StartTime":65606.0,"Position":411.0,"HyperDash":false}]},{"StartTime":65800.0,"Objects":[{"StartTime":65800.0,"Position":462.0,"HyperDash":false},{"StartTime":65878.0,"Position":458.3886,"HyperDash":false},{"StartTime":65993.0,"Position":411.0,"HyperDash":false}]},{"StartTime":66187.0,"Objects":[{"StartTime":66187.0,"Position":344.0,"HyperDash":false},{"StartTime":66283.0,"Position":327.697662,"HyperDash":false},{"StartTime":66380.0,"Position":293.131775,"HyperDash":false},{"StartTime":66459.0,"Position":271.3101,"HyperDash":false},{"StartTime":66574.0,"Position":242.0,"HyperDash":false}]},{"StartTime":66961.0,"Objects":[{"StartTime":66961.0,"Position":152.0,"HyperDash":false},{"StartTime":67057.0,"Position":167.659241,"HyperDash":false},{"StartTime":67154.0,"Position":147.9835,"HyperDash":false},{"StartTime":67233.0,"Position":135.201309,"HyperDash":false},{"StartTime":67348.0,"Position":106.616547,"HyperDash":false}]},{"StartTime":67735.0,"Objects":[{"StartTime":67735.0,"Position":32.0,"HyperDash":false},{"StartTime":67831.0,"Position":42.2565079,"HyperDash":false},{"StartTime":67928.0,"Position":78.75527,"HyperDash":false},{"StartTime":68007.0,"Position":85.89344,"HyperDash":false},{"StartTime":68122.0,"Position":125.752792,"HyperDash":false}]},{"StartTime":68316.0,"Objects":[{"StartTime":68316.0,"Position":208.0,"HyperDash":false}]},{"StartTime":68509.0,"Objects":[{"StartTime":68509.0,"Position":224.0,"HyperDash":false},{"StartTime":68605.0,"Position":240.243561,"HyperDash":false},{"StartTime":68702.0,"Position":270.729248,"HyperDash":false},{"StartTime":68781.0,"Position":291.85675,"HyperDash":false},{"StartTime":68896.0,"Position":317.7006,"HyperDash":false}]},{"StartTime":69284.0,"Objects":[{"StartTime":69284.0,"Position":216.0,"HyperDash":false},{"StartTime":69380.0,"Position":191.846649,"HyperDash":false},{"StartTime":69477.0,"Position":185.704849,"HyperDash":false},{"StartTime":69556.0,"Position":168.950912,"HyperDash":false},{"StartTime":69671.0,"Position":193.879364,"HyperDash":false}]},{"StartTime":70058.0,"Objects":[{"StartTime":70058.0,"Position":360.0,"HyperDash":false},{"StartTime":70154.0,"Position":374.986725,"HyperDash":false},{"StartTime":70251.0,"Position":367.9918,"HyperDash":false},{"StartTime":70330.0,"Position":353.6845,"HyperDash":false},{"StartTime":70445.0,"Position":337.885529,"HyperDash":false}]},{"StartTime":70832.0,"Objects":[{"StartTime":70832.0,"Position":264.0,"HyperDash":false},{"StartTime":70928.0,"Position":225.951981,"HyperDash":false},{"StartTime":71025.0,"Position":213.643036,"HyperDash":false},{"StartTime":71104.0,"Position":187.030609,"HyperDash":false},{"StartTime":71219.0,"Position":163.025146,"HyperDash":false}]},{"StartTime":71413.0,"Objects":[{"StartTime":71413.0,"Position":112.0,"HyperDash":false},{"StartTime":71509.0,"Position":75.97218,"HyperDash":false},{"StartTime":71606.0,"Position":61.6836624,"HyperDash":false},{"StartTime":71685.0,"Position":27.0878525,"HyperDash":false},{"StartTime":71800.0,"Position":11.1066208,"HyperDash":false}]},{"StartTime":71993.0,"Objects":[{"StartTime":71993.0,"Position":40.0,"HyperDash":false},{"StartTime":72071.0,"Position":52.4331474,"HyperDash":false},{"StartTime":72186.0,"Position":68.28971,"HyperDash":false}]},{"StartTime":72380.0,"Objects":[{"StartTime":72380.0,"Position":176.0,"HyperDash":false},{"StartTime":72476.0,"Position":187.970581,"HyperDash":false},{"StartTime":72573.0,"Position":161.344147,"HyperDash":false},{"StartTime":72670.0,"Position":136.575012,"HyperDash":false},{"StartTime":72767.0,"Position":119.0057,"HyperDash":false},{"StartTime":72845.0,"Position":79.55367,"HyperDash":false},{"StartTime":72960.0,"Position":69.6823959,"HyperDash":false}]},{"StartTime":73154.0,"Objects":[{"StartTime":73154.0,"Position":120.0,"HyperDash":false},{"StartTime":73250.0,"Position":160.2306,"HyperDash":false},{"StartTime":73347.0,"Position":169.814178,"HyperDash":false},{"StartTime":73426.0,"Position":170.964127,"HyperDash":false},{"StartTime":73541.0,"Position":209.453659,"HyperDash":false}]},{"StartTime":73929.0,"Objects":[{"StartTime":73929.0,"Position":312.0,"HyperDash":false},{"StartTime":74025.0,"Position":321.048035,"HyperDash":false},{"StartTime":74122.0,"Position":362.356964,"HyperDash":false},{"StartTime":74201.0,"Position":394.9694,"HyperDash":false},{"StartTime":74316.0,"Position":412.974854,"HyperDash":false}]},{"StartTime":74703.0,"Objects":[{"StartTime":74703.0,"Position":336.0,"HyperDash":false},{"StartTime":74781.0,"Position":342.880768,"HyperDash":false},{"StartTime":74896.0,"Position":315.910126,"HyperDash":false}]},{"StartTime":75090.0,"Objects":[{"StartTime":75090.0,"Position":400.0,"HyperDash":false},{"StartTime":75168.0,"Position":399.237152,"HyperDash":false},{"StartTime":75283.0,"Position":417.9073,"HyperDash":false}]},{"StartTime":75477.0,"Objects":[{"StartTime":75477.0,"Position":328.0,"HyperDash":false},{"StartTime":75573.0,"Position":296.892883,"HyperDash":false},{"StartTime":75670.0,"Position":288.19165,"HyperDash":false},{"StartTime":75767.0,"Position":275.9188,"HyperDash":false},{"StartTime":75864.0,"Position":238.263733,"HyperDash":false},{"StartTime":75942.0,"Position":221.022842,"HyperDash":false},{"StartTime":76057.0,"Position":202.919159,"HyperDash":false}]},{"StartTime":76251.0,"Objects":[{"StartTime":76251.0,"Position":296.0,"HyperDash":false},{"StartTime":76347.0,"Position":313.798157,"HyperDash":false},{"StartTime":76444.0,"Position":346.261322,"HyperDash":false},{"StartTime":76523.0,"Position":375.263733,"HyperDash":false},{"StartTime":76638.0,"Position":392.493958,"HyperDash":false}]},{"StartTime":77219.0,"Objects":[{"StartTime":77219.0,"Position":152.0,"HyperDash":false},{"StartTime":77315.0,"Position":119.697678,"HyperDash":false},{"StartTime":77412.0,"Position":101.0,"HyperDash":false},{"StartTime":77491.0,"Position":137.689911,"HyperDash":false},{"StartTime":77606.0,"Position":152.0,"HyperDash":false}]},{"StartTime":77800.0,"Objects":[{"StartTime":77800.0,"Position":320.0,"HyperDash":false}]},{"StartTime":78187.0,"Objects":[{"StartTime":78187.0,"Position":320.0,"HyperDash":false},{"StartTime":78265.0,"Position":323.92218,"HyperDash":false},{"StartTime":78380.0,"Position":369.294647,"HyperDash":false}]},{"StartTime":78574.0,"Objects":[{"StartTime":78574.0,"Position":456.0,"HyperDash":false},{"StartTime":78670.0,"Position":443.684448,"HyperDash":false},{"StartTime":78767.0,"Position":433.251038,"HyperDash":false},{"StartTime":78846.0,"Position":411.9393,"HyperDash":false},{"StartTime":78961.0,"Position":410.384216,"HyperDash":false}]},{"StartTime":79348.0,"Objects":[{"StartTime":79348.0,"Position":288.0,"HyperDash":false},{"StartTime":79444.0,"Position":287.315552,"HyperDash":false},{"StartTime":79541.0,"Position":310.748962,"HyperDash":false},{"StartTime":79620.0,"Position":322.0607,"HyperDash":false},{"StartTime":79735.0,"Position":333.615784,"HyperDash":false}]},{"StartTime":80122.0,"Objects":[{"StartTime":80122.0,"Position":240.0,"HyperDash":false},{"StartTime":80218.0,"Position":206.699463,"HyperDash":false},{"StartTime":80315.0,"Position":192.5893,"HyperDash":false},{"StartTime":80394.0,"Position":180.9993,"HyperDash":false},{"StartTime":80509.0,"Position":144.773514,"HyperDash":false}]},{"StartTime":80703.0,"Objects":[{"StartTime":80703.0,"Position":64.0,"HyperDash":false}]},{"StartTime":80896.0,"Objects":[{"StartTime":80896.0,"Position":40.0,"HyperDash":false},{"StartTime":80992.0,"Position":52.30054,"HyperDash":false},{"StartTime":81089.0,"Position":87.4107056,"HyperDash":false},{"StartTime":81168.0,"Position":99.0006943,"HyperDash":false},{"StartTime":81283.0,"Position":135.226486,"HyperDash":false}]},{"StartTime":81671.0,"Objects":[{"StartTime":81671.0,"Position":248.0,"HyperDash":false},{"StartTime":81767.0,"Position":248.315552,"HyperDash":false},{"StartTime":81864.0,"Position":270.748962,"HyperDash":false},{"StartTime":81943.0,"Position":270.0607,"HyperDash":false},{"StartTime":82058.0,"Position":293.615784,"HyperDash":false}]},{"StartTime":82445.0,"Objects":[{"StartTime":82445.0,"Position":120.0,"HyperDash":false}]},{"StartTime":82832.0,"Objects":[{"StartTime":82832.0,"Position":312.0,"HyperDash":false}]},{"StartTime":83219.0,"Objects":[{"StartTime":83219.0,"Position":400.0,"HyperDash":false},{"StartTime":83297.0,"Position":406.999,"HyperDash":false},{"StartTime":83412.0,"Position":412.369324,"HyperDash":false}]},{"StartTime":83606.0,"Objects":[{"StartTime":83606.0,"Position":360.0,"HyperDash":false},{"StartTime":83684.0,"Position":344.762848,"HyperDash":false},{"StartTime":83799.0,"Position":342.0927,"HyperDash":false}]},{"StartTime":83993.0,"Objects":[{"StartTime":83993.0,"Position":272.0,"HyperDash":false},{"StartTime":84089.0,"Position":267.17865,"HyperDash":false},{"StartTime":84186.0,"Position":223.813,"HyperDash":false},{"StartTime":84265.0,"Position":218.85318,"HyperDash":false},{"StartTime":84380.0,"Position":179.797424,"HyperDash":false}]},{"StartTime":84767.0,"Objects":[{"StartTime":84767.0,"Position":80.0,"HyperDash":false},{"StartTime":84845.0,"Position":91.5179,"HyperDash":false},{"StartTime":84960.0,"Position":96.12762,"HyperDash":false}]},{"StartTime":85154.0,"Objects":[{"StartTime":85154.0,"Position":16.0,"HyperDash":false},{"StartTime":85232.0,"Position":0.0,"HyperDash":false},{"StartTime":85347.0,"Position":16.0,"HyperDash":false}]},{"StartTime":85542.0,"Objects":[{"StartTime":85542.0,"Position":104.0,"HyperDash":false},{"StartTime":85638.0,"Position":112.302322,"HyperDash":false},{"StartTime":85735.0,"Position":154.868225,"HyperDash":false},{"StartTime":85814.0,"Position":182.689911,"HyperDash":false},{"StartTime":85929.0,"Position":206.0,"HyperDash":false}]},{"StartTime":86316.0,"Objects":[{"StartTime":86316.0,"Position":376.0,"HyperDash":false},{"StartTime":86412.0,"Position":382.0039,"HyperDash":false},{"StartTime":86509.0,"Position":424.2578,"HyperDash":false},{"StartTime":86588.0,"Position":445.011047,"HyperDash":false},{"StartTime":86703.0,"Position":472.7657,"HyperDash":false}]},{"StartTime":87090.0,"Objects":[{"StartTime":87090.0,"Position":296.0,"HyperDash":false},{"StartTime":87186.0,"Position":311.353729,"HyperDash":false},{"StartTime":87283.0,"Position":308.602417,"HyperDash":false},{"StartTime":87362.0,"Position":307.240021,"HyperDash":false},{"StartTime":87477.0,"Position":312.385956,"HyperDash":false}]},{"StartTime":87864.0,"Objects":[{"StartTime":87864.0,"Position":24.0,"HyperDash":false}]},{"StartTime":88251.0,"Objects":[{"StartTime":88251.0,"Position":249.0,"HyperDash":false},{"StartTime":88347.0,"Position":233.0,"HyperDash":false},{"StartTime":88444.0,"Position":449.0,"HyperDash":false},{"StartTime":88541.0,"Position":411.0,"HyperDash":false},{"StartTime":88638.0,"Position":75.0,"HyperDash":false},{"StartTime":88735.0,"Position":474.0,"HyperDash":false},{"StartTime":88831.0,"Position":176.0,"HyperDash":false},{"StartTime":88928.0,"Position":1.0,"HyperDash":false},{"StartTime":89025.0,"Position":37.0,"HyperDash":false},{"StartTime":89122.0,"Position":481.0,"HyperDash":false},{"StartTime":89219.0,"Position":375.0,"HyperDash":false},{"StartTime":89315.0,"Position":407.0,"HyperDash":false},{"StartTime":89412.0,"Position":231.0,"HyperDash":false},{"StartTime":89509.0,"Position":338.0,"HyperDash":false},{"StartTime":89606.0,"Position":322.0,"HyperDash":false},{"StartTime":89703.0,"Position":347.0,"HyperDash":false},{"StartTime":89800.0,"Position":365.0,"HyperDash":false}]}]} \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1041052.osu b/osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1041052.osu new file mode 100644 index 0000000000..a0cecc1b18 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1041052.osu @@ -0,0 +1,210 @@ +osu file format v14 + +[General] +AudioFilename: audio.mp3 +AudioLeadIn: 0 +PreviewTime: 65316 +Countdown: 0 +SampleSet: Soft +StackLeniency: 0.7 +Mode: 2 +LetterboxInBreaks: 0 +WidescreenStoryboard: 0 + +[Editor] +DistanceSpacing: 1.4 +BeatDivisor: 4 +GridSize: 8 +TimelineZoom: 1.4 + +[Metadata] +Title:Nanairo Symphony -TV Size- +TitleUnicode:七色シンフォニー -TV Size- +Artist:Coalamode. +ArtistUnicode:コアラモード. +Creator:Ascendance +Version:Aru's Cup +Source:四月は君の嘘 +Tags:shigatsu wa kimi no uso your lie in april opening arusamour tenshichan [superstar] +BeatmapID:1041052 +BeatmapSetID:488149 + +[Difficulty] +HPDrainRate:3 +CircleSize:2.5 +OverallDifficulty:6 +ApproachRate:6 +SliderMultiplier:1.02 +SliderTickRate:2 + +[Events] +//Background and Video events +Video,500,"forty.avi" +0,0,"cropped-1366-768-647733.jpg",0,0 +//Break Periods +//Storyboard Layer 0 (Background) +//Storyboard Layer 1 (Fail) +//Storyboard Layer 2 (Pass) +//Storyboard Layer 3 (Foreground) +//Storyboard Sound Samples + +[TimingPoints] +1155,387.096774193548,4,2,1,50,1,0 +15284,-100,4,2,1,60,0,0 +16638,-100,4,2,1,50,0,0 +41413,-100,4,2,1,60,0,0 +59993,-100,4,2,1,65,0,0 +66187,-100,4,2,1,70,0,1 +87284,-100,4,2,1,60,0,1 +87864,-100,4,2,1,70,0,0 +87961,-100,4,2,1,50,0,0 +88638,-100,4,2,1,30,0,0 +89413,-100,4,2,1,10,0,0 +89800,-100,4,2,1,5,0,0 + + +[Colours] +Combo1 : 255,128,64 +Combo2 : 0,128,255 +Combo3 : 255,128,192 +Combo4 : 0,128,192 + +[HitObjects] +208,160,1155,6,0,L|45:160,1,153,2|2,0:0|0:0,0:0:0:0: +160,160,2122,1,0,0:0:0:0: +272,160,2509,1,2,0:0:0:0: +448,288,3284,6,0,P|480:240|480:192,1,102,2|0,0:0|0:0,0:0:0:0: +384,96,4058,1,2,0:0:0:0: +128,64,5025,6,0,L|32:64,2,76.5,2|0|0,0:0|0:0|0:0,0:0:0:0: +192,64,5800,1,2,0:0:0:0: +240,64,5993,1,2,0:0:0:0: +288,64,6187,1,2,0:0:0:0: +416,80,6574,6,0,L|192:80,1,204,0|2,0:0|0:0,0:0:0:0: +488,160,8122,2,0,L|376:160,1,102 +457,288,8896,2,0,L|297:288,1,153,2|2,0:0|0:0,0:0:0:0: +400,288,10058,1,0,0:0:0:0: +304,288,10445,6,0,L|192:288,2,102,2|0|2,0:0|0:0|0:0,0:0:0:0: +400,288,11606,1,0,0:0:0:0: +240,288,11993,2,0,L|80:288,1,153,2|0,0:0|0:0,0:0:0:0: +0,288,13154,1,0,0:0:0:0: +112,240,13542,6,0,P|160:288|256:288,1,153,6|2,0:0|0:0,0:0:0:0: +288,288,14316,2,0,L|368:288,2,76.5,2|0|0,0:0|0:0|0:0,0:0:0:0: +192,288,15284,2,0,L|160:224,1,51,0|12,0:0|0:0,0:0:0:0: +312,208,15864,1,6,0:0:0:0: +128,176,16638,6,0,P|64:160|0:96,2,153,6|2|0,0:0|0:0|0:0,0:0:0:0: +224,176,18187,2,0,P|288:192|352:272,2,153,2|2|0,0:0|0:0|0:0,0:0:0:0: +128,176,19735,6,0,L|288:176,1,153,2|2,0:0|0:0,0:0:0:0: +432,176,20896,1,0,0:0:0:0: +328,176,21284,2,0,L|488:176,1,153,2|2,0:0|0:0,0:0:0:0: +328,176,22445,1,0,0:0:0:0: +224,176,22832,6,0,L|64:176,1,153,2|2,0:0|0:0,0:0:0:0: +224,176,23993,1,0,0:0:0:0: +112,176,24380,2,0,L|272:176,1,153,2|2,0:0|0:0,0:0:0:0: +416,176,25541,1,0,0:0:0:0: +304,256,25929,6,0,P|272:208|312:120,1,153,2|2,0:0|0:0,0:0:0:0: +480,112,27090,1,0,0:0:0:0: +384,112,27477,6,0,L|320:112,2,51,2|2|0,0:0|0:0|0:0,0:0:0:0: +432,112,28058,1,2,0:0:0:0: +333,112,28445,2,0,L|282:112,2,51,0|0|0,0:0|0:0|0:0,0:0:0:0: +384,112,29025,6,0,L|272:112,1,102,6|0,0:0|0:0,0:0:0:0: +224,112,29606,2,0,P|160:144|160:240,1,153,2|2,0:0|0:0,0:0:0:0: +272,272,30574,2,0,L|374:272,1,102 +424,272,31154,2,0,P|414:344|348:378,1,153,0|0,0:0|0:0,0:0:0:0: +224,304,32122,6,0,P|176:320|144:368,1,102,2|0,0:0|0:0,0:0:0:0: +200,368,32703,1,2,0:0:0:0: +376,368,33284,1,0,0:0:0:0: +304,296,33671,2,0,L|240:296,2,51,2|2|0,0:0|0:0|0:0,0:0:0:0: +352,296,34251,2,0,P|400:248|384:168,1,153,2|0,0:0|0:0,0:0:0:0: +280,176,35219,6,0,L|216:80,1,102,2|0,0:0|0:0,0:0:0:0: +272,104,35800,2,0,L|336:8,1,102,2|0,0:0|0:0,0:0:0:0: +280,16,36380,1,2,0:0:0:0: +176,32,36767,6,0,L|112:128,1,102,2|0,0:0|0:0,0:0:0:0: +168,128,37348,2,0,L|232:224,1,102,2|0,0:0|0:0,0:0:0:0: +176,224,37928,1,2,0:0:0:0: +304,264,38316,6,0,L|200:264,1,102,2|0,0:0|0:0,0:0:0:0: +144,264,38896,1,2,0:0:0:0: +280,336,39477,2,0,L|336:336,1,51 +424,336,39864,2,0,P|440:304|416:240,1,102,8|0,0:3|0:3,0:3:0:0: +352,232,40445,1,4,0:1:0:0: +160,224,41025,1,8,0:3:0:0: +256,48,41413,6,0,P|302:28|353:31,1,102,6|0,0:0|0:0,0:0:0:0: +400,40,41993,1,0,0:0:0:0: +440,80,42187,2,0,P|389:76|342:96,1,102,2|8,0:0|0:0,0:0:0:0: +248,128,42961,2,0,P|312:176|392:144,2,153,2|2|8,0:0|0:0|0:3,0:0:0:0: +144,136,44509,6,0,P|80:88|0:120,1,153,2|0,0:0|0:0,0:0:0:0: +56,136,45284,1,2,0:0:0:0: +160,144,45671,1,8,0:0:0:0: +264,144,46058,2,0,L|384:144,1,102,2|0,0:0|0:0,0:0:0:0: +416,152,46638,2,0,L|264:152,1,153,2|8,0:0|0:3,0:0:0:0: +360,120,47606,6,0,L|192:120,1,153,2|0,0:0|0:0,0:0:0:0: +160,128,48380,2,0,P|208:80|256:96,1,102,2|8,0:0|0:0,0:0:0:0: +144,136,49154,1,2,0:0:0:0: +248,144,49542,2,0,L|368:144,1,102,0|2,0:0|0:0,0:0:0:0: +256,192,50316,2,0,L|200:192,1,51,10|0,0:0|0:0,0:0:0:0: +256,184,50703,6,0,L|360:184,1,102,2|0,0:0|0:0,0:0:0:0: +400,208,51284,1,0,0:0:0:0: +352,240,51477,2,0,L|240:240,1,102 +128,336,52251,6,0,P|64:336|0:256,1,153,2|2,0:0|0:0,0:0:0:0: +88,264,53025,1,2,0:0:0:0: +168,208,53413,2,0,L|152:144,1,51,8|8,0:0|0:3,0:0:0:0: +248,120,53800,6,0,P|328:152|392:120,1,153,6|0,0:0|0:0,0:0:0:0: +432,120,54574,1,2,0:0:0:0: +328,128,54961,1,8,0:0:0:0: +224,128,55348,6,0,L|112:144,1,102,2|0,0:0|0:0,0:0:0:0: +72,152,55929,2,0,L|192:176,1,102,2|0,0:0|0:0,0:0:0:0: +224,184,56509,1,8,0:3:0:0: +328,176,56896,6,0,P|376:208|472:192,1,153,2|0,0:0|0:0,0:0:0:0: +416,208,57671,2,0,L|304:240,1,102,2|8,0:0|0:0,0:0:0:0: +224,272,58445,5,2,0:0:0:0: +320,296,58832,1,0,0:0:0:0: +224,328,59219,1,2,0:0:0:0: +120,328,59606,1,8,0:3:0:0: +224,264,59993,6,0,P|224:200|192:152,1,102,6|0,0:0|0:0,0:0:0:0: +80,184,60767,2,0,P|76:133|97:87,1,102,2|8,0:0|0:0,0:0:0:0: +200,80,61542,2,0,P|232:112|296:112,1,102,2|0,0:0|0:0,0:0:0:0: +376,160,62316,2,0,P|344:192|280:192,1,102,2|8,0:0|0:0,0:0:0:0: +184,240,63090,6,0,L|200:128,1,102,2|8,0:0|0:0,0:0:0:0: +88,136,63864,2,0,L|8:152,2,76.5,6|2|2,0:0|0:0|0:0,0:0:0:0: +160,112,64638,1,8,0:0:0:0: +208,128,64832,1,8,0:0:0:0: +256,144,65025,1,8,0:0:0:0: +360,152,65413,6,0,L|424:152,1,51,8|0,0:0|0:0,0:0:0:0: +462,152,65800,2,0,L|398:152,1,51,8|8,0:0|0:3,0:0:0:0: +344,144,66187,6,0,L|232:144,1,102,12|8,0:0|0:0,0:0:0:0: +152,120,66961,2,0,P|148:169|107:196,1,102,8|8,0:0|0:0,0:0:0:0: +32,264,67735,6,0,L|144:216,1,102,8|8,0:0|0:0,0:0:0:0: +176,208,68316,1,0,0:0:0:0: +224,200,68509,2,0,L|317:240,1,102,8|8,0:0|0:0,0:0:0:0: +216,256,69284,6,0,P|184:304|200:352,1,102,8|8,0:0|0:0,0:0:0:0: +360,256,70058,2,0,P|368:207|337:167,1,102,8|8,0:0|0:0,0:0:0:0: +264,80,70832,6,0,L|152:96,1,102,8|8,0:0|0:0,0:0:0:0: +112,104,71413,2,0,L|11:89,1,102,8|0,0:0|0:0,0:0:0:0: +40,128,71993,2,0,L|72:176,1,51,8|8,0:0|0:3,0:0:0:0: +176,216,72380,6,0,P|144:280|64:280,1,153,12|0,0:0|0:0,0:0:0:0: +120,280,73154,2,0,P|191:299|216:328,1,102,8|8,0:0|0:0,0:0:0:0: +312,320,73929,6,0,L|424:304,1,102,8|8,0:0|0:0,0:0:0:0: +336,272,74703,2,0,L|312:216,1,51,8|0,0:0|0:0,0:0:0:0: +400,200,75090,2,0,L|424:136,1,51,8|0,0:0|0:0,0:0:0:0: +328,152,75477,6,0,P|280:184|200:136,1,153,12|0,0:0|0:0,0:0:0:0: +296,136,76251,2,0,P|360:136|408:168,1,102,8|8,0:0|0:0,0:0:0:0: +152,248,77219,6,0,L|96:248,2,51,0|12|0,0:0|0:0|0:0,0:0:0:0: +208,248,77800,1,8,0:0:0:0: +320,256,78187,2,0,L|369:243,1,51,8|8,0:0|0:3,0:0:0:0: +456,232,78574,6,0,L|408:136,1,102,12|8,0:0|0:0,0:0:0:0: +288,136,79348,2,0,L|336:40,1,102,8|8,0:0|0:0,0:0:0:0: +240,80,80122,6,0,P|144:80|128:64,1,102,8|8,0:0|0:0,0:0:0:0: +96,72,80703,1,0,0:0:0:0: +40,104,80896,2,0,P|136:104|152:88,1,102,8|8,0:0|0:0,0:0:0:0: +248,128,81671,6,0,L|296:224,1,102,12|8,0:0|0:0,0:0:0:0: +208,272,82445,1,10,0:0:0:0: +312,272,82832,1,8,0:0:0:0: +400,224,83219,6,0,L|416:160,1,51,8|2,0:0|0:0,0:0:0:0: +360,56,83606,2,0,L|336:120,1,51,8|0,0:0|0:0,0:0:0:0: +272,152,83993,2,0,P|192:152|176:136,1,102,0|8,0:0|0:0,0:0:0:0: +80,160,84767,6,0,L|96:208,1,51,8|0,0:0|0:0,0:0:0:0: +16,272,85154,2,0,L|16:328,1,51,8|0,0:0|0:0,0:0:0:0: +104,304,85542,2,0,L|208:304,1,102,2|8,0:0|0:0,0:0:0:0: +376,336,86316,6,0,L|472:304,1,102,4|0,0:0|0:0,0:0:0:0: +296,248,87090,2,0,P|312:168|312:136,1,102,2|8,0:0|0:3,0:0:0:0: +168,96,87864,1,4,0:0:0:0: +256,192,88251,12,0,89800,0:0:0:0: From 285adcb00e65abbcaad8d6a7cffedcc416949ab5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 2 Mar 2024 00:19:45 +0300 Subject: [PATCH 692/915] Fix catch hit object position getting randomised when last object has pos=0 --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 200018f28b..198f8f59c6 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -118,7 +118,11 @@ namespace osu.Game.Rulesets.Catch.Beatmaps float offsetPosition = hitObject.OriginalX; double startTime = hitObject.StartTime; - if (lastPosition == null) + if (lastPosition == null || + // some objects can get assigned position zero, making stable incorrectly go inside this if branch on the next object. to maintain behaviour and compatibility, do the same here. + // reference: https://github.com/peppy/osu-stable-reference/blob/3ea48705eb67172c430371dcfc8a16a002ed0d3d/osu!/GameplayElements/HitObjects/Fruits/HitFactoryFruits.cs#L45-L50 + // todo: should be revisited and corrected later probably. + lastPosition == 0) { lastPosition = offsetPosition; lastStartTime = startTime; From 85f131d2f87f7da733c542a38ae8cd6804a43f89 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 2 Mar 2024 22:45:15 +0300 Subject: [PATCH 693/915] Fix "unranked explaination" tooltip text using incorrect translation key --- osu.Game/Localisation/ModSelectOverlayStrings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/ModSelectOverlayStrings.cs b/osu.Game/Localisation/ModSelectOverlayStrings.cs index 9513eacf02..7a9bb698d8 100644 --- a/osu.Game/Localisation/ModSelectOverlayStrings.cs +++ b/osu.Game/Localisation/ModSelectOverlayStrings.cs @@ -67,7 +67,7 @@ namespace osu.Game.Localisation /// /// "Performance points will not be granted due to active mods." /// - public static LocalisableString UnrankedExplanation => new TranslatableString(getKey(@"ranked_explanation"), @"Performance points will not be granted due to active mods."); + public static LocalisableString UnrankedExplanation => new TranslatableString(getKey(@"unranked_explanation"), @"Performance points will not be granted due to active mods."); private static string getKey(string key) => $@"{prefix}:{key}"; } From bce3bd55e5a863e52f41598c306a248a79638843 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 4 Mar 2024 16:08:17 +0900 Subject: [PATCH 694/915] Fix catch by moving cursor-specific handling local --- .../TestSceneResumeOverlay.cs | 16 +++++++++++++--- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 7 +++++++ osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- osu.Game/Screens/Play/ResumeOverlay.cs | 3 ++- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs index 25d0b0a3d3..b35984a2fc 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs @@ -6,11 +6,11 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osu.Game.Tests.Gameplay; using osu.Game.Tests.Visual; @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Tests public partial class TestSceneResumeOverlay : OsuManualInputManagerTestScene { private ManualOsuInputManager osuInputManager = null!; - private CursorContainer cursor = null!; + private GameplayCursorContainer cursor = null!; private ResumeOverlay resume = null!; private bool resumeFired; @@ -99,7 +99,17 @@ namespace osu.Game.Rulesets.Osu.Tests private void loadContent() { - Child = osuInputManager = new ManualOsuInputManager(new OsuRuleset().RulesetInfo) { Children = new Drawable[] { cursor = new CursorContainer(), resume = new OsuResumeOverlay { GameplayCursor = cursor }, } }; + Child = osuInputManager = new ManualOsuInputManager(new OsuRuleset().RulesetInfo) + { + Children = new Drawable[] + { + cursor = new GameplayCursorContainer(), + resume = new OsuResumeOverlay + { + GameplayCursor = cursor + }, + } + }; resumeFired = false; resume.ResumeAction = () => resumeFired = true; diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 8a84fe14e5..adc7bd97ff 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -39,6 +39,13 @@ namespace osu.Game.Rulesets.Osu.UI protected override void PopIn() { + // Can't display if the cursor is outside the window. + if (GameplayCursor.LastFrameState == Visibility.Hidden || !Contains(GameplayCursor.ActiveCursor.ScreenSpaceDrawQuad.Centre)) + { + Resume(); + return; + } + base.PopIn(); GameplayCursor.ActiveCursor.Hide(); diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 4aeb3d4862..218fdf5b86 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -227,7 +227,7 @@ namespace osu.Game.Rulesets.UI public override void RequestResume(Action continueResume) { - if (ResumeOverlay != null && UseResumeOverlay && (Cursor == null || (Cursor.LastFrameState == Visibility.Visible && Contains(Cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre)))) + if (ResumeOverlay != null && UseResumeOverlay) { ResumeOverlay.GameplayCursor = Cursor; ResumeOverlay.ResumeAction = continueResume; diff --git a/osu.Game/Screens/Play/ResumeOverlay.cs b/osu.Game/Screens/Play/ResumeOverlay.cs index fae406bd6b..a33dd79888 100644 --- a/osu.Game/Screens/Play/ResumeOverlay.cs +++ b/osu.Game/Screens/Play/ResumeOverlay.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.UI; using osuTK; using osuTK.Graphics; @@ -21,7 +22,7 @@ namespace osu.Game.Screens.Play /// public abstract partial class ResumeOverlay : VisibilityContainer { - public CursorContainer GameplayCursor { get; set; } + public GameplayCursorContainer GameplayCursor { get; set; } /// /// The action to be performed to complete resuming. From 6635d9be04952b43b41ff8e3f2596999a069ff74 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 4 Mar 2024 16:08:25 +0900 Subject: [PATCH 695/915] Add countdown display --- .../UI/DrawableCatchRuleset.cs | 3 +- .../Gameplay/TestSceneDelayedResumeOverlay.cs | 44 ++++++ osu.Game/Screens/Play/DelayedResumeOverlay.cs | 135 +++++++++++++++++- 3 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneDelayedResumeOverlay.cs diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index 580c90bcb4..32ebdc1159 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osuTK; namespace osu.Game.Rulesets.Catch.UI { @@ -54,6 +55,6 @@ namespace osu.Game.Rulesets.Catch.UI public override DrawableHitObject? CreateDrawableRepresentation(CatchHitObject h) => null; - protected override ResumeOverlay CreateResumeOverlay() => new DelayedResumeOverlay(); + protected override ResumeOverlay CreateResumeOverlay() => new DelayedResumeOverlay { Scale = new Vector2(0.65f) }; } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDelayedResumeOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDelayedResumeOverlay.cs new file mode 100644 index 0000000000..241a78b6b8 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDelayedResumeOverlay.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Play; +using osu.Game.Tests.Gameplay; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public partial class TestSceneDelayedResumeOverlay : OsuTestScene + { + private ResumeOverlay resume = null!; + private bool resumeFired; + + [Cached] + private GameplayState gameplayState; + + public TestSceneDelayedResumeOverlay() + { + gameplayState = TestGameplayState.Create(new OsuRuleset()); + } + + [SetUp] + public void SetUp() => Schedule(loadContent); + + [Test] + public void TestResume() + { + AddStep("show", () => resume.Show()); + AddUntilStep("dismissed", () => resumeFired && resume.State.Value == Visibility.Hidden); + } + + private void loadContent() + { + Child = resume = new DelayedResumeOverlay(); + + resumeFired = false; + resume.ResumeAction = () => resumeFired = true; + } + } +} diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index ef39c8eb76..6f70a914f0 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -1,8 +1,18 @@ // 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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Threading; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Play { @@ -11,21 +21,140 @@ namespace osu.Game.Screens.Play /// public partial class DelayedResumeOverlay : ResumeOverlay { + private const double countdown_time = 800; + protected override LocalisableString Message => string.Empty; + [Resolved] + private OsuColour colours { get; set; } = null!; + private ScheduledDelegate? scheduledResume; + private int countdownCount = 3; + private double countdownStartTime; + + private Drawable content = null!; + private Drawable background = null!; + private SpriteText countdown = null!; + + public DelayedResumeOverlay() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + [BackgroundDependencyLoader] + private void load() + { + Add(content = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Masking = true, + BorderColour = colours.Yellow, + BorderThickness = 1, + Children = new[] + { + background = new Box + { + Size = new Vector2(250, 40), + Colour = Color4.Black, + Alpha = 0.8f + }, + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(5), + Colour = colours.Yellow, + Children = new Drawable[] + { + // new Box + // { + // Anchor = Anchor.Centre, + // Origin = Anchor.Centre, + // Size = new Vector2(40, 3) + // }, + countdown = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + UseFullGlyphHeight = false, + AlwaysPresent = true, + Font = OsuFont.Numeric.With(size: 20, fixedWidth: true) + }, + // new Box + // { + // Anchor = Anchor.Centre, + // Origin = Anchor.Centre, + // Size = new Vector2(40, 3) + // } + } + } + } + } + } + }); + } protected override void PopIn() { - base.PopIn(); + this.FadeIn(); + + content.FadeInFromZero(150, Easing.OutQuint); + content.ScaleTo(new Vector2(1.5f, 1)).Then().ScaleTo(1, 150, Easing.OutElasticQuarter); + + countdownCount = 3; + countdownStartTime = Time.Current; scheduledResume?.Cancel(); - scheduledResume = Scheduler.AddDelayed(Resume, 800); + scheduledResume = Scheduler.AddDelayed(Resume, countdown_time); + } + + protected override void Update() + { + base.Update(); + updateCountdown(); + } + + private void updateCountdown() + { + double amountTimePassed = Math.Min(countdown_time, Time.Current - countdownStartTime) / countdown_time; + int newCount = 3 - (int)Math.Floor(amountTimePassed * 3); + + if (newCount > 0) + { + countdown.Alpha = 1; + countdown.Text = newCount.ToString(); + } + else + countdown.Alpha = 0; + + if (newCount != countdownCount) + { + if (newCount == 0) + content.ScaleTo(new Vector2(1.5f, 1), 150, Easing.OutQuint); + else + content.ScaleTo(new Vector2(1.05f, 1), 50, Easing.OutQuint).Then().ScaleTo(1, 50, Easing.Out); + } + + countdownCount = newCount; } protected override void PopOut() { - base.PopOut(); + this.Delay(150).FadeOut(); + + content.FadeOut(150, Easing.OutQuint); + scheduledResume?.Cancel(); } } From af2b80e0304e9541378fa9fa68caad0ca347a37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 4 Mar 2024 11:28:34 +0100 Subject: [PATCH 696/915] Add failing encode test --- .../Formats/LegacyScoreDecoderTest.cs | 2 +- .../Formats/LegacyScoreEncoderTest.cs | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs index 7e3967dc95..43e471320e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs @@ -432,7 +432,7 @@ namespace osu.Game.Tests.Beatmaps.Formats CultureInfo.CurrentCulture = originalCulture; } - private class TestLegacyScoreDecoder : LegacyScoreDecoder + public class TestLegacyScoreDecoder : LegacyScoreDecoder { private readonly int beatmapVersion; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs new file mode 100644 index 0000000000..c0a7285f39 --- /dev/null +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs @@ -0,0 +1,55 @@ +// 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.IO; +using NUnit.Framework; +using osu.Game.Beatmaps.Formats; +using osu.Game.Rulesets.Catch; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Scoring.Legacy; +using osu.Game.Tests.Resources; + +namespace osu.Game.Tests.Beatmaps.Formats +{ + public class LegacyScoreEncoderTest + { + [TestCase(1, 3)] + [TestCase(1, 0)] + [TestCase(0, 3)] + public void CatchMergesFruitAndDropletMisses(int missCount, int largeTickMissCount) + { + var ruleset = new CatchRuleset().RulesetInfo; + + var scoreInfo = TestResources.CreateTestScoreInfo(ruleset); + var beatmap = new TestBeatmap(ruleset); + scoreInfo.Statistics = new Dictionary + { + [HitResult.Great] = 50, + [HitResult.LargeTickHit] = 5, + [HitResult.Miss] = missCount, + [HitResult.LargeTickMiss] = largeTickMissCount + }; + var score = new Score { ScoreInfo = scoreInfo }; + + var decodedAfterEncode = encodeThenDecode(LegacyBeatmapDecoder.LATEST_VERSION, score, beatmap); + + Assert.That(decodedAfterEncode.ScoreInfo.GetCountMiss(), Is.EqualTo(missCount + largeTickMissCount)); + } + + private static Score encodeThenDecode(int beatmapVersion, Score score, TestBeatmap beatmap) + { + var encodeStream = new MemoryStream(); + + var encoder = new LegacyScoreEncoder(score, beatmap); + encoder.Encode(encodeStream); + + var decodeStream = new MemoryStream(encodeStream.GetBuffer()); + + var decoder = new LegacyScoreDecoderTest.TestLegacyScoreDecoder(beatmapVersion); + var decodedAfterEncode = decoder.Parse(decodeStream); + return decodedAfterEncode; + } + } +} From dcd6b028090a97ea1b2c43a374bb9210417b0adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 4 Mar 2024 11:35:31 +0100 Subject: [PATCH 697/915] Fix incorrect implementation of `GetCountMiss()` for catch --- .../Scoring/Legacy/ScoreInfoExtensions.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs index 07c35a334f..23624401e2 100644 --- a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs @@ -198,10 +198,25 @@ namespace osu.Game.Scoring.Legacy } } - public static int? GetCountMiss(this ScoreInfo scoreInfo) => - getCount(scoreInfo, HitResult.Miss); + public static int? GetCountMiss(this ScoreInfo scoreInfo) + { + switch (scoreInfo.Ruleset.OnlineID) + { + case 0: + case 1: + case 3: + return getCount(scoreInfo, HitResult.Miss); + + case 2: + return (getCount(scoreInfo, HitResult.Miss) ?? 0) + (getCount(scoreInfo, HitResult.LargeTickMiss) ?? 0); + } + + return null; + } public static void SetCountMiss(this ScoreInfo scoreInfo, int value) => + // this does not match the implementation of `GetCountMiss()` for catch, + // but we physically cannot recover that data anymore at this point. scoreInfo.Statistics[HitResult.Miss] = value; private static int? getCount(ScoreInfo scoreInfo, HitResult result) From b896d97a4f844498e0c1c914a0b70c4fdf70449f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 4 Mar 2024 11:45:44 +0100 Subject: [PATCH 698/915] Fix catch pp calculator not matching live with respect to miss handling --- .../Difficulty/CatchPerformanceCalculator.cs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index b30b85be2d..d07f25ba90 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -2,22 +2,21 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Scoring.Legacy; namespace osu.Game.Rulesets.Catch.Difficulty { public class CatchPerformanceCalculator : PerformanceCalculator { - private int fruitsHit; - private int ticksHit; - private int tinyTicksHit; - private int tinyTicksMissed; - private int misses; + private int num300; + private int num100; + private int num50; + private int numKatu; + private int numMiss; public CatchPerformanceCalculator() : base(new CatchRuleset()) @@ -28,11 +27,11 @@ namespace osu.Game.Rulesets.Catch.Difficulty { var catchAttributes = (CatchDifficultyAttributes)attributes; - fruitsHit = score.Statistics.GetValueOrDefault(HitResult.Great); - ticksHit = score.Statistics.GetValueOrDefault(HitResult.LargeTickHit); - tinyTicksHit = score.Statistics.GetValueOrDefault(HitResult.SmallTickHit); - tinyTicksMissed = score.Statistics.GetValueOrDefault(HitResult.SmallTickMiss); - misses = score.Statistics.GetValueOrDefault(HitResult.Miss); + num300 = score.GetCount300() ?? 0; // HitResult.Great + num100 = score.GetCount100() ?? 0; // HitResult.LargeTickHit + num50 = score.GetCount50() ?? 0; // HitResult.SmallTickHit + numKatu = score.GetCountKatu() ?? 0; // HitResult.SmallTickMiss + numMiss = score.GetCountMiss() ?? 0; // HitResult.Miss PLUS HitResult.LargeTickMiss // We are heavily relying on aim in catch the beat double value = Math.Pow(5.0 * Math.Max(1.0, catchAttributes.StarRating / 0.0049) - 4.0, 2.0) / 100000.0; @@ -45,7 +44,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty (numTotalHits > 2500 ? Math.Log10(numTotalHits / 2500.0) * 0.475 : 0.0); value *= lengthBonus; - value *= Math.Pow(0.97, misses); + value *= Math.Pow(0.97, numMiss); // Combo scaling if (catchAttributes.MaxCombo > 0) @@ -86,8 +85,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty } private double accuracy() => totalHits() == 0 ? 0 : Math.Clamp((double)totalSuccessfulHits() / totalHits(), 0, 1); - private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; - private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; - private int totalComboHits() => misses + ticksHit + fruitsHit; + private int totalHits() => num50 + num100 + num300 + numMiss + numKatu; + private int totalSuccessfulHits() => num50 + num100 + num300; + private int totalComboHits() => numMiss + num100 + num300; } } From 405958f73c560b5c3eae381255d5141e37c819c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 4 Mar 2024 14:43:53 +0100 Subject: [PATCH 699/915] Add test scene for drawable ranks --- .../Visual/Ranking/TestSceneDrawableRank.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 osu.Game.Tests/Visual/Ranking/TestSceneDrawableRank.cs diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneDrawableRank.cs b/osu.Game.Tests/Visual/Ranking/TestSceneDrawableRank.cs new file mode 100644 index 0000000000..804c8dfc44 --- /dev/null +++ b/osu.Game.Tests/Visual/Ranking/TestSceneDrawableRank.cs @@ -0,0 +1,39 @@ +// 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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.Leaderboards; +using osu.Game.Scoring; +using osuTK; + +namespace osu.Game.Tests.Visual.Ranking +{ + public partial class TestSceneDrawableRank : OsuTestScene + { + [Test] + public void TestAllRanks() + { + AddStep("create content", () => Child = new FillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(20), + Spacing = new Vector2(10), + ChildrenEnumerable = Enum.GetValues().OrderBy(v => v).Select(rank => new DrawableRank(rank) + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(50, 25), + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }) + }); + } + } +} From 6080c14dd5b589c982b09365aa1b5eb74ccd14ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 4 Mar 2024 14:47:49 +0100 Subject: [PATCH 700/915] Update F rank badge colours to match latest designs --- osu.Game/Graphics/OsuColour.cs | 6 +++++- osu.Game/Online/Leaderboards/DrawableRank.cs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 985898958c..c479d0cfe4 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -63,8 +63,12 @@ namespace osu.Game.Graphics case ScoreRank.C: return Color4Extensions.FromHex(@"ff8e5d"); - default: + case ScoreRank.D: return Color4Extensions.FromHex(@"ff5a5a"); + + case ScoreRank.F: + default: + return Color4Extensions.FromHex(@"3f3f3f"); } } diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 5177f35478..0b0ab11410 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -95,8 +95,12 @@ namespace osu.Game.Online.Leaderboards case ScoreRank.C: return Color4Extensions.FromHex(@"473625"); - default: + case ScoreRank.D: return Color4Extensions.FromHex(@"512525"); + + case ScoreRank.F: + default: + return Color4Extensions.FromHex(@"CC3333"); } } } From 9543908c7ab23cc397522ccaa1cfdc97c9d791b1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 4 Mar 2024 23:36:45 +0300 Subject: [PATCH 701/915] Fix mod select overlay settings order not always matching panels order --- .../TestSceneModSelectOverlay.cs | 24 +++++++++++++++++++ osu.Game/Overlays/Mods/ModSettingsArea.cs | 11 +++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index b26e126249..6c75530a6e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -859,6 +859,30 @@ namespace osu.Game.Tests.Visual.UserInterface () => modSelectOverlay.ChildrenOfType().Single().ModMultiplier.Value, () => Is.EqualTo(0.3).Within(Precision.DOUBLE_EPSILON)); } + [Test] + public void TestModSettingsOrder() + { + createScreen(); + + AddStep("select DT + HD + DF", () => SelectedMods.Value = new Mod[] { new OsuModDoubleTime(), new OsuModHidden(), new OsuModDeflate() }); + AddAssert("mod settings order: DT, HD, DF", () => + { + var columns = this.ChildrenOfType().Single().ChildrenOfType(); + return columns.ElementAt(0).Mod is OsuModDoubleTime && + columns.ElementAt(1).Mod is OsuModHidden && + columns.ElementAt(2).Mod is OsuModDeflate; + }); + + AddStep("replace DT with NC", () => SelectedMods.Value = SelectedMods.Value.Where(m => m is not ModDoubleTime).Append(new OsuModNightcore()).ToList()); + AddAssert("mod settings order: NC, HD, DF", () => + { + var columns = this.ChildrenOfType().Single().ChildrenOfType(); + return columns.ElementAt(0).Mod is OsuModNightcore && + columns.ElementAt(1).Mod is OsuModHidden && + columns.ElementAt(2).Mod is OsuModDeflate; + }); + } + private void waitForColumnLoad() => AddUntilStep("all column content loaded", () => modSelectOverlay.ChildrenOfType().Any() && modSelectOverlay.ChildrenOfType().All(column => column.IsLoaded && column.ItemsLoaded) diff --git a/osu.Game/Overlays/Mods/ModSettingsArea.cs b/osu.Game/Overlays/Mods/ModSettingsArea.cs index 54bfcc7199..d0e0f7e648 100644 --- a/osu.Game/Overlays/Mods/ModSettingsArea.cs +++ b/osu.Game/Overlays/Mods/ModSettingsArea.cs @@ -86,7 +86,10 @@ namespace osu.Game.Overlays.Mods { modSettingsFlow.Clear(); - foreach (var mod in SelectedMods.Value.AsOrdered()) + // Importantly, the selected mods bindable is already ordered by the mod select overlay (following the order of mod columns and panels). + // Using AsOrdered produces a slightly different order (e.g. DT and NC no longer becoming adjacent), + // which breaks user expectations when interacting with the overlay. + foreach (var mod in SelectedMods.Value) { var settings = mod.CreateSettingsControls().ToList(); @@ -110,10 +113,14 @@ namespace osu.Game.Overlays.Mods protected override bool OnMouseDown(MouseDownEvent e) => true; protected override bool OnHover(HoverEvent e) => true; - private partial class ModSettingsColumn : CompositeDrawable + public partial class ModSettingsColumn : CompositeDrawable { + public readonly Mod Mod; + public ModSettingsColumn(Mod mod, IEnumerable settingsControls) { + Mod = mod; + Width = 250; RelativeSizeAxes = Axes.Y; Padding = new MarginPadding { Bottom = 7 }; From 92f455f1995d32d380380b4a06adf34b21bfdc63 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 5 Mar 2024 03:01:01 +0300 Subject: [PATCH 702/915] Abstractify performance points calculation to a base class --- .../HUD/DefaultPerformancePointsCounter.cs | 91 +++++++++++++++++++ .../Play/HUD/PerformancePointsCounter.cs | 83 +---------------- 2 files changed, 93 insertions(+), 81 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/DefaultPerformancePointsCounter.cs diff --git a/osu.Game/Screens/Play/HUD/DefaultPerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/DefaultPerformancePointsCounter.cs new file mode 100644 index 0000000000..3c4e58e575 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/DefaultPerformancePointsCounter.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. + +#nullable disable + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Resources.Localisation.Web; +using osuTK; + +namespace osu.Game.Screens.Play.HUD +{ + public partial class DefaultPerformancePointsCounter : PerformancePointsCounter + { + protected override bool IsRollingProportional => true; + + protected override double RollingDuration => 500; + + private const float alpha_when_invalid = 0.3f; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.BlueLighter; + } + + public override bool IsValid + { + get => base.IsValid; + set + { + if (value == IsValid) + return; + + base.IsValid = value; + DrawableCount.FadeTo(value ? 1 : alpha_when_invalid, 1000, Easing.OutQuint); + } + } + + protected override LocalisableString FormatCount(int count) => count.ToString(@"D"); + + protected override IHasText CreateText() => new TextComponent + { + Alpha = alpha_when_invalid + }; + + private partial class TextComponent : CompositeDrawable, IHasText + { + public LocalisableString Text + { + get => text.Text; + set => text.Text = value; + } + + private readonly OsuSpriteText text; + + public TextComponent() + { + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(2), + Children = new Drawable[] + { + text = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.Numeric.With(size: 16, fixedWidth: true) + }, + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Text = BeatmapsetsStrings.ShowScoreboardHeaderspp, + Font = OsuFont.Numeric.With(size: 8), + Padding = new MarginPadding { Bottom = 1.5f }, // align baseline better + } + } + }; + } + } + } +} diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index f041e120f6..4b07e7da36 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -13,16 +13,9 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Localisation; using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Judgements; @@ -31,7 +24,6 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Skinning; -using osuTK; namespace osu.Game.Screens.Play.HUD { @@ -39,12 +31,6 @@ namespace osu.Game.Screens.Play.HUD { public bool UsesFixedAnchor { get; set; } - protected override bool IsRollingProportional => true; - - protected override double RollingDuration => 500; - - private const float alpha_when_invalid = 0.3f; - [Resolved] private ScoreProcessor scoreProcessor { get; set; } @@ -60,18 +46,11 @@ namespace osu.Game.Screens.Play.HUD private PerformanceCalculator performanceCalculator; private ScoreInfo scoreInfo; - public PerformancePointsCounter() - { - Current.Value = DisplayedCount = 0; - } - private Mod[] clonedMods; [BackgroundDependencyLoader] - private void load(OsuColour colours, BeatmapDifficultyCache difficultyCache) + private void load(BeatmapDifficultyCache difficultyCache) { - Colour = colours.BlueLighter; - if (gameplayState != null) { performanceCalculator = gameplayState.Ruleset.CreatePerformanceCalculator(); @@ -107,19 +86,7 @@ namespace osu.Game.Screens.Play.HUD onJudgementChanged(gameplayState.LastJudgementResult.Value); } - private bool isValid; - - protected bool IsValid - { - set - { - if (value == isValid) - return; - - isValid = value; - DrawableCount.FadeTo(isValid ? 1 : alpha_when_invalid, 1000, Easing.OutQuint); - } - } + public virtual bool IsValid { get; set; } private void onJudgementChanged(JudgementResult judgement) { @@ -151,13 +118,6 @@ namespace osu.Game.Screens.Play.HUD return timedAttributes[Math.Clamp(attribIndex, 0, timedAttributes.Count - 1)].Attributes; } - protected override LocalisableString FormatCount(int count) => count.ToString(@"D"); - - protected override IHasText CreateText() => new TextComponent - { - Alpha = alpha_when_invalid - }; - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -171,45 +131,6 @@ namespace osu.Game.Screens.Play.HUD loadCancellationSource?.Cancel(); } - private partial class TextComponent : CompositeDrawable, IHasText - { - public LocalisableString Text - { - get => text.Text; - set => text.Text = value; - } - - private readonly OsuSpriteText text; - - public TextComponent() - { - AutoSizeAxes = Axes.Both; - - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(2), - Children = new Drawable[] - { - text = new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Font = OsuFont.Numeric.With(size: 16, fixedWidth: true) - }, - new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Text = BeatmapsetsStrings.ShowScoreboardHeaderspp, - Font = OsuFont.Numeric.With(size: 8), - Padding = new MarginPadding { Bottom = 1.5f }, // align baseline better - } - } - }; - } - } - // TODO: This class shouldn't exist, but requires breaking changes to allow DifficultyCalculator to receive an IBeatmap. private class GameplayWorkingBeatmap : WorkingBeatmap { From 3ee57cdfba7c932dc4dbfb0351d644e1ce46c6d3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 5 Mar 2024 03:01:46 +0300 Subject: [PATCH 703/915] Refactor performance points test scene to support skinning --- .../SkinnableHUDComponentTestScene.cs | 13 ++- .../TestScenePerformancePointsCounter.cs | 96 ++++++++----------- .../TestSceneSkinnableAccuracyCounter.cs | 6 +- .../TestSceneSkinnableHealthDisplay.cs | 6 +- .../Play/HUD/ArgonPerformancePointsCounter.cs | 9 ++ 5 files changed, 65 insertions(+), 65 deletions(-) create mode 100644 osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs diff --git a/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs b/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs index f54f50795e..7933647dd2 100644 --- a/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs +++ b/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs @@ -1,8 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Skinning; @@ -13,8 +13,13 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset(); - [SetUp] - public void SetUp() => Schedule(() => + [SetUpSteps] + public virtual void SetUpSteps() + { + AddStep("setup components", SetUpComponents); + } + + public void SetUpComponents() { SetContents(skin => { @@ -28,7 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay implementation.Origin = Anchor.Centre; return implementation; }); - }); + } protected abstract Drawable CreateDefaultImplementation(); protected virtual Drawable CreateArgonImplementation() => CreateDefaultImplementation(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs index 9622caabf5..986167279c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs @@ -3,102 +3,88 @@ #nullable disable -using System; -using System.Diagnostics; +using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Testing; -using osu.Game.Rulesets; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; -using osuTK; +using osu.Game.Tests.Gameplay; namespace osu.Game.Tests.Visual.Gameplay { - public partial class TestScenePerformancePointsCounter : OsuTestScene + public partial class TestScenePerformancePointsCounter : SkinnableHUDComponentTestScene { - private DependencyProvidingContainer dependencyContainer; + [Cached(typeof(ScoreProcessor))] + private readonly ScoreProcessor scoreProcessor = new OsuScoreProcessor(); - private GameplayState gameplayState; - private ScoreProcessor scoreProcessor; + [Cached] + private readonly GameplayState gameplayState = TestGameplayState.Create(new OsuRuleset()); private int iteration; - private Bindable lastJudgementResult = new Bindable(); - private PerformancePointsCounter counter; - [SetUpSteps] - public void SetUpSteps() => AddStep("create components", () => + protected override Drawable CreateDefaultImplementation() => new DefaultPerformancePointsCounter(); + protected override Drawable CreateArgonImplementation() => new ArgonPerformancePointsCounter(); + protected override Drawable CreateLegacyImplementation() => Empty(); + + private Bindable lastJudgementResult => (Bindable)gameplayState.LastJudgementResult; + + public override void SetUpSteps() { - var ruleset = CreateRuleset(); - - Debug.Assert(ruleset != null); - - var beatmap = CreateWorkingBeatmap(ruleset.RulesetInfo) - .GetPlayableBeatmap(ruleset.RulesetInfo); - - lastJudgementResult = new Bindable(); - - gameplayState = new GameplayState(beatmap, ruleset); - gameplayState.LastJudgementResult.BindTo(lastJudgementResult); - - scoreProcessor = new ScoreProcessor(ruleset); - - Child = dependencyContainer = new DependencyProvidingContainer + AddStep("reset", () => { - RelativeSizeAxes = Axes.Both, - CachedDependencies = new (Type, object)[] - { - (typeof(GameplayState), gameplayState), - (typeof(ScoreProcessor), scoreProcessor) - } - }; + var ruleset = new OsuRuleset(); + var beatmap = CreateWorkingBeatmap(ruleset.RulesetInfo) + .GetPlayableBeatmap(ruleset.RulesetInfo); - iteration = 0; - }); + iteration = 0; + scoreProcessor.ApplyBeatmap(beatmap); + lastJudgementResult.SetDefault(); + }); - protected override Ruleset CreateRuleset() => new OsuRuleset(); + base.SetUpSteps(); + } - private void createCounter() => AddStep("Create counter", () => + [Test] + public void TestDisplay() { - dependencyContainer.Child = counter = new PerformancePointsCounter - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(5), - }; - }); + AddSliderStep("pp", 0, 2000, 0, v => this.ChildrenOfType().ForEach(c => c.Current.Value = v)); + AddToggleStep("toggle validity", v => this.ChildrenOfType().ForEach(c => c.IsValid = v)); + } [Test] public void TestBasicCounting() { int previousValue = 0; - createCounter(); - AddAssert("counter displaying zero", () => counter.Current.Value == 0); + AddAssert("counter displaying zero", () => this.ChildrenOfType().All(c => c.Current.Value == 0)); AddRepeatStep("Add judgement", applyOneJudgement, 10); - AddUntilStep("counter non-zero", () => counter.Current.Value > 0); - AddUntilStep("counter opaque", () => counter.Child.Alpha == 1); + AddUntilStep("counter non-zero", () => this.ChildrenOfType().All(c => c.Current.Value > 0)); + AddUntilStep("counter valid", () => this.ChildrenOfType().All(c => c.IsValid)); AddStep("Revert judgement", () => { - previousValue = counter.Current.Value; + previousValue = this.ChildrenOfType().First().Current.Value; scoreProcessor.RevertResult(new JudgementResult(new HitObject(), new OsuJudgement())); }); - AddUntilStep("counter decreased", () => counter.Current.Value < previousValue); + AddUntilStep("counter decreased", () => this.ChildrenOfType().All(c => c.Current.Value < previousValue)); AddStep("Add judgement", applyOneJudgement); - AddUntilStep("counter non-zero", () => counter.Current.Value > 0); + AddUntilStep("counter non-zero", () => this.ChildrenOfType().All(c => c.Current.Value > 0)); } [Test] @@ -106,10 +92,10 @@ namespace osu.Game.Tests.Visual.Gameplay { AddRepeatStep("Add judgement", applyOneJudgement, 10); - createCounter(); + AddStep("recreate counter", SetUpComponents); - AddUntilStep("counter non-zero", () => counter.Current.Value > 0); - AddUntilStep("counter opaque", () => counter.Child.Alpha == 1); + AddUntilStep("counter non-zero", () => this.ChildrenOfType().All(c => c.Current.Value > 0)); + AddUntilStep("counter valid", () => this.ChildrenOfType().All(c => c.IsValid)); } private void applyOneJudgement() diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs index e088d2ca87..d815b80cbc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Testing; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; @@ -21,10 +20,11 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Drawable CreateDefaultImplementation() => new DefaultAccuracyCounter(); protected override Drawable CreateLegacyImplementation() => new LegacyAccuracyCounter(); - [SetUpSteps] - public void SetUpSteps() + public override void SetUpSteps() { AddStep("Set initial accuracy", () => scoreProcessor.Accuracy.Value = 1); + + base.SetUpSteps(); } [Test] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs index 1849e8abd0..3fd6caf7f2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Testing; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; @@ -25,14 +24,15 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Drawable CreateDefaultImplementation() => new DefaultHealthDisplay { Scale = new Vector2(0.6f) }; protected override Drawable CreateLegacyImplementation() => new LegacyHealthDisplay { Scale = new Vector2(0.6f) }; - [SetUpSteps] - public void SetUpSteps() + public override void SetUpSteps() { AddStep(@"Reset all", delegate { healthProcessor.Health.Value = 1; healthProcessor.Failed += () => false; // health won't be updated if the processor gets into a "fail" state. }); + + base.SetUpSteps(); } protected override void Update() diff --git a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs new file mode 100644 index 0000000000..9e6b5f81e0 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs @@ -0,0 +1,9 @@ +// 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.Screens.Play.HUD +{ + public partial class ArgonPerformancePointsCounter : PerformancePointsCounter + { + } +} From d7f1e50d66b10529a37d48c99a79a6b0ef2b54f8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 5 Mar 2024 03:34:29 +0300 Subject: [PATCH 704/915] Add "Argon" performance points counter --- .../Play/HUD/ArgonPerformancePointsCounter.cs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs index 9e6b5f81e0..022c1fab9e 100644 --- a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs @@ -1,9 +1,79 @@ // 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.Bindables; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; +using osu.Game.Localisation.SkinComponents; +using osu.Game.Resources.Localisation.Web; + namespace osu.Game.Screens.Play.HUD { public partial class ArgonPerformancePointsCounter : PerformancePointsCounter { + private ArgonCounterTextComponent text = null!; + + protected override double RollingDuration => 250; + + private const float alpha_when_invalid = 0.3f; + + [SettingSource("Wireframe opacity", "Controls the opacity of the wire frames behind the digits.")] + public BindableFloat WireframeOpacity { get; } = new BindableFloat(0.25f) + { + Precision = 0.01f, + MinValue = 0, + MaxValue = 1, + }; + + [SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.ShowLabel), nameof(SkinnableComponentStrings.ShowLabelDescription))] + public Bindable ShowLabel { get; } = new BindableBool(true); + + public override bool IsValid + { + get => base.IsValid; + set + { + if (value == IsValid) + return; + + base.IsValid = value; + text.FadeTo(value ? 1 : alpha_when_invalid, 1000, Easing.OutQuint); + } + } + + public override int DisplayedCount + { + get => base.DisplayedCount; + set + { + base.DisplayedCount = value; + updateWireframe(); + } + } + + private void updateWireframe() + { + int digitsRequiredForDisplayCount = getDigitsRequiredForDisplayCount(); + + if (digitsRequiredForDisplayCount != text.WireframeTemplate.Length) + text.WireframeTemplate = new string('#', digitsRequiredForDisplayCount); + } + + private int getDigitsRequiredForDisplayCount() + { + int digitsRequired = 1; + long c = DisplayedCount; + while ((c /= 10) > 0) + digitsRequired++; + return digitsRequired; + } + + protected override IHasText CreateText() => text = new ArgonCounterTextComponent(Anchor.TopRight, BeatmapsetsStrings.ShowScoreboardHeaderspp.ToUpper()) + { + WireframeOpacity = { BindTarget = WireframeOpacity }, + ShowLabel = { BindTarget = ShowLabel }, + }; } } From 0cbcfcecdc3f777efe1adbda732787c26c294ff6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 5 Mar 2024 03:58:43 +0300 Subject: [PATCH 705/915] Integrate "Argon" performance points counter with HUD layout --- osu.Game/Skinning/ArgonSkin.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index 6fcab6a977..24e17d21f4 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -118,6 +118,7 @@ namespace osu.Game.Skinning var wedgePieces = container.OfType().ToArray(); var score = container.OfType().FirstOrDefault(); var accuracy = container.OfType().FirstOrDefault(); + var performancePoints = container.OfType().FirstOrDefault(); var combo = container.OfType().FirstOrDefault(); var songProgress = container.OfType().FirstOrDefault(); var keyCounter = container.OfType().FirstOrDefault(); @@ -159,6 +160,13 @@ namespace osu.Game.Skinning accuracy.Origin = Anchor.TopRight; } + if (performancePoints != null && accuracy != null) + { + performancePoints.Position = new Vector2(accuracy.X, accuracy.Y + accuracy.DrawHeight + 10); + performancePoints.Anchor = Anchor.TopRight; + performancePoints.Origin = Anchor.TopRight; + } + var hitError = container.OfType().FirstOrDefault(); if (hitError != null) @@ -224,6 +232,7 @@ namespace osu.Game.Skinning CornerRadius = { Value = 0.5f } }, new ArgonAccuracyCounter(), + new ArgonPerformancePointsCounter(), new ArgonComboCounter { Scale = new Vector2(1.3f) From b1477c30f2218ffd449f98f595c8a5c8a83fcfdf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 5 Mar 2024 04:30:57 +0300 Subject: [PATCH 706/915] Add deserialisation test coverage --- .../Archives/modified-argon-20240305.osk | Bin 0 -> 2390 bytes osu.Game.Tests/Skins/SkinDeserialisationTest.cs | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 osu.Game.Tests/Resources/Archives/modified-argon-20240305.osk diff --git a/osu.Game.Tests/Resources/Archives/modified-argon-20240305.osk b/osu.Game.Tests/Resources/Archives/modified-argon-20240305.osk new file mode 100644 index 0000000000000000000000000000000000000000..6db24352a5e62a877cc2c046fb8130a8dfe9c1b2 GIT binary patch literal 2390 zcmbVNdpMM7AAZL;hIZwA+Kb5{5i^>c%8oM`lZhc|8D~a}bzD}eNvX&oYbf7#IoD85 znQ zx&Z$T4RGBHC;`|Y&lo>~Z;+36V0Z}82`35&dQx6>|{D~0Dxe_rF|}$}{gv0a&zvpaR+JS2gei_Z{r6 z87#>GfE1Vk#*;v_ak4NE3H~{R=u36ctcavK4n??Er}?C(fI;N4mvuHB(cJ=N@i_Xs`G&VOh*bZ&H$FT@j$*ockJ1pgngB>G(%5QWRctuH-Q&R8ArZ5M z1H9NHQkeUH=$IVmLzVxB)esorb=T{1_})r0dP#!xds)$D)38HUEqyWFE=3=7>(y19 z>gh|aoJDIzN*$qdC?LNe^X#*%N)Fipbp^KUPLE$KQ1s!DBE^OyzjAI- zyC3dAXs5ODeFq~M4Y&(!n#egcOEun9LJeBWXf=ok{Z?TF#U?Ic%j_>LY2+^X^7^n! z7iNx%`9d#8Of`J0qJ1K?^an^i$aK4K)l&>5A<|@`6k*XV=|M0UzA`fYgVfas9!und zC$AD7henyTLM>(T-39S>HYQH#n3qxEzop-dUXYzOpAp?N=@325<9V>YFf6~d2;$h$ zMS9(O-qN^w!dHJ{K>aW4q{TZcv6AQov0Kfmjtic{>W@#QeN8wMRzH}7B~$pdDEddY(+E{uEX zM+pwVC5*V(twjGgaP`nWvy)XOsfpvMLMc>?E!n4L_$jUPVq9m_;ReLV+1sV$iGt)` z0=h_1t3R7A^qY(2Hwz0qq5944W!AICvK`Mh6y&>6N>_>Sp0qtT?eaIy5Uoh=Pu8VM z-?sD9^s57V*vDC=gIdQR$SwKn#+$RoEqN`7KOxbV!c@_y<+a11A?D)-{Y9Rv}d)Z^R26=4p{(ZKkS~DpXv2b|ESKXxjTzX|$lqM`mx>!qwN` z*9%K0Ps_)aG+_D2%UTjLtT<+v#kfW0zT|FVC;jH9oYRrXONPvXXxwxje##PIf}%u{ zy+`jXPq%1gM=)Hx_WKVwcV~Lf;%p@fZX;M1mhg-}C*wUiIXBwZ=jGSM$;+vyPAnha zT)x`~;T9$)v}UUnR3Pr}?_QW(P};=7!r<{3Q*(Pq7aeW z2gM8t_x5&ob#`iN&R2K7!4;654B`sNc2G(4py2FEm0jfI>sxo?&Sl?r wP)UM(z`x<*&Ih>dvl9|-`)mi5MB)D@?Qd=-ESe8I0swsAU_bzXD8T*t8{3tr>i_@% literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs index 6423e061c5..d979bdab93 100644 --- a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs +++ b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs @@ -60,6 +60,8 @@ namespace osu.Game.Tests.Skins "Archives/modified-argon-20231106.osk", // Covers "Argon" accuracy/score/combo counters, and wedges "Archives/modified-argon-20231108.osk", + // Covers "Argon" performance points counter + "Archives/modified-argon-20240305.osk", }; /// From 49b3e81e8aa2f9ba438d3218d06a9e167fd30191 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 5 Mar 2024 04:34:41 +0300 Subject: [PATCH 707/915] Migrate `DefaultPerformancePointsCounter` and rename it --- .../Visual/Gameplay/TestScenePerformancePointsCounter.cs | 3 ++- osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs | 2 +- osu.Game/Skinning/Skin.cs | 1 + .../Triangles/TrianglesPerformancePointsCounter.cs} | 5 +++-- osu.Game/Skinning/TrianglesSkin.cs | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) rename osu.Game/{Screens/Play/HUD/DefaultPerformancePointsCounter.cs => Skinning/Triangles/TrianglesPerformancePointsCounter.cs} (94%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs index 986167279c..eada72326d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; +using osu.Game.Skinning.Triangles; using osu.Game.Tests.Gameplay; namespace osu.Game.Tests.Visual.Gameplay @@ -32,7 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay private int iteration; - protected override Drawable CreateDefaultImplementation() => new DefaultPerformancePointsCounter(); + protected override Drawable CreateDefaultImplementation() => new TrianglesPerformancePointsCounter(); protected override Drawable CreateArgonImplementation() => new ArgonPerformancePointsCounter(); protected override Drawable CreateLegacyImplementation() => Empty(); diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index 4b07e7da36..c5ad106bcc 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -27,7 +27,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public partial class PerformancePointsCounter : RollingCounter, ISerialisableDrawable + public abstract partial class PerformancePointsCounter : RollingCounter, ISerialisableDrawable { public bool UsesFixedAnchor { get; set; } diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 9ee69d033d..91b21f0308 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -153,6 +153,7 @@ namespace osu.Game.Skinning // handle namespace changes... jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.SongProgress", @"osu.Game.Screens.Play.HUD.DefaultSongProgress"); jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.HUD.LegacyComboCounter", @"osu.Game.Skinning.LegacyComboCounter"); + jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.HUD.PerformancePointsCounter", @"osu.Game.Skinning.Triangles.TrianglesPerformancePointsCounter"); var deserializedContent = JsonConvert.DeserializeObject>(jsonContent); diff --git a/osu.Game/Screens/Play/HUD/DefaultPerformancePointsCounter.cs b/osu.Game/Skinning/Triangles/TrianglesPerformancePointsCounter.cs similarity index 94% rename from osu.Game/Screens/Play/HUD/DefaultPerformancePointsCounter.cs rename to osu.Game/Skinning/Triangles/TrianglesPerformancePointsCounter.cs index 3c4e58e575..99da2c0942 100644 --- a/osu.Game/Screens/Play/HUD/DefaultPerformancePointsCounter.cs +++ b/osu.Game/Skinning/Triangles/TrianglesPerformancePointsCounter.cs @@ -11,11 +11,12 @@ using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Resources.Localisation.Web; +using osu.Game.Screens.Play.HUD; using osuTK; -namespace osu.Game.Screens.Play.HUD +namespace osu.Game.Skinning.Triangles { - public partial class DefaultPerformancePointsCounter : PerformancePointsCounter + public partial class TrianglesPerformancePointsCounter : PerformancePointsCounter { protected override bool IsRollingProportional => true; diff --git a/osu.Game/Skinning/TrianglesSkin.cs b/osu.Game/Skinning/TrianglesSkin.cs index a2dca5d333..6158d4c7bf 100644 --- a/osu.Game/Skinning/TrianglesSkin.cs +++ b/osu.Game/Skinning/TrianglesSkin.cs @@ -14,6 +14,7 @@ using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD.HitErrorMeters; +using osu.Game.Skinning.Triangles; using osuTK; using osuTK.Graphics; @@ -167,7 +168,7 @@ namespace osu.Game.Skinning new DefaultKeyCounterDisplay(), new BarHitErrorMeter(), new BarHitErrorMeter(), - new PerformancePointsCounter() + new TrianglesPerformancePointsCounter() } }; From cceb616a18cc862f975da533bed42b49a89d2fa9 Mon Sep 17 00:00:00 2001 From: Jayden Date: Mon, 4 Mar 2024 22:25:36 -0500 Subject: [PATCH 708/915] Update failure messages Co-authored-by: Salman Ahmed --- osu.Desktop/DiscordRichPresence.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 035add8044..85b6129043 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -184,14 +184,14 @@ namespace osu.Desktop game.Window?.Raise(); if (!tryParseRoomSecret(args.Secret, out long roomId, out string? password)) - Logger.Log("Failed to parse the room secret Discord gave us", LoggingTarget.Network, LogLevel.Error); + Logger.Log("Could not parse room from Discord RPC Client", LoggingTarget.Network, LogLevel.Important); var request = new GetRoomRequest(roomId); request.Success += room => Schedule(() => { game.PresentMultiplayerMatch(room, password); }); - request.Failure += _ => Logger.Log("Couldn't find the room Discord gave us", LoggingTarget.Network, LogLevel.Error); + request.Failure += _ => Logger.Log($"Could not find room {roomId} from Discord RPC Client", LoggingTarget.Network, LogLevel.Important); api.Queue(request); } From 43841e210d2a1915d3c39bfe191ef62befbd3492 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Tue, 5 Mar 2024 09:58:46 +0100 Subject: [PATCH 709/915] Use ObjectDisposedException.ThrowIf throw helper --- osu.Game/Database/RealmAccess.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 4bd7f36cdd..167d170c81 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -489,8 +489,7 @@ namespace osu.Game.Database /// The work to run. public Task WriteAsync(Action action) { - if (isDisposed) - throw new ObjectDisposedException(nameof(RealmAccess)); + ObjectDisposedException.ThrowIf(isDisposed, this); // Required to ensure the write is tracked and accounted for before disposal. // Can potentially be avoided if we have a need to do so in the future. @@ -675,8 +674,7 @@ namespace osu.Game.Database private Realm getRealmInstance() { - if (isDisposed) - throw new ObjectDisposedException(nameof(RealmAccess)); + ObjectDisposedException.ThrowIf(isDisposed, this); bool tookSemaphoreLock = false; @@ -1189,8 +1187,7 @@ namespace osu.Game.Database if (!ThreadSafety.IsUpdateThread) throw new InvalidOperationException(@$"{nameof(BlockAllOperations)} must be called from the update thread."); - if (isDisposed) - throw new ObjectDisposedException(nameof(RealmAccess)); + ObjectDisposedException.ThrowIf(isDisposed, this); SynchronizationContext? syncContext = null; From 9bac60a98fc098cb4c6b1f118e61c5255bd5b235 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Tue, 5 Mar 2024 10:19:47 +0100 Subject: [PATCH 710/915] Use ArgumentNullException.ThrowIfNull in more places --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 13e28279e6..bdc0ff85ba 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -135,8 +135,7 @@ namespace osu.Game.Rulesets.UI protected DrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) : base(ruleset) { - if (beatmap == null) - throw new ArgumentNullException(nameof(beatmap), "Beatmap cannot be null."); + ArgumentNullException.ThrowIfNull(beatmap); if (!(beatmap is Beatmap tBeatmap)) throw new ArgumentException($"{GetType()} expected the beatmap to contain hitobjects of type {typeof(TObject)}.", nameof(beatmap)); From a89130348469e1b1ea8e025bb2c6cf4a85da51b3 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Tue, 5 Mar 2024 10:20:30 +0100 Subject: [PATCH 711/915] Use ArgumentOutOfRangeException throw helper methods --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs | 6 +++--- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 2 +- osu.Game/Beatmaps/Timing/TimeSignature.cs | 3 +-- osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs | 3 +-- osu.Game/Rulesets/Objects/Types/PathType.cs | 3 +-- osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs | 3 +-- osu.Game/Utils/LimitedCapacityQueue.cs | 3 +-- osu.Game/Utils/StatelessRNG.cs | 2 +- 8 files changed, 10 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 835c67ff19..9cc0a8c414 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -58,9 +58,9 @@ namespace osu.Game.Rulesets.Osu.Beatmaps private void applyStacking(Beatmap beatmap, int startIndex, int endIndex) { - if (startIndex > endIndex) throw new ArgumentOutOfRangeException(nameof(startIndex), $"{nameof(startIndex)} cannot be greater than {nameof(endIndex)}."); - if (startIndex < 0) throw new ArgumentOutOfRangeException(nameof(startIndex), $"{nameof(startIndex)} cannot be less than 0."); - if (endIndex < 0) throw new ArgumentOutOfRangeException(nameof(endIndex), $"{nameof(endIndex)} cannot be less than 0."); + ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex, endIndex); + ArgumentOutOfRangeException.ThrowIfNegative(startIndex); + ArgumentOutOfRangeException.ThrowIfNegative(endIndex); int extendedEndIndex = endIndex; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 448cfaf84c..3ead61f64a 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -334,7 +334,7 @@ namespace osu.Game.Rulesets.Osu.Edit /// The from a selected to a target . private OsuDistanceSnapGrid createGrid(Func sourceSelector, int targetOffset = 1) { - if (targetOffset < 1) throw new ArgumentOutOfRangeException(nameof(targetOffset)); + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(targetOffset); int sourceIndex = -1; diff --git a/osu.Game/Beatmaps/Timing/TimeSignature.cs b/osu.Game/Beatmaps/Timing/TimeSignature.cs index 7499a725dc..377a878631 100644 --- a/osu.Game/Beatmaps/Timing/TimeSignature.cs +++ b/osu.Game/Beatmaps/Timing/TimeSignature.cs @@ -23,8 +23,7 @@ namespace osu.Game.Beatmaps.Timing public TimeSignature(int numerator) { - if (numerator < 1) - throw new ArgumentOutOfRangeException(nameof(numerator), numerator, "The numerator of a time signature must be positive."); + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(numerator); Numerator = numerator; } diff --git a/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs b/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs index 3dc2d133ba..17c3c51cfb 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs @@ -27,8 +27,7 @@ namespace osu.Game.Rulesets.Difficulty.Utils public ReverseQueue(int initialCapacity) { - if (initialCapacity <= 0) - throw new ArgumentOutOfRangeException(nameof(initialCapacity)); + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(initialCapacity); items = new T[initialCapacity]; capacity = initialCapacity; diff --git a/osu.Game/Rulesets/Objects/Types/PathType.cs b/osu.Game/Rulesets/Objects/Types/PathType.cs index 23f1ccf0bc..6983484dce 100644 --- a/osu.Game/Rulesets/Objects/Types/PathType.cs +++ b/osu.Game/Rulesets/Objects/Types/PathType.cs @@ -40,8 +40,7 @@ namespace osu.Game.Rulesets.Objects.Types public static PathType BSpline(int degree) { - if (degree <= 0) - throw new ArgumentOutOfRangeException(nameof(degree), "The degree of a B-Spline path must be greater than zero."); + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(degree); return new PathType { Type = SplineType.BSpline, Degree = degree }; } diff --git a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs index ed31bc8643..4abf0007a7 100644 --- a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs +++ b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs @@ -33,8 +33,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// The s to display in this row. public SimpleStatisticTable(int columnCount, [ItemNotNull] IEnumerable items) { - if (columnCount < 1) - throw new ArgumentOutOfRangeException(nameof(columnCount)); + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(columnCount); this.columnCount = columnCount; this.items = items.ToArray(); diff --git a/osu.Game/Utils/LimitedCapacityQueue.cs b/osu.Game/Utils/LimitedCapacityQueue.cs index d36aa8af2c..b96148d4a0 100644 --- a/osu.Game/Utils/LimitedCapacityQueue.cs +++ b/osu.Game/Utils/LimitedCapacityQueue.cs @@ -35,8 +35,7 @@ namespace osu.Game.Utils /// The number of items the queue can hold. public LimitedCapacityQueue(int capacity) { - if (capacity < 0) - throw new ArgumentOutOfRangeException(nameof(capacity)); + ArgumentOutOfRangeException.ThrowIfNegative(capacity); this.capacity = capacity; array = new T[capacity]; diff --git a/osu.Game/Utils/StatelessRNG.cs b/osu.Game/Utils/StatelessRNG.cs index 3db632fc42..8833dcbbdb 100644 --- a/osu.Game/Utils/StatelessRNG.cs +++ b/osu.Game/Utils/StatelessRNG.cs @@ -58,7 +58,7 @@ namespace osu.Game.Utils /// public static int NextInt(int maxValue, int seed, int series = 0) { - if (maxValue <= 0) throw new ArgumentOutOfRangeException(nameof(maxValue)); + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(maxValue); return (int)(NextULong(seed, series) % (ulong)maxValue); } From 5965db4fd7344822d116aa7bd23ad2fa2ebfa22e Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Tue, 5 Mar 2024 10:20:57 +0100 Subject: [PATCH 712/915] Use ArgumentException.ThrowIfNullOrEmpty throw helper --- osu.Game/IO/WrappedStorage.cs | 3 +-- osu.Game/Online/API/OAuth.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/IO/WrappedStorage.cs b/osu.Game/IO/WrappedStorage.cs index 95ff26db6a..5a8f4aef59 100644 --- a/osu.Game/IO/WrappedStorage.cs +++ b/osu.Game/IO/WrappedStorage.cs @@ -80,8 +80,7 @@ namespace osu.Game.IO public override Storage GetStorageForDirectory(string path) { - if (string.IsNullOrEmpty(path)) - throw new ArgumentException("Must be non-null and not empty string", nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); if (!path.EndsWith(Path.DirectorySeparatorChar)) path += Path.DirectorySeparatorChar; diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index 4829310870..b06d9c6586 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -39,8 +39,8 @@ namespace osu.Game.Online.API internal void AuthenticateWithLogin(string username, string password) { - if (string.IsNullOrEmpty(username)) throw new ArgumentException("Missing username."); - if (string.IsNullOrEmpty(password)) throw new ArgumentException("Missing password."); + ArgumentException.ThrowIfNullOrEmpty(username); + ArgumentException.ThrowIfNullOrEmpty(password); var accessTokenRequest = new AccessTokenRequestPassword(username, password) { From 6fabbe26166df10907358d5c58dc26f8cf17dbbe Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Tue, 5 Mar 2024 10:27:12 +0100 Subject: [PATCH 713/915] Use new ToDictionary() overload without delegates --- osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs | 4 ++-- osu.Game/Scoring/Legacy/LegacyReplaySoloScoreInfo.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs index 6f321fd401..64caddb2fc 100644 --- a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs @@ -245,8 +245,8 @@ namespace osu.Game.Online.API.Requests.Responses RulesetID = score.RulesetID, Passed = score.Passed, Mods = score.APIMods, - Statistics = score.Statistics.Where(kvp => kvp.Value != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), - MaximumStatistics = score.MaximumStatistics.Where(kvp => kvp.Value != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), + Statistics = score.Statistics.Where(kvp => kvp.Value != 0).ToDictionary(), + MaximumStatistics = score.MaximumStatistics.Where(kvp => kvp.Value != 0).ToDictionary(), }; } } diff --git a/osu.Game/Scoring/Legacy/LegacyReplaySoloScoreInfo.cs b/osu.Game/Scoring/Legacy/LegacyReplaySoloScoreInfo.cs index 2c5b91f10f..afdcef1d21 100644 --- a/osu.Game/Scoring/Legacy/LegacyReplaySoloScoreInfo.cs +++ b/osu.Game/Scoring/Legacy/LegacyReplaySoloScoreInfo.cs @@ -42,8 +42,8 @@ namespace osu.Game.Scoring.Legacy { OnlineID = score.OnlineID, Mods = score.APIMods, - Statistics = score.Statistics.Where(kvp => kvp.Value != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), - MaximumStatistics = score.MaximumStatistics.Where(kvp => kvp.Value != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), + Statistics = score.Statistics.Where(kvp => kvp.Value != 0).ToDictionary(), + MaximumStatistics = score.MaximumStatistics.Where(kvp => kvp.Value != 0).ToDictionary(), ClientVersion = score.ClientVersion, }; } From d0f7ab3316584f92957cd738c57e6dfd85fb9fcc Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Tue, 5 Mar 2024 17:18:59 +0100 Subject: [PATCH 714/915] Revert some changes --- osu.Game/Online/API/OAuth.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index b06d9c6586..4829310870 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -39,8 +39,8 @@ namespace osu.Game.Online.API internal void AuthenticateWithLogin(string username, string password) { - ArgumentException.ThrowIfNullOrEmpty(username); - ArgumentException.ThrowIfNullOrEmpty(password); + if (string.IsNullOrEmpty(username)) throw new ArgumentException("Missing username."); + if (string.IsNullOrEmpty(password)) throw new ArgumentException("Missing password."); var accessTokenRequest = new AccessTokenRequestPassword(username, password) { From e6f1a722cbb54a905a20c91fe30a8be072ba357c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 5 Mar 2024 18:48:58 +0100 Subject: [PATCH 715/915] Remove unused field and commented-out code --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 34 +++++-------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index 6f70a914f0..08d00f8ac2 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -33,7 +33,6 @@ namespace osu.Game.Screens.Play private double countdownStartTime; private Drawable content = null!; - private Drawable background = null!; private SpriteText countdown = null!; public DelayedResumeOverlay() @@ -53,9 +52,9 @@ namespace osu.Game.Screens.Play Masking = true, BorderColour = colours.Yellow, BorderThickness = 1, - Children = new[] + Children = new Drawable[] { - background = new Box + new Box { Size = new Vector2(250, 40), Colour = Color4.Black, @@ -75,29 +74,14 @@ namespace osu.Game.Screens.Play AutoSizeAxes = Axes.Both, Spacing = new Vector2(5), Colour = colours.Yellow, - Children = new Drawable[] + Child = countdown = new OsuSpriteText { - // new Box - // { - // Anchor = Anchor.Centre, - // Origin = Anchor.Centre, - // Size = new Vector2(40, 3) - // }, - countdown = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - UseFullGlyphHeight = false, - AlwaysPresent = true, - Font = OsuFont.Numeric.With(size: 20, fixedWidth: true) - }, - // new Box - // { - // Anchor = Anchor.Centre, - // Origin = Anchor.Centre, - // Size = new Vector2(40, 3) - // } - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + UseFullGlyphHeight = false, + AlwaysPresent = true, + Font = OsuFont.Numeric.With(size: 20, fixedWidth: true) + }, } } } From 57daaa7fed6b7c7021e0c85d83ff8e532f657c7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Mar 2024 04:17:15 +0800 Subject: [PATCH 716/915] Add logging for `GameplayClockContainer` starting or stopping --- osu.Game/Screens/Play/GameplayClockContainer.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index c039d1e535..255877e0aa 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -122,8 +122,17 @@ namespace osu.Game.Screens.Play StopGameplayClock(); } - protected virtual void StartGameplayClock() => GameplayClock.Start(); - protected virtual void StopGameplayClock() => GameplayClock.Stop(); + protected virtual void StartGameplayClock() + { + Logger.Log($"{nameof(GameplayClockContainer)} started via call to {nameof(StartGameplayClock)}"); + GameplayClock.Start(); + } + + protected virtual void StopGameplayClock() + { + Logger.Log($"{nameof(GameplayClockContainer)} stopped via call to {nameof(StopGameplayClock)}"); + GameplayClock.Stop(); + } /// /// Resets this and the source to an initial state ready for gameplay. From 65ce4ca390925c43ebb8167c4aa19c15b8b46b01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Mar 2024 04:17:51 +0800 Subject: [PATCH 717/915] Never set `waitingOnFrames` if a replay is not attached --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 884310e44c..b49924762e 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.UI double timeBehind = Math.Abs(proposedTime - referenceClock.CurrentTime); isCatchingUp.Value = timeBehind > 200; - waitingOnFrames.Value = state == PlaybackState.NotValid; + waitingOnFrames.Value = hasReplayAttached && state == PlaybackState.NotValid; manualClock.CurrentTime = proposedTime; manualClock.Rate = Math.Abs(referenceClock.Rate) * direction; From b53777c2a42bab857664cb5c2887e5cced0c0625 Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 5 Mar 2024 18:15:53 -0500 Subject: [PATCH 718/915] Refactor room secret handling to use JSON Also log room secrets for debugging purposes --- osu.Desktop/DiscordRichPresence.cs | 41 ++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 85b6129043..7315ee0c17 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -5,6 +5,7 @@ using System; using System.Text; using DiscordRPC; using DiscordRPC.Message; +using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -147,7 +148,13 @@ namespace osu.Desktop Size = room.Users.Count, }; - presence.Secrets.JoinSecret = $"{room.RoomID}:{room.Settings.Password}"; + RoomSecret roomSecret = new RoomSecret + { + RoomID = room.RoomID, + Password = room.Settings.Password, + }; + + presence.Secrets.JoinSecret = JsonConvert.SerializeObject(roomSecret); } else { @@ -182,9 +189,13 @@ namespace osu.Desktop private void onJoin(object sender, JoinMessage args) { game.Window?.Raise(); + Logger.Log($"Received room secret from Discord RPC Client: {args.Secret}", LoggingTarget.Network, LogLevel.Debug); if (!tryParseRoomSecret(args.Secret, out long roomId, out string? password)) + { Logger.Log("Could not parse room from Discord RPC Client", LoggingTarget.Network, LogLevel.Important); + return; + } var request = new GetRoomRequest(roomId); request.Success += room => Schedule(() => @@ -216,21 +227,26 @@ namespace osu.Desktop }); } - private static bool tryParseRoomSecret(ReadOnlySpan secret, out long roomId, out string? password) + private static bool tryParseRoomSecret(string secretJson, out long roomId, out string? password) { roomId = 0; password = null; - int roomSecretSplitIndex = secret.IndexOf(':'); + RoomSecret? roomSecret; - if (roomSecretSplitIndex == -1) + try + { + roomSecret = JsonConvert.DeserializeObject(secretJson); + } + catch + { return false; + } - if (!long.TryParse(secret[..roomSecretSplitIndex], out roomId)) - return false; + if (roomSecret == null) return false; - password = secret[(roomSecretSplitIndex + 1)..].ToString(); - if (password.Length == 0) password = null; + roomId = roomSecret.RoomID; + password = roomSecret.Password; return true; } @@ -254,5 +270,14 @@ namespace osu.Desktop client.Dispose(); base.Dispose(isDisposing); } + + private class RoomSecret + { + [JsonProperty(@"roomId", Required = Required.Always)] + public long RoomID { get; set; } + + [JsonProperty(@"password", Required = Required.AllowNull)] + public string? Password { get; set; } + } } } From 98713003176da6b09bafeea7392564959098956b Mon Sep 17 00:00:00 2001 From: Jayden Date: Tue, 5 Mar 2024 18:22:39 -0500 Subject: [PATCH 719/915] Improve language of user-facing errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Desktop/DiscordRichPresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 7315ee0c17..8fecd015d4 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -193,7 +193,7 @@ namespace osu.Desktop if (!tryParseRoomSecret(args.Secret, out long roomId, out string? password)) { - Logger.Log("Could not parse room from Discord RPC Client", LoggingTarget.Network, LogLevel.Important); + Logger.Log("Could not join multiplayer room.", LoggingTarget.Network, LogLevel.Important); return; } From 6455c0583b5e607baeca7f584410bc63515aa619 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Mar 2024 10:19:40 +0800 Subject: [PATCH 720/915] Update usage of `CircularProgress.Current` --- .../Skinning/Argon/ArgonSpinnerProgressArc.cs | 6 +++--- .../Skinning/Argon/ArgonSpinnerRingArc.cs | 6 +++--- osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs | 8 ++++++-- osu.Game/Overlays/Volume/VolumeMeter.cs | 6 +++--- .../Edit/Compose/Components/CircularDistanceSnapGrid.cs | 2 +- osu.Game/Screens/Edit/Timing/TapButton.cs | 6 +++--- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 7 ++++++- .../Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 6 +++--- .../Screens/Ranking/Expanded/Accuracy/GradedCircles.cs | 2 +- osu.Game/Skinning/LegacySongProgress.cs | 4 ++-- 10 files changed, 31 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerProgressArc.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerProgressArc.cs index 76afeeb2c4..1de5b1f309 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerProgressArc.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerProgressArc.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon Origin = Anchor.Centre, Colour = Color4.White.Opacity(0.25f), RelativeSizeAxes = Axes.Both, - Current = { Value = arc_fill }, + Progress = arc_fill, Rotation = 90 - arc_fill * 180, InnerRadius = arc_radius, RoundedCaps = true, @@ -71,9 +71,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon background.Alpha = spinner.Progress >= 1 ? 0 : 1; fill.Alpha = (float)Interpolation.DampContinuously(fill.Alpha, spinner.Progress > 0 && spinner.Progress < 1 ? 1 : 0, 40f, (float)Math.Abs(Time.Elapsed)); - fill.Current.Value = (float)Interpolation.DampContinuously(fill.Current.Value, spinner.Progress >= 1 ? 0 : arc_fill * spinner.Progress, 40f, (float)Math.Abs(Time.Elapsed)); + fill.Progress = (float)Interpolation.DampContinuously(fill.Progress, spinner.Progress >= 1 ? 0 : arc_fill * spinner.Progress, 40f, (float)Math.Abs(Time.Elapsed)); - fill.Rotation = (float)(90 - fill.Current.Value * 180); + fill.Rotation = (float)(90 - fill.Progress * 180); } private partial class ProgressFill : CircularProgress diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerRingArc.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerRingArc.cs index 702c5c2675..12cd0994b4 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerRingArc.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSpinnerRingArc.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Current = { Value = arc_fill }, + Progress = arc_fill, Rotation = -arc_fill * 180, InnerRadius = arc_radius, RoundedCaps = true, @@ -44,10 +44,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon { base.Update(); - fill.Current.Value = (float)Interpolation.DampContinuously(fill.Current.Value, spinner.Progress >= 1 ? arc_fill_complete : arc_fill, 40f, (float)Math.Abs(Time.Elapsed)); + fill.Progress = (float)Interpolation.DampContinuously(fill.Progress, spinner.Progress >= 1 ? arc_fill_complete : arc_fill, 40f, (float)Math.Abs(Time.Elapsed)); fill.InnerRadius = (float)Interpolation.DampContinuously(fill.InnerRadius, spinner.Progress >= 1 ? arc_radius * 2.2f : arc_radius, 40f, (float)Math.Abs(Time.Elapsed)); - fill.Rotation = (float)(-fill.Current.Value * 180); + fill.Rotation = (float)(-fill.Progress * 180); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs index 5a26a988fb..cd498c474a 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs @@ -86,11 +86,15 @@ namespace osu.Game.Beatmaps.Drawables.Cards Dimmed.BindValueChanged(_ => updateState()); playButton.Playing.BindValueChanged(_ => updateState(), true); - ((IBindable)progress.Current).BindTo(playButton.Progress); - FinishTransforms(true); } + protected override void Update() + { + base.Update(); + progress.Progress = playButton.Progress.Value; + } + private void updateState() { bool shouldDim = Dimmed.Value || playButton.Playing.Value; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 6ec4971f06..e96cd0fa46 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -235,7 +235,7 @@ namespace osu.Game.Overlays.Volume Bindable.BindValueChanged(volume => { this.TransformTo(nameof(DisplayVolume), volume.NewValue, 400, Easing.OutQuint); }, true); - bgProgress.Current.Value = 0.75f; + bgProgress.Progress = 0.75f; } private int? displayVolumeInt; @@ -265,8 +265,8 @@ namespace osu.Game.Overlays.Volume text.Text = intValue.ToString(CultureInfo.CurrentCulture); } - volumeCircle.Current.Value = displayVolume * 0.75f; - volumeCircleGlow.Current.Value = displayVolume * 0.75f; + volumeCircle.Progress = displayVolume * 0.75f; + volumeCircleGlow.Progress = displayVolume * 0.75f; if (intVolumeChanged && IsLoaded) Scheduler.AddOnce(playTickSound); diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index e33ef66007..92fe52148c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -140,7 +140,7 @@ namespace osu.Game.Screens.Edit.Compose.Components Colour = this.baseColour = baseColour; - Current.Value = 1; + Progress = 1; } protected override void Update() diff --git a/osu.Game/Screens/Edit/Timing/TapButton.cs b/osu.Game/Screens/Edit/Timing/TapButton.cs index fd60fb1b5b..d2ae0e76cf 100644 --- a/osu.Game/Screens/Edit/Timing/TapButton.cs +++ b/osu.Game/Screens/Edit/Timing/TapButton.cs @@ -366,7 +366,7 @@ namespace osu.Game.Screens.Edit.Timing new CircularProgress { RelativeSizeAxes = Axes.Both, - Current = { Value = 1f / light_count - angular_light_gap }, + Progress = 1f / light_count - angular_light_gap, Colour = colourProvider.Background2, }, fillContent = new Container @@ -379,7 +379,7 @@ namespace osu.Game.Screens.Edit.Timing new CircularProgress { RelativeSizeAxes = Axes.Both, - Current = { Value = 1f / light_count - angular_light_gap }, + Progress = 1f / light_count - angular_light_gap, Blending = BlendingParameters.Additive }, // Please do not try and make sense of this. @@ -388,7 +388,7 @@ namespace osu.Game.Screens.Edit.Timing Glow = new CircularProgress { RelativeSizeAxes = Axes.Both, - Current = { Value = 1f / light_count - 0.01f }, + Progress = 1f / light_count - 0.01f, Blending = BlendingParameters.Additive }.WithEffect(new GlowEffect { diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index a260156595..6d045e5f01 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -198,9 +198,14 @@ namespace osu.Game.Screens.Play.HUD bind(); } + protected override void Update() + { + base.Update(); + circularProgress.Progress = Progress.Value; + } + private void bind() { - ((IBindable)circularProgress.Current).BindTo(Progress); Progress.ValueChanged += progress => { icon.Scale = new Vector2(1 + (float)progress.NewValue * 0.2f); diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 83b02a0951..2231346404 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -147,7 +147,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy Colour = OsuColour.Gray(47), Alpha = 0.5f, InnerRadius = accuracy_circle_radius + 0.01f, // Extends a little bit into the circle - Current = { Value = 1 }, + Progress = 1, }, accuracyCircle = new CircularProgress { @@ -268,7 +268,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy if (targetAccuracy < 1 && targetAccuracy >= visual_alignment_offset) targetAccuracy -= visual_alignment_offset; - accuracyCircle.FillTo(targetAccuracy, ACCURACY_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING); + accuracyCircle.ProgressTo(targetAccuracy, ACCURACY_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING); if (withFlair) { @@ -359,7 +359,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy .FadeOut(800, Easing.Out); accuracyCircle - .FillTo(accuracyS - GRADE_SPACING_PERCENTAGE / 2 - visual_alignment_offset, 70, Easing.OutQuint); + .ProgressTo(accuracyS - GRADE_SPACING_PERCENTAGE / 2 - visual_alignment_offset, 70, Easing.OutQuint); badges.Single(b => b.Rank == getRank(ScoreRank.S)) .FadeOut(70, Easing.OutQuint); diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs index 33b71c53a7..633ed6d92e 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { public double RevealProgress { - set => Current.Value = Math.Clamp(value, startProgress, endProgress) - startProgress; + set => Progress = Math.Clamp(value, startProgress, endProgress) - startProgress; } private readonly double startProgress; diff --git a/osu.Game/Skinning/LegacySongProgress.cs b/osu.Game/Skinning/LegacySongProgress.cs index 4295060a3a..9af82c4992 100644 --- a/osu.Game/Skinning/LegacySongProgress.cs +++ b/osu.Game/Skinning/LegacySongProgress.cs @@ -72,14 +72,14 @@ namespace osu.Game.Skinning circularProgress.Scale = new Vector2(-1, 1); circularProgress.Anchor = Anchor.TopRight; circularProgress.Colour = new Colour4(199, 255, 47, 153); - circularProgress.Current.Value = 1 - progress; + circularProgress.Progress = 1 - progress; } else { circularProgress.Scale = new Vector2(1); circularProgress.Anchor = Anchor.TopLeft; circularProgress.Colour = new Colour4(255, 255, 255, 153); - circularProgress.Current.Value = progress; + circularProgress.Progress = progress; } } } From b53b752e543d563b1059cc66d6dd8c6077bb6e01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Mar 2024 10:42:20 +0800 Subject: [PATCH 721/915] Update usage of `MathUtils` --- osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs | 2 +- .../Objects/Drawables/DrawableSliderRepeat.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 2 +- .../Skinning/Default/SpinnerRotationTracker.cs | 2 +- osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 3 +-- osu.Game/Graphics/Cursor/MenuCursorContainer.cs | 2 +- osu.Game/Graphics/UserInterface/OsuNumberBox.cs | 4 +--- osu.Game/IO/Archives/ZipArchiveReader.cs | 3 +-- .../Overlays/Settings/Sections/Input/TabletAreaSelection.cs | 3 +-- osu.Game/Overlays/Settings/SettingsNumberBox.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 4 ++-- osu.Game/Utils/GeometryUtils.cs | 5 ++--- 13 files changed, 15 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs index df9544b71e..992f4d5f03 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.Mods // multiply the SPM by 1.01 to ensure that the spinner is completed. if the calculation is left exact, // some spinners may not complete due to very minor decimal loss during calculation float rotationSpeed = (float)(1.01 * spinner.HitObject.SpinsRequired / spinner.HitObject.Duration); - spinner.RotationTracker.AddRotation(MathUtils.RadiansToDegrees((float)rateIndependentElapsedTime * rotationSpeed * MathF.PI * 2.0f)); + spinner.RotationTracker.AddRotation(float.RadiansToDegrees((float)rateIndependentElapsedTime * rotationSpeed * MathF.PI * 2.0f)); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 3239565528..fcbd0edfe0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -146,7 +146,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; } - float aimRotation = MathUtils.RadiansToDegrees(MathF.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); + float aimRotation = float.RadiansToDegrees(MathF.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); while (Math.Abs(aimRotation - Arrow.Rotation) > 180) aimRotation += aimRotation < Arrow.Rotation ? 360 : -360; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index 1cf6bc91f0..d43e6092c2 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -342,7 +342,7 @@ namespace osu.Game.Rulesets.Osu.Replays // 0.05 rad/ms, or ~477 RPM, as per stable. // the redundant conversion from RPM to rad/ms is here for ease of testing custom SPM specs. const float spin_rpm = 0.05f / (2 * MathF.PI) * 60000; - float radsPerMillisecond = MathUtils.DegreesToRadians(spin_rpm * 360) / 60000; + float radsPerMillisecond = float.DegreesToRadians(spin_rpm * 360) / 60000; switch (h) { diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs index 1d75663fd9..7e97f826f9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default if (mousePosition is Vector2 pos) { - float thisAngle = -MathUtils.RadiansToDegrees(MathF.Atan2(pos.X - DrawSize.X / 2, pos.Y - DrawSize.Y / 2)); + float thisAngle = -float.RadiansToDegrees(MathF.Atan2(pos.X - DrawSize.X / 2, pos.Y - DrawSize.Y / 2)); float delta = lastAngle == null ? 0 : thisAngle - lastAngle.Value; // Normalise the delta to -180 .. 180 diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index f9d4a3b325..4b3b543ea4 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -246,7 +246,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. - double rotatedAngle = finalAngle - MathUtils.DegreesToRadians(rotation); + double rotatedAngle = finalAngle - float.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/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index cf4700bf85..6689f087cb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using osu.Framework.Graphics; -using osu.Framework.Utils; using osu.Game.Beatmaps.Legacy; using osu.Game.IO; using osu.Game.Storyboards; @@ -230,7 +229,7 @@ namespace osu.Game.Beatmaps.Formats { 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)); + timelineGroup?.Rotation.Add(easing, startTime, endTime, float.RadiansToDegrees(startValue), float.RadiansToDegrees(endValue)); break; } diff --git a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs index 7e42d45191..696ea62b42 100644 --- a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs @@ -157,7 +157,7 @@ namespace osu.Game.Graphics.Cursor if (dragRotationState == DragRotationState.Rotating && distance > 0) { Vector2 offset = e.MousePosition - positionMouseDown; - float degrees = MathUtils.RadiansToDegrees(MathF.Atan2(-offset.X, offset.Y)) + 24.3f; + float degrees = float.RadiansToDegrees(MathF.Atan2(-offset.X, offset.Y)) + 24.3f; // Always rotate in the direction of least distance float diff = (degrees - activeCursor.Rotation) % 360; diff --git a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs index df92863797..e9b28f4771 100644 --- a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs @@ -1,14 +1,12 @@ // 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.Extensions; - namespace osu.Game.Graphics.UserInterface { public partial class OsuNumberBox : OsuTextBox { protected override bool AllowIme => false; - protected override bool CanAddCharacter(char character) => character.IsAsciiDigit(); + protected override bool CanAddCharacter(char character) => char.IsAsciiDigit(character); } } diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index 5ef03b3641..7d7ce858dd 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Toolkit.HighPerformance; -using osu.Framework.Extensions; using osu.Framework.IO.Stores; using SharpCompress.Archives.Zip; using SixLabors.ImageSharp.Memory; @@ -36,7 +35,7 @@ namespace osu.Game.IO.Archives var owner = MemoryAllocator.Default.Allocate((int)entry.Size); using (Stream s = entry.OpenEntryStream()) - s.ReadToFill(owner.Memory.Span); + s.ReadExactly(owner.Memory.Span); return new MemoryOwnerMemoryStream(owner); } diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs index 686002fe71..33f4f49173 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Input.Handlers.Tablet; -using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; @@ -196,7 +195,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input var matrix = Matrix3.Identity; MatrixExtensions.TranslateFromLeft(ref matrix, offset); - MatrixExtensions.RotateFromLeft(ref matrix, MathUtils.DegreesToRadians(rotation.Value)); + MatrixExtensions.RotateFromLeft(ref matrix, float.DegreesToRadians(rotation.Value)); usableAreaQuad *= matrix; diff --git a/osu.Game/Overlays/Settings/SettingsNumberBox.cs b/osu.Game/Overlays/Settings/SettingsNumberBox.cs index a0f85eda31..cdf648fc5f 100644 --- a/osu.Game/Overlays/Settings/SettingsNumberBox.cs +++ b/osu.Game/Overlays/Settings/SettingsNumberBox.cs @@ -69,7 +69,7 @@ namespace osu.Game.Overlays.Settings { protected override bool AllowIme => false; - protected override bool CanAddCharacter(char character) => character.IsAsciiDigit(); + protected override bool CanAddCharacter(char character) => char.IsAsciiDigit(character); public new void NotifyInputError() => base.NotifyInputError(); } diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index b722b83280..c47ce91711 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -209,13 +209,13 @@ namespace osu.Game.Screens.Menu if (audioData[i] < amplitude_dead_zone) continue; - float rotation = MathUtils.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds); + float rotation = float.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds); float rotationCos = MathF.Cos(rotation); float rotationSin = MathF.Sin(rotation); // taking the cos and sin to the 0..1 range var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * size; - var barSize = new Vector2(size * MathF.Sqrt(2 * (1 - MathF.Cos(MathUtils.DegreesToRadians(360f / bars_per_visualiser)))) / 2f, bar_length * audioData[i]); + var barSize = new Vector2(size * MathF.Sqrt(2 * (1 - MathF.Cos(float.DegreesToRadians(360f / bars_per_visualiser)))) / 2f, bar_length * audioData[i]); // The distance between the position and the sides of the bar. var bottomOffset = new Vector2(-rotationSin * barSize.X / 2, rotationCos * barSize.X / 2); // The distance between the bottom side of the bar and the top side. diff --git a/osu.Game/Utils/GeometryUtils.cs b/osu.Game/Utils/GeometryUtils.cs index 725e93d098..dbeba4dfc1 100644 --- a/osu.Game/Utils/GeometryUtils.cs +++ b/osu.Game/Utils/GeometryUtils.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; -using osu.Framework.Utils; using osu.Game.Rulesets.Objects.Types; using osuTK; @@ -28,8 +27,8 @@ namespace osu.Game.Utils point.Y -= origin.Y; Vector2 ret; - ret.X = point.X * MathF.Cos(MathUtils.DegreesToRadians(angle)) + point.Y * MathF.Sin(MathUtils.DegreesToRadians(angle)); - ret.Y = point.X * -MathF.Sin(MathUtils.DegreesToRadians(angle)) + point.Y * MathF.Cos(MathUtils.DegreesToRadians(angle)); + ret.X = point.X * MathF.Cos(float.DegreesToRadians(angle)) + point.Y * MathF.Sin(float.DegreesToRadians(angle)); + ret.Y = point.X * -MathF.Sin(float.DegreesToRadians(angle)) + point.Y * MathF.Cos(float.DegreesToRadians(angle)); ret.X += origin.X; ret.Y += origin.Y; From 0696e7de524123d1b332a166c4cd81f5d6c24c15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Mar 2024 10:42:42 +0800 Subject: [PATCH 722/915] Update ImageSharp usages --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerMaxDimensions.cs | 2 +- osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs | 2 +- osu.Game/Skinning/LegacyTextureLoaderStore.cs | 2 +- osu.Game/Skinning/MaxDimensionLimitedTextureLoaderStore.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerMaxDimensions.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerMaxDimensions.cs index 53a4abdd07..3f78dedec5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerMaxDimensions.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerMaxDimensions.cs @@ -121,7 +121,7 @@ namespace osu.Game.Tests.Visual.Gameplay private TextureUpload upscale(TextureUpload textureUpload) { - var image = Image.LoadPixelData(textureUpload.Data.ToArray(), textureUpload.Width, textureUpload.Height); + var image = Image.LoadPixelData(textureUpload.Data, textureUpload.Width, textureUpload.Height); // The original texture upload will no longer be returned or used. textureUpload.Dispose(); diff --git a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs index 128e100e4b..cf58ae73fe 100644 --- a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs +++ b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs @@ -64,7 +64,7 @@ namespace osu.Game.Beatmaps // The original texture upload will no longer be returned or used. textureUpload.Dispose(); - Size size = image.Size(); + Size size = image.Size; // Assume that panel backgrounds are always displayed using `FillMode.Fill`. // Also assume that all backgrounds are wider than they are tall, so the diff --git a/osu.Game/Skinning/LegacyTextureLoaderStore.cs b/osu.Game/Skinning/LegacyTextureLoaderStore.cs index 29206bbb85..5045374c14 100644 --- a/osu.Game/Skinning/LegacyTextureLoaderStore.cs +++ b/osu.Game/Skinning/LegacyTextureLoaderStore.cs @@ -73,7 +73,7 @@ namespace osu.Game.Skinning private TextureUpload convertToGrayscale(TextureUpload textureUpload) { - var image = Image.LoadPixelData(textureUpload.Data.ToArray(), textureUpload.Width, textureUpload.Height); + var image = Image.LoadPixelData(textureUpload.Data, textureUpload.Width, textureUpload.Height); // stable uses `0.299 * r + 0.587 * g + 0.114 * b` // (https://github.com/peppy/osu-stable-reference/blob/013c3010a9d495e3471a9c59518de17006f9ad89/osu!/Graphics/Textures/pTexture.cs#L138-L153) diff --git a/osu.Game/Skinning/MaxDimensionLimitedTextureLoaderStore.cs b/osu.Game/Skinning/MaxDimensionLimitedTextureLoaderStore.cs index f15097a169..58dadbe753 100644 --- a/osu.Game/Skinning/MaxDimensionLimitedTextureLoaderStore.cs +++ b/osu.Game/Skinning/MaxDimensionLimitedTextureLoaderStore.cs @@ -61,7 +61,7 @@ namespace osu.Game.Skinning if (textureUpload.Height > max_supported_texture_size || textureUpload.Width > max_supported_texture_size) { - var image = Image.LoadPixelData(textureUpload.Data.ToArray(), textureUpload.Width, textureUpload.Height); + var image = Image.LoadPixelData(textureUpload.Data, textureUpload.Width, textureUpload.Height); // The original texture upload will no longer be returned or used. textureUpload.Dispose(); From 4c7678225ee018e24724024fe88580c024164b55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Mar 2024 12:13:41 +0800 Subject: [PATCH 723/915] Update framework --- 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 1b395a7c83..4901f30d8a 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + diff --git a/osu.iOS.props b/osu.iOS.props index 747d6059da..6b63bfa1e2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -23,6 +23,6 @@ iossimulator-x64 - + From 3a224211aa322a0055342f10bd36e0af3c3b078c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Mar 2024 12:17:00 +0800 Subject: [PATCH 724/915] Update various packages which shouldn't cause issues --- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- osu.Game/osu.Game.csproj | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 64da5412a8..af84ee47f1 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -7,7 +7,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 942763e388..b143a3a6b1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -20,8 +20,8 @@ - - + + @@ -35,14 +35,14 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + From 98ca021e6628d94df508709482f047a2cff7cdde Mon Sep 17 00:00:00 2001 From: jvyden Date: Wed, 6 Mar 2024 01:17:11 -0500 Subject: [PATCH 725/915] Catch and warn about osu!stable lobbies --- osu.Desktop/DiscordRichPresence.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 8fecd015d4..b4a7e80d48 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -191,6 +191,15 @@ namespace osu.Desktop game.Window?.Raise(); Logger.Log($"Received room secret from Discord RPC Client: {args.Secret}", LoggingTarget.Network, LogLevel.Debug); + // Stable and Lazer share the same Discord client ID, meaning they can accept join requests from each other. + // Since they aren't compatible in multi, see if stable's format is being used and log to avoid confusion. + // https://discord.com/channels/188630481301012481/188630652340404224/1214697229063946291 + if (args.Secret[0] != '{') + { + Logger.Log("osu!stable rooms are not compatible with lazer.", LoggingTarget.Network, LogLevel.Important); + return; + } + if (!tryParseRoomSecret(args.Secret, out long roomId, out string? password)) { Logger.Log("Could not join multiplayer room.", LoggingTarget.Network, LogLevel.Important); From 53fffc6a75df70e82be5c1e1a3d2fe633f86c834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 6 Mar 2024 07:57:59 +0100 Subject: [PATCH 726/915] Remove unused using directives --- osu.Game/Overlays/Settings/SettingsNumberBox.cs | 1 - osu.Game/Screens/Menu/LogoVisualisation.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsNumberBox.cs b/osu.Game/Overlays/Settings/SettingsNumberBox.cs index cdf648fc5f..fbcdb4a968 100644 --- a/osu.Game/Overlays/Settings/SettingsNumberBox.cs +++ b/osu.Game/Overlays/Settings/SettingsNumberBox.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index c47ce91711..6d9d2f69b7 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -14,7 +14,6 @@ using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Rendering.Vertices; using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Textures; -using osu.Framework.Utils; using osu.Game.Beatmaps; using osuTK; using osuTK.Graphics; From 08609e19d6bb13669cb4f44e0ae6b80a7444c786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 6 Mar 2024 11:40:10 +0100 Subject: [PATCH 727/915] Fix osu! standardised score estimation algorithm violating basic invariants As it turns out, the "lower" and "upper" estimates of the combo portion of the score being converted were misnomers. In selected cases (scores with high accuracy but combo being lower than max by more than a few objects) the janky score-based math could overestimate the count of remaining objects in a map. For instance, in one case the numbers worked out something like this: - Accuracy: practically 100% - Max combo on beatmap: 571x - Max combo for score: 551x The score-based estimation attempts to extract a "remaining object count" from score, by doing something along of sqrt(571^2 - 551^2). That comes out to _almost 150_. Which leads to the estimation overshooting the total max combo count on the beatmap by some hundred objects. To curtail this nonsense, enforce some basic invariants: - Neither estimate is allowed to exceed maximum achievable - Ensure that lower estimate is really lower and upper is really upper by just looking at the values and making sure that is so rather than just saying that it is. --- .../Database/StandardisedScoreMigrationTools.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index 0594c80390..53ff1a25ca 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -415,7 +415,7 @@ namespace osu.Game.Database // Calculate how many times the longest combo the user has achieved in the play can repeat // without exceeding the combo portion in score V1 as achieved by the player. - // This is a pessimistic estimate; it intentionally does not operate on object count and uses only score instead. + // This it intentionally does not operate on object count and uses only score instead. double maximumOccurrencesOfLongestCombo = Math.Floor(comboPortionInScoreV1 / comboPortionFromLongestComboInScoreV1); double comboPortionFromRepeatedLongestCombosInScoreV1 = maximumOccurrencesOfLongestCombo * comboPortionFromLongestComboInScoreV1; @@ -426,13 +426,12 @@ namespace osu.Game.Database // ...and then based on that raw combo length, we calculate how much this last combo is worth in standardised score. double remainingComboPortionInStandardisedScore = Math.Pow(remainingCombo, 1 + ScoreProcessor.COMBO_EXPONENT); - double lowerEstimateOfComboPortionInStandardisedScore + double scoreBasedEstimateOfComboPortionInStandardisedScore = maximumOccurrencesOfLongestCombo * comboPortionFromLongestComboInStandardisedScore + remainingComboPortionInStandardisedScore; // Compute approximate upper estimate new score for that play. // This time, divide the remaining combo among remaining objects equally to achieve longest possible combo lengths. - // There is no rigorous proof that doing this will yield a correct upper bound, but it seems to work out in practice. remainingComboPortionInScoreV1 = comboPortionInScoreV1 - comboPortionFromLongestComboInScoreV1; double remainingCountOfObjectsGivingCombo = maximumLegacyCombo - score.MaxCombo - score.Statistics.GetValueOrDefault(HitResult.Miss); // Because we assumed all combos were equal, `remainingComboPortionInScoreV1` @@ -449,7 +448,17 @@ namespace osu.Game.Database // we can skip adding the 1 and just multiply by x ^ 0.5. remainingComboPortionInStandardisedScore = remainingCountOfObjectsGivingCombo * Math.Pow(lengthOfRemainingCombos, ScoreProcessor.COMBO_EXPONENT); - double upperEstimateOfComboPortionInStandardisedScore = comboPortionFromLongestComboInStandardisedScore + remainingComboPortionInStandardisedScore; + double objectCountBasedEstimateOfComboPortionInStandardisedScore = comboPortionFromLongestComboInStandardisedScore + remainingComboPortionInStandardisedScore; + + // Enforce some invariants on both of the estimates. + // In rare cases they can produce invalid results. + scoreBasedEstimateOfComboPortionInStandardisedScore = + Math.Clamp(scoreBasedEstimateOfComboPortionInStandardisedScore, 0, maximumAchievableComboPortionInStandardisedScore); + objectCountBasedEstimateOfComboPortionInStandardisedScore = + Math.Clamp(objectCountBasedEstimateOfComboPortionInStandardisedScore, 0, maximumAchievableComboPortionInStandardisedScore); + + double lowerEstimateOfComboPortionInStandardisedScore = Math.Min(scoreBasedEstimateOfComboPortionInStandardisedScore, objectCountBasedEstimateOfComboPortionInStandardisedScore); + double upperEstimateOfComboPortionInStandardisedScore = Math.Max(scoreBasedEstimateOfComboPortionInStandardisedScore, objectCountBasedEstimateOfComboPortionInStandardisedScore); // Approximate by combining lower and upper estimates. // As the lower-estimate is very pessimistic, we use a 30/70 ratio From 5b6703ec0da46259daddd777ee88be5317aba2d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Mar 2024 19:23:29 +0800 Subject: [PATCH 728/915] Move optimisation to isolated method --- osu.Game/Storyboards/StoryboardSprite.cs | 76 +++++++++++++----------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 350438942e..4992ae128d 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -90,41 +90,8 @@ namespace osu.Game.Storyboards // Ignore the whole setup if there are loops. In theory they can be handled here too, however the logic will be overly complex. if (loops.Count == 0) { - // Here we are starting from maximum value and trying to minimise the end time on each step. - // There are few solid guesses we can make using which sprite's end time can be minimised: alpha = 0, scale = 0, colour.a = 0. - double[] deathTimes = - { - double.MaxValue, // alpha - double.MaxValue, // colour alpha - double.MaxValue, // scale - double.MaxValue, // scale x - double.MaxValue, // scale y - }; - - // The loops below are following the same pattern. - // We could be using TimelineGroup.EndValue here, however it's possible to have multiple commands with 0 value in a row - // so we are saving the earliest of them. - foreach (var alphaCommand in TimelineGroup.Alpha.Commands) - { - deathTimes[0] = alphaCommand.EndValue == 0 - ? Math.Min(alphaCommand.EndTime, deathTimes[0]) // commands are ordered by the start time, however end time may vary. Save the earliest. - : double.MaxValue; // If value isn't 0 (sprite becomes visible again), revert the saved state. - } - - foreach (var colourCommand in TimelineGroup.Colour.Commands) - deathTimes[1] = colourCommand.EndValue.A == 0 ? Math.Min(colourCommand.EndTime, deathTimes[1]) : double.MaxValue; - - foreach (var scaleCommand in TimelineGroup.Scale.Commands) - deathTimes[2] = scaleCommand.EndValue == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[2]) : double.MaxValue; - - foreach (var scaleCommand in TimelineGroup.VectorScale.Commands) - { - deathTimes[3] = scaleCommand.EndValue.X == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[3]) : double.MaxValue; - deathTimes[4] = scaleCommand.EndValue.Y == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[4]) : double.MaxValue; - } - // Take the minimum time of all the potential "death" reasons. - latestEndTime = deathTimes.Min(); + latestEndTime = calculateOptimisedEndTime(TimelineGroup); } // If the logic above fails to find anything or discarded by the fact that there are loops present, latestEndTime will be double.MaxValue @@ -238,6 +205,47 @@ namespace osu.Game.Storyboards return commands; } + private static double calculateOptimisedEndTime(CommandTimelineGroup timelineGroup) + { + // Here we are starting from maximum value and trying to minimise the end time on each step. + // There are few solid guesses we can make using which sprite's end time can be minimised: alpha = 0, scale = 0, colour.a = 0. + double[] deathTimes = + { + double.MaxValue, // alpha + double.MaxValue, // colour alpha + double.MaxValue, // scale + double.MaxValue, // scale x + double.MaxValue, // scale y + }; + + // The loops below are following the same pattern. + // We could be using TimelineGroup.EndValue here, however it's possible to have multiple commands with 0 value in a row + // so we are saving the earliest of them. + foreach (var alphaCommand in timelineGroup.Alpha.Commands) + { + if (alphaCommand.EndValue == 0) + // commands are ordered by the start time, however end time may vary. Save the earliest. + deathTimes[0] = Math.Min(alphaCommand.EndTime, deathTimes[0]); + else + // If value isn't 0 (sprite becomes visible again), revert the saved state. + deathTimes[0] = double.MaxValue; + } + + foreach (var colourCommand in timelineGroup.Colour.Commands) + deathTimes[1] = colourCommand.EndValue.A == 0 ? Math.Min(colourCommand.EndTime, deathTimes[1]) : double.MaxValue; + + foreach (var scaleCommand in timelineGroup.Scale.Commands) + deathTimes[2] = scaleCommand.EndValue == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[2]) : double.MaxValue; + + foreach (var scaleCommand in timelineGroup.VectorScale.Commands) + { + deathTimes[3] = scaleCommand.EndValue.X == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[3]) : double.MaxValue; + deathTimes[4] = scaleCommand.EndValue.Y == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[4]) : double.MaxValue; + } + + return deathTimes.Min(); + } + public override string ToString() => $"{Path}, {Origin}, {InitialPosition}"; From 672f645cbab747d02cbb61d31283f604a3244ed8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 6 Mar 2024 18:39:18 +0300 Subject: [PATCH 729/915] Clamp only on horizontal sides --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs index 6ba91fbbd5..8f9a2d7e74 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs @@ -47,19 +47,18 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy AutoSizeAxes = Axes.Y, Children = new Drawable[] { + // Key images are placed side-to-side on the playfield, therefore ClampToEdge must be used to prevent any gaps between each key. upSprite = new Sprite { Origin = Anchor.BottomCentre, - // ClampToEdge is used to avoid gaps between keys, see: https://github.com/ppy/osu/issues/27431 - Texture = skin.GetTexture(upImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge), + Texture = skin.GetTexture(upImage, WrapMode.ClampToEdge, default), RelativeSizeAxes = Axes.X, Width = 1 }, downSprite = new Sprite { Origin = Anchor.BottomCentre, - // ClampToEdge is used to avoid gaps between keys, see: https://github.com/ppy/osu/issues/27431 - Texture = skin.GetTexture(downImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge), + Texture = skin.GetTexture(downImage, WrapMode.ClampToEdge, default), RelativeSizeAxes = Axes.X, Width = 1, Alpha = 0 From 3121cf81e6f8ad0dd8ecb80b5dfc2cff4f55c306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 6 Mar 2024 21:30:09 +0100 Subject: [PATCH 730/915] Bump score version --- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 775d87f3f2..4ee4231925 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -45,9 +45,10 @@ namespace osu.Game.Scoring.Legacy /// /// 30000013: All local scores will use lazer definitions of ranks for consistency. Recalculates the rank of all scores. /// 30000014: Fix edge cases in conversion for osu! scores on selected beatmaps. Reconvert all scores. + /// 30000015: Fix osu! standardised score estimation algorithm violating basic invariants. Reconvert all scores. /// /// - public const int LATEST_VERSION = 30000014; + public const int LATEST_VERSION = 30000015; /// /// The first stable-compatible YYYYMMDD format version given to lazer usage of replays. From aa3cd402ca9ed3d666aac0e9934f9290af01b828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 6 Mar 2024 21:30:31 +0100 Subject: [PATCH 731/915] Fix broken english --- osu.Game/Database/StandardisedScoreMigrationTools.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index 53ff1a25ca..6f2f8d64fa 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -415,7 +415,7 @@ namespace osu.Game.Database // Calculate how many times the longest combo the user has achieved in the play can repeat // without exceeding the combo portion in score V1 as achieved by the player. - // This it intentionally does not operate on object count and uses only score instead. + // This intentionally does not operate on object count and uses only score instead. double maximumOccurrencesOfLongestCombo = Math.Floor(comboPortionInScoreV1 / comboPortionFromLongestComboInScoreV1); double comboPortionFromRepeatedLongestCombosInScoreV1 = maximumOccurrencesOfLongestCombo * comboPortionFromLongestComboInScoreV1; From 336a6180e537ba1c205c488cead7c5494446b705 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 7 Mar 2024 08:20:20 +0300 Subject: [PATCH 732/915] Expose `TRANSITION_LENGTH` from tab control --- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index c260c92b43..f24977927f 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -116,18 +116,18 @@ namespace osu.Game.Graphics.UserInterface } } - private const float transition_length = 500; + protected const float TRANSITION_LENGTH = 500; - protected void FadeHovered() + protected virtual void FadeHovered() { - Bar.FadeIn(transition_length, Easing.OutQuint); - Text.FadeColour(Color4.White, transition_length, Easing.OutQuint); + Bar.FadeIn(TRANSITION_LENGTH, Easing.OutQuint); + Text.FadeColour(Color4.White, TRANSITION_LENGTH, Easing.OutQuint); } - protected void FadeUnhovered() + protected virtual void FadeUnhovered() { - Bar.FadeTo(IsHovered ? 1 : 0, transition_length, Easing.OutQuint); - Text.FadeColour(IsHovered ? Color4.White : AccentColour, transition_length, Easing.OutQuint); + Bar.FadeTo(IsHovered ? 1 : 0, TRANSITION_LENGTH, Easing.OutQuint); + Text.FadeColour(IsHovered ? Color4.White : AccentColour, TRANSITION_LENGTH, Easing.OutQuint); } protected override bool OnHover(HoverEvent e) From 0fe139a1892423030b1de36df957bff095fc6587 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 7 Mar 2024 08:20:46 +0300 Subject: [PATCH 733/915] Adjust editor screen switcher control design and behaviour --- .../Menus/EditorScreenSwitcherControl.cs | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs b/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs index 1f6d61d0ad..2b0b1ea219 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Edit.Components.Menus { @@ -21,7 +22,7 @@ namespace osu.Game.Screens.Edit.Components.Menus TabContainer.RelativeSizeAxes &= ~Axes.X; TabContainer.AutoSizeAxes = Axes.X; - TabContainer.Padding = new MarginPadding(10); + TabContainer.Spacing = Vector2.Zero; } [BackgroundDependencyLoader] @@ -42,30 +43,51 @@ namespace osu.Game.Screens.Edit.Components.Menus private partial class TabItem : OsuTabItem { - private const float transition_length = 250; + private readonly Box background; + private Color4 backgroundIdleColour; + private Color4 backgroundHoverColour; public TabItem(EditorScreenMode value) : base(value) { - Text.Margin = new MarginPadding(); + Text.Margin = new MarginPadding(10); Text.Anchor = Anchor.CentreLeft; Text.Origin = Anchor.CentreLeft; Text.Font = OsuFont.TorusAlternate; + Add(background = new Box + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue, + }); + Bar.Expire(); } - protected override void OnActivated() + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) { - base.OnActivated(); - Bar.ScaleTo(new Vector2(1, 5), transition_length, Easing.OutQuint); + backgroundIdleColour = colourProvider.Background2; + backgroundHoverColour = colourProvider.Background1; } - protected override void OnDeactivated() + protected override void LoadComplete() { - base.OnDeactivated(); - Bar.ScaleTo(Vector2.One, transition_length, Easing.OutQuint); + base.LoadComplete(); + background.Colour = backgroundIdleColour; + } + + protected override void FadeHovered() + { + base.FadeHovered(); + background.FadeColour(backgroundHoverColour, TRANSITION_LENGTH, Easing.OutQuint); + } + + protected override void FadeUnhovered() + { + base.FadeUnhovered(); + background.FadeColour(backgroundIdleColour, TRANSITION_LENGTH, Easing.OutQuint); } } } From 56caf1935043112ec13c5d0b1d43e9d23b8d1f7e Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 6 Mar 2024 22:48:54 -0800 Subject: [PATCH 734/915] Add visual test for failed S display --- .../TestSceneExpandedPanelMiddleContent.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs index d71c72f4ec..ceb2d4927c 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs @@ -88,8 +88,21 @@ namespace osu.Game.Tests.Visual.Ranking AddAssert("play time not displayed", () => !this.ChildrenOfType().Any()); } - private void showPanel(ScoreInfo score) => - Child = new ExpandedPanelMiddleContentContainer(score); + [TestCase(false)] + [TestCase(true)] + public void TestFailedSDisplay(bool withFlair) + { + AddStep("show failed S score", () => + { + var score = TestResources.CreateTestScoreInfo(createTestBeatmap(new RealmUser())); + score.Rank = ScoreRank.A; + score.Accuracy = 0.975; + showPanel(score, withFlair); + }); + } + + private void showPanel(ScoreInfo score, bool withFlair = false) => + Child = new ExpandedPanelMiddleContentContainer(score, withFlair); private BeatmapInfo createTestBeatmap([NotNull] RealmUser author) { @@ -107,7 +120,7 @@ namespace osu.Game.Tests.Visual.Ranking private partial class ExpandedPanelMiddleContentContainer : Container { - public ExpandedPanelMiddleContentContainer(ScoreInfo score) + public ExpandedPanelMiddleContentContainer(ScoreInfo score, bool withFlair) { Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -119,7 +132,7 @@ namespace osu.Game.Tests.Visual.Ranking RelativeSizeAxes = Axes.Both, Colour = Color4Extensions.FromHex("#444"), }, - new ExpandedPanelMiddleContent(score) + new ExpandedPanelMiddleContent(score, withFlair) }; } } From c36232bc02ff9289b0ecc16a6235049f3ddaa63a Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 6 Mar 2024 20:08:46 -0800 Subject: [PATCH 735/915] Fix results screen accuracy circle not showing correctly for failed S with no flair --- .../Expanded/Accuracy/AccuracyCircle.cs | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index 54829a6274..f04e4a6444 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -194,11 +194,11 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy rankText = new RankText(score.Rank) }; + if (isFailedSDueToMisses) + AddInternal(failedSRankText = new RankText(ScoreRank.S)); + if (withFlair) { - if (isFailedSDueToMisses) - AddInternal(failedSRankText = new RankText(ScoreRank.S)); - var applauseSamples = new List { applauseSampleName }; if (score.Rank >= ScoreRank.B) // when rank is B or higher, play legacy applause sample on legacy skins. @@ -326,24 +326,25 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy { rankText.Appear(); - if (!withFlair) return; - - Schedule(() => - { - isTicking = false; - rankImpactSound.Play(); - }); - - const double applause_pre_delay = 545f; - const double applause_volume = 0.8f; - - using (BeginDelayedSequence(applause_pre_delay)) + if (withFlair) { Schedule(() => { - rankApplauseSound.VolumeTo(applause_volume); - rankApplauseSound.Play(); + isTicking = false; + rankImpactSound.Play(); }); + + const double applause_pre_delay = 545f; + const double applause_volume = 0.8f; + + using (BeginDelayedSequence(applause_pre_delay)) + { + Schedule(() => + { + rankApplauseSound.VolumeTo(applause_volume); + rankApplauseSound.Play(); + }); + } } } From 1cafb0997713ee387f8994e972d64ad908aa4181 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 7 Mar 2024 17:22:38 +0900 Subject: [PATCH 736/915] Increase border thickness --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index 08d00f8ac2..ba49810b2b 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Play AutoSizeAxes = Axes.Both, Masking = true, BorderColour = colours.Yellow, - BorderThickness = 1, + BorderThickness = 2, Children = new Drawable[] { new Box From 039520d55dc9b9cc55e143a6da8bb87f684ef882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 7 Mar 2024 09:49:20 +0100 Subject: [PATCH 737/915] Use slightly nicer parameterisation in test --- .../Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs index ceb2d4927c..d97946a1d5 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs @@ -88,9 +88,8 @@ namespace osu.Game.Tests.Visual.Ranking AddAssert("play time not displayed", () => !this.ChildrenOfType().Any()); } - [TestCase(false)] - [TestCase(true)] - public void TestFailedSDisplay(bool withFlair) + [Test] + public void TestFailedSDisplay([Values] bool withFlair) { AddStep("show failed S score", () => { From ca92a31cf97bcb28fd8d9e67fe0ac83b1085ac80 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 7 Mar 2024 21:10:11 +0900 Subject: [PATCH 738/915] Fix missing event unbinds --- osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs | 9 +++++++++ .../Components/Timeline/TimelineHitObjectBlueprint.cs | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index 5ddc627642..3365b206cf 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Game.Rulesets.Mania.UI; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Skinning; using osu.Game.Rulesets.Mods; @@ -101,6 +102,14 @@ namespace osu.Game.Rulesets.Mania.Mods return base.GetHeight(coverage) * reference_playfield_height / availablePlayfieldHeight; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (skin.IsNotNull()) + skin.SourceChanged -= onSkinChanged; + } } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 47dc3fb82e..d4afcc0151 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -6,6 +6,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -265,6 +266,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline return !Precision.AlmostIntersects(maskingBounds, rect); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (skin.IsNotNull()) + skin.SourceChanged -= updateColour; + } + private partial class Tick : Circle { public Tick() From 87b4406bdc01d5ff5a9dd0cbff59fdf4f25f5829 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Mar 2024 09:41:28 +0800 Subject: [PATCH 739/915] Pad at minimum three digits for argon pp display --- osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs index 022c1fab9e..c57e7bc7ea 100644 --- a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.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 osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; @@ -55,7 +56,7 @@ namespace osu.Game.Screens.Play.HUD private void updateWireframe() { - int digitsRequiredForDisplayCount = getDigitsRequiredForDisplayCount(); + int digitsRequiredForDisplayCount = Math.Max(3, getDigitsRequiredForDisplayCount()); if (digitsRequiredForDisplayCount != text.WireframeTemplate.Length) text.WireframeTemplate = new string('#', digitsRequiredForDisplayCount); From f2753ef7a225316ec96ecb1ca8e1be261d2ca570 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Mar 2024 09:41:38 +0800 Subject: [PATCH 740/915] Decrease size of pp display relative to accuracy --- osu.Game/Skinning/ArgonSkin.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index 24e17d21f4..953badaf65 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -232,7 +232,10 @@ namespace osu.Game.Skinning CornerRadius = { Value = 0.5f } }, new ArgonAccuracyCounter(), - new ArgonPerformancePointsCounter(), + new ArgonPerformancePointsCounter + { + Scale = new Vector2(0.8f), + }, new ArgonComboCounter { Scale = new Vector2(1.3f) From ae2ef8ee1ece9083ca41118dc59846047d021022 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Mar 2024 10:19:00 +0800 Subject: [PATCH 741/915] Fix typo in wireframe description --- osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs | 2 +- osu.Game/Screens/Play/HUD/ArgonComboCounter.cs | 2 +- osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs | 2 +- osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs index 4cc04e1485..d7fe1f52ff 100644 --- a/osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonAccuracyCounter.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Play.HUD { protected override double RollingDuration => 250; - [SettingSource("Wireframe opacity", "Controls the opacity of the wire frames behind the digits.")] + [SettingSource("Wireframe opacity", "Controls the opacity of the wireframes behind the digits.")] public BindableFloat WireframeOpacity { get; } = new BindableFloat(0.25f) { Precision = 0.01f, diff --git a/osu.Game/Screens/Play/HUD/ArgonComboCounter.cs b/osu.Game/Screens/Play/HUD/ArgonComboCounter.cs index 3f187650b2..db0480c566 100644 --- a/osu.Game/Screens/Play/HUD/ArgonComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonComboCounter.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Play.HUD protected override double RollingDuration => 250; - [SettingSource("Wireframe opacity", "Controls the opacity of the wire frames behind the digits.")] + [SettingSource("Wireframe opacity", "Controls the opacity of the wireframes behind the digits.")] public BindableFloat WireframeOpacity { get; } = new BindableFloat(0.25f) { Precision = 0.01f, diff --git a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs index c57e7bc7ea..d4d842bd9a 100644 --- a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Play.HUD private const float alpha_when_invalid = 0.3f; - [SettingSource("Wireframe opacity", "Controls the opacity of the wire frames behind the digits.")] + [SettingSource("Wireframe opacity", "Controls the opacity of the wireframes behind the digits.")] public BindableFloat WireframeOpacity { get; } = new BindableFloat(0.25f) { Precision = 0.01f, diff --git a/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs b/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs index a14ab3cbcd..8658651407 100644 --- a/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonScoreCounter.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Play.HUD protected override double RollingDuration => 250; - [SettingSource("Wireframe opacity", "Controls the opacity of the wire frames behind the digits.")] + [SettingSource("Wireframe opacity", "Controls the opacity of the wireframes behind the digits.")] public BindableFloat WireframeOpacity { get; } = new BindableFloat(0.25f) { Precision = 0.01f, From 0ebb12f67f97d82ef8931df095445c1c6542ba08 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Mar 2024 10:23:43 +0800 Subject: [PATCH 742/915] Move skinnable interface specification to non-`abstract` classes --- osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs | 3 ++- osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs | 2 +- .../Skinning/Triangles/TrianglesPerformancePointsCounter.cs | 4 +--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs index d4d842bd9a..1620da2f2e 100644 --- a/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/ArgonPerformancePointsCounter.cs @@ -9,10 +9,11 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Localisation.SkinComponents; using osu.Game.Resources.Localisation.Web; +using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public partial class ArgonPerformancePointsCounter : PerformancePointsCounter + public partial class ArgonPerformancePointsCounter : PerformancePointsCounter, ISerialisableDrawable { private ArgonCounterTextComponent text = null!; diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index c5ad106bcc..25c1387220 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -27,7 +27,7 @@ using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { - public abstract partial class PerformancePointsCounter : RollingCounter, ISerialisableDrawable + public abstract partial class PerformancePointsCounter : RollingCounter { public bool UsesFixedAnchor { get; set; } diff --git a/osu.Game/Skinning/Triangles/TrianglesPerformancePointsCounter.cs b/osu.Game/Skinning/Triangles/TrianglesPerformancePointsCounter.cs index 99da2c0942..d6753a81ba 100644 --- a/osu.Game/Skinning/Triangles/TrianglesPerformancePointsCounter.cs +++ b/osu.Game/Skinning/Triangles/TrianglesPerformancePointsCounter.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,7 +14,7 @@ using osuTK; namespace osu.Game.Skinning.Triangles { - public partial class TrianglesPerformancePointsCounter : PerformancePointsCounter + public partial class TrianglesPerformancePointsCounter : PerformancePointsCounter, ISerialisableDrawable { protected override bool IsRollingProportional => true; From 928639863325278dd66fe428bdd10870b9ca0e64 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Mar 2024 10:26:08 +0800 Subject: [PATCH 743/915] Move naming migrations to more correct place --- osu.Game/Skinning/Skin.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 91b21f0308..e4ca908d90 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -133,6 +133,11 @@ namespace osu.Game.Skinning SkinLayoutInfo? layoutInfo = null; + // handle namespace changes... + jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.SongProgress", @"osu.Game.Screens.Play.HUD.DefaultSongProgress"); + jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.HUD.LegacyComboCounter", @"osu.Game.Skinning.LegacyComboCounter"); + jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.HUD.PerformancePointsCounter", @"osu.Game.Skinning.Triangles.TrianglesPerformancePointsCounter"); + try { // First attempt to deserialise using the new SkinLayoutInfo format @@ -150,11 +155,6 @@ namespace osu.Game.Skinning // If deserialisation using SkinLayoutInfo fails, attempt to deserialise using the old naked list. if (layoutInfo == null) { - // handle namespace changes... - jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.SongProgress", @"osu.Game.Screens.Play.HUD.DefaultSongProgress"); - jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.HUD.LegacyComboCounter", @"osu.Game.Skinning.LegacyComboCounter"); - jsonContent = jsonContent.Replace(@"osu.Game.Screens.Play.HUD.PerformancePointsCounter", @"osu.Game.Skinning.Triangles.TrianglesPerformancePointsCounter"); - var deserializedContent = JsonConvert.DeserializeObject>(jsonContent); if (deserializedContent == null) From fcc35a6accce8c849ec1de154d01e4fffa7ebc4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Mar 2024 11:37:13 +0800 Subject: [PATCH 744/915] Fix cross-talk between pooled `DrawableSliderRepeat` usage causing incorrect rotation --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index fcbd0edfe0..27c5278614 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -79,6 +79,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.OnApply(); Position = HitObject.Position - DrawableSlider.Position; + hasRotation = false; } protected override void CheckForResult(bool userTriggered, double timeOffset) => DrawableSlider.SliderInputManager.TryJudgeNestedObject(this, timeOffset); From 5e7d9ea04ac544b43bb349b99151f2599da5c747 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Mar 2024 13:59:04 +0800 Subject: [PATCH 745/915] Adjust scroll speed back to original --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index a5fc75aea3..dcd78833bd 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -346,7 +346,7 @@ namespace osu.Game.Overlays.Mods ScheduleAfterChildren(() => { columnScroll.ScrollToEnd(false); - columnScroll.ScrollTo(0, true, 0.0055); + columnScroll.ScrollTo(0); }); } From 44d0dc6113a408a15a18025325e55646a2147b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 8 Mar 2024 11:05:07 +0100 Subject: [PATCH 746/915] Fix 1px flashlight gaps when gameplay scaling mode is active Closes https://github.com/ppy/osu/issues/27522. Concerns mostly taiko and catch. Not much of a proper fix rather than a workaround but it is what it is. I tried a few other things, including setting `MaskingSmoothness = 0` on the scaling container itself, to no avail. --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index c3775b0875..c924915bd0 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Rendering.Vertices; @@ -88,7 +89,13 @@ namespace osu.Game.Rulesets.Mods flashlight.Combo.BindTo(Combo); flashlight.GetPlayfieldScale = () => drawableRuleset.Playfield.Scale; - drawableRuleset.Overlays.Add(flashlight); + drawableRuleset.Overlays.Add(new Container + { + RelativeSizeAxes = Axes.Both, + // workaround for 1px gaps on the edges of the playfield which would sometimes show with "gameplay" screen scaling active. + Padding = new MarginPadding(-1), + Child = flashlight, + }); } protected abstract Flashlight CreateFlashlight(); From 46e5bda40c68e15aca0dcbd3d468144d9efe6065 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Mar 2024 19:02:12 +0800 Subject: [PATCH 747/915] Fix test failures --- osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs index 3dca179f2f..075fdd88ca 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModFlashlight.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods PassCondition = () => { var flashlightOverlay = Player.DrawableRuleset.Overlays - .OfType.Flashlight>() + .ChildrenOfType.Flashlight>() .First(); return Precision.AlmostEquals(mod.DefaultFlashlightSize * .5f, flashlightOverlay.GetSize()); From ad842b60f5416c83edf0f341575bd80572465b58 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 8 Mar 2024 21:43:18 +0900 Subject: [PATCH 748/915] Add support for Argon hitsounds --- osu.Game/Skinning/ArgonProSkin.cs | 6 ++++-- osu.Game/Skinning/ArgonSkin.cs | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/ArgonProSkin.cs b/osu.Game/Skinning/ArgonProSkin.cs index b753dd8fbe..6ec9945c0e 100644 --- a/osu.Game/Skinning/ArgonProSkin.cs +++ b/osu.Game/Skinning/ArgonProSkin.cs @@ -24,9 +24,11 @@ namespace osu.Game.Skinning { foreach (string lookup in sampleInfo.LookupNames) { - string remappedLookup = lookup.Replace(@"Gameplay/", @"Gameplay/ArgonPro/"); + var sample = Samples?.Get(lookup) + ?? Resources.AudioManager?.Samples.Get(lookup.Replace(@"Gameplay/", @"Gameplay/ArgonPro/")) + ?? Resources.AudioManager?.Samples.Get(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/")) + ?? Resources.AudioManager?.Samples.Get(lookup); - var sample = Samples?.Get(remappedLookup) ?? Resources.AudioManager?.Samples.Get(remappedLookup); if (sample != null) return sample; } diff --git a/osu.Game/Skinning/ArgonSkin.cs b/osu.Game/Skinning/ArgonSkin.cs index 953badaf65..8fd393fcc5 100644 --- a/osu.Game/Skinning/ArgonSkin.cs +++ b/osu.Game/Skinning/ArgonSkin.cs @@ -77,7 +77,10 @@ namespace osu.Game.Skinning { foreach (string lookup in sampleInfo.LookupNames) { - var sample = Samples?.Get(lookup) ?? Resources.AudioManager?.Samples.Get(lookup); + var sample = Samples?.Get(lookup) + ?? Resources.AudioManager?.Samples.Get(lookup.Replace(@"Gameplay/", @"Gameplay/Argon/")) + ?? Resources.AudioManager?.Samples.Get(lookup); + if (sample != null) return sample; } From 27d78fdb087e0be54973ab40fb02818e747b9e62 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Sat, 9 Mar 2024 01:10:28 +0900 Subject: [PATCH 749/915] Add fallback to find spinner samples without a bank prefix --- osu.Game/Audio/HitSampleInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 24cb1730bf..f9c93d72ff 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -80,6 +80,8 @@ namespace osu.Game.Audio yield return $"Gameplay/{Bank}-{Name}{Suffix}"; yield return $"Gameplay/{Bank}-{Name}"; + + yield return $"Gameplay/{Name}"; } } From db1c59475b0e31fd17d6944804c23a65b206c756 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 9 Feb 2024 15:10:45 -0800 Subject: [PATCH 750/915] Wrap beatmap listing filters and match web spacing --- .../BeatmapListingSearchControl.cs | 1 + .../BeatmapListing/BeatmapSearchFilterRow.cs | 37 ++++--------------- ...BeatmapSearchMultipleSelectionFilterRow.cs | 4 +- .../Overlays/BeatmapListing/FilterTabItem.cs | 2 - 4 files changed, 9 insertions(+), 35 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index 3fa0fc7a77..bab64165cb 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -128,6 +128,7 @@ namespace osu.Game.Overlays.BeatmapListing RelativeSizeAxes = Axes.X, Direction = FillDirection.Vertical, Padding = new MarginPadding { Horizontal = 10 }, + Spacing = new Vector2(5), Children = new Drawable[] { generalFilter = new BeatmapSearchGeneralFilterRow(), diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs index 6d75521cb0..f79695a123 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs @@ -1,14 +1,12 @@ // 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.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osuTK; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Localisation; @@ -49,8 +47,6 @@ namespace osu.Game.Overlays.BeatmapListing { new OsuSpriteText { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(size: 13), Text = header }, @@ -69,10 +65,8 @@ namespace osu.Game.Overlays.BeatmapListing { public BeatmapSearchFilter() { - Anchor = Anchor.BottomLeft; - Origin = Anchor.BottomLeft; RelativeSizeAxes = Axes.X; - Height = 15; + AutoSizeAxes = Axes.Y; TabContainer.Spacing = new Vector2(10, 0); @@ -83,33 +77,16 @@ namespace osu.Game.Overlays.BeatmapListing } } - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - if (Dropdown is FilterDropdown fd) - fd.AccentColour = colourProvider.Light2; - } - - protected override Dropdown CreateDropdown() => new FilterDropdown(); + protected override Dropdown CreateDropdown() => null!; protected override TabItem CreateTabItem(T value) => new FilterTabItem(value); - private partial class FilterDropdown : OsuTabDropdown + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer { - protected override DropdownHeader CreateHeader() => new FilterHeader - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight - }; - - private partial class FilterHeader : OsuTabDropdownHeader - { - public FilterHeader() - { - Background.Height = 1; - } - } - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + AllowMultiline = true, + }; } } } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs index abd2643a41..e59beb43ff 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs @@ -52,10 +52,8 @@ namespace osu.Game.Overlays.BeatmapListing [BackgroundDependencyLoader] private void load() { - Anchor = Anchor.BottomLeft; - Origin = Anchor.BottomLeft; RelativeSizeAxes = Axes.X; - Height = 15; + AutoSizeAxes = Axes.Y; Spacing = new Vector2(10, 0); AddRange(GetValues().Select(CreateTabItem)); diff --git a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs index c33d5056fa..831cf812ff 100644 --- a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs +++ b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs @@ -33,8 +33,6 @@ namespace osu.Game.Overlays.BeatmapListing private void load() { AutoSizeAxes = Axes.Both; - Anchor = Anchor.BottomLeft; - Origin = Anchor.BottomLeft; AddRangeInternal(new Drawable[] { text = new OsuSpriteText From 26c97ef73314a5e307beb5b1b2b755fa78188dc7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 9 Mar 2024 00:51:33 +0300 Subject: [PATCH 751/915] Fix WikiPanelContainer causing poor performance --- osu.Game/Overlays/Wiki/WikiPanelContainer.cs | 68 +++++++++++++------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs index cbffe5732e..555dab852e 100644 --- a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs +++ b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs @@ -3,7 +3,6 @@ #nullable disable -using System; using Markdig.Syntax; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -22,29 +21,61 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Wiki { - public partial class WikiPanelContainer : Container + public partial class WikiPanelContainer : CompositeDrawable { - private WikiPanelMarkdownContainer panelContainer; + private const float padding = 3; private readonly string text; - private readonly bool isFullWidth; public WikiPanelContainer(string text, bool isFullWidth = false) { this.text = text; this.isFullWidth = isFullWidth; - - RelativeSizeAxes = Axes.X; - Padding = new MarginPadding(3); } + private PanelBackground background; + [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, IAPIProvider api) + private void load(IAPIProvider api) { - Children = new Drawable[] + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + InternalChildren = new Drawable[] { + background = new PanelBackground + { + BypassAutoSizeAxes = Axes.Both + }, new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding(padding), + Child = new WikiPanelMarkdownContainer(isFullWidth) + { + CurrentPath = $@"{api.WebsiteRootUrl}/wiki/", + Text = text, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + } + } + }; + } + + protected override void Update() + { + base.Update(); + background.Size = Parent!.DrawSize * new Vector2(Size.X, 1); + } + + private partial class PanelBackground : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Padding = new MarginPadding(padding); + InternalChild = new Container { RelativeSizeAxes = Axes.Both, Masking = true, @@ -60,22 +91,9 @@ namespace osu.Game.Overlays.Wiki { Colour = colourProvider.Background4, RelativeSizeAxes = Axes.Both, - }, - }, - panelContainer = new WikiPanelMarkdownContainer(isFullWidth) - { - CurrentPath = $@"{api.WebsiteRootUrl}/wiki/", - Text = text, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - } - }; - } - - protected override void Update() - { - base.Update(); - Height = Math.Max(panelContainer.Height, Parent!.DrawHeight); + } + }; + } } private partial class WikiPanelMarkdownContainer : WikiMarkdownContainer From dd36942508aee46ff0b0357daed108f293260924 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 9 Mar 2024 13:58:05 +0300 Subject: [PATCH 752/915] Reduce allocations in DrawableFlag tooltip --- osu.Game/Users/Drawables/DrawableFlag.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index 289f68ee7f..08c323d42c 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -15,11 +15,14 @@ namespace osu.Game.Users.Drawables { private readonly CountryCode countryCode; - public LocalisableString TooltipText => countryCode == CountryCode.Unknown ? string.Empty : countryCode.GetDescription(); + public LocalisableString TooltipText => countryCode == CountryCode.Unknown ? string.Empty : description; + + private readonly string description; public DrawableFlag(CountryCode countryCode) { this.countryCode = countryCode; + description = countryCode.GetDescription(); } [BackgroundDependencyLoader] From 58b6acde10eee69faedd57fcf5c6f1869eb8fba7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 9 Mar 2024 14:10:32 +0300 Subject: [PATCH 753/915] Further simplify tooltip text creation --- osu.Game/Users/Drawables/DrawableFlag.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index 08c323d42c..39f0ab370b 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -15,14 +15,14 @@ namespace osu.Game.Users.Drawables { private readonly CountryCode countryCode; - public LocalisableString TooltipText => countryCode == CountryCode.Unknown ? string.Empty : description; + public LocalisableString TooltipText => tooltipText; - private readonly string description; + private readonly string tooltipText; public DrawableFlag(CountryCode countryCode) { this.countryCode = countryCode; - description = countryCode.GetDescription(); + tooltipText = countryCode == CountryCode.Unknown ? string.Empty : countryCode.GetDescription(); } [BackgroundDependencyLoader] From b8a362fcb69390fb774bcb5a4afc78bb138ddf7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 9 Mar 2024 20:17:27 +0800 Subject: [PATCH 754/915] Simplify assignment by using an auto property --- osu.Game/Users/Drawables/DrawableFlag.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index 39f0ab370b..6813b13cef 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -15,14 +15,12 @@ namespace osu.Game.Users.Drawables { private readonly CountryCode countryCode; - public LocalisableString TooltipText => tooltipText; - - private readonly string tooltipText; + public LocalisableString TooltipText { get; } public DrawableFlag(CountryCode countryCode) { this.countryCode = countryCode; - tooltipText = countryCode == CountryCode.Unknown ? string.Empty : countryCode.GetDescription(); + TooltipText = countryCode == CountryCode.Unknown ? string.Empty : countryCode.GetDescription(); } [BackgroundDependencyLoader] From 31739be49912ffedf1ae7a4deeb747b8b2ec9204 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 9 Mar 2024 20:46:48 +0800 Subject: [PATCH 755/915] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b143a3a6b1..55bd68dea0 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From 549a8d678e4a9d8c91a1a220bef6f3519aaa687d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 9 Mar 2024 20:50:54 +0300 Subject: [PATCH 756/915] Reduce allocations in ControlPointList --- .../Screens/Edit/Timing/ControlPointList.cs | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointList.cs b/osu.Game/Screens/Edit/Timing/ControlPointList.cs index 7cd1dbc630..4e4090ccd0 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointList.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointList.cs @@ -162,26 +162,43 @@ namespace osu.Game.Screens.Edit.Timing // If the selected group only has one control point, update the tracking type. case 1: - trackedType = selectedGroup.Value?.ControlPoints.Single().GetType(); + trackedType = selectedGroup.Value?.ControlPoints[0].GetType(); break; // If the selected group has more than one control point, choose the first as the tracking type // if we don't already have a singular tracked type. default: - trackedType ??= selectedGroup.Value?.ControlPoints.FirstOrDefault()?.GetType(); + trackedType ??= selectedGroup.Value?.ControlPoints[0].GetType(); break; } } if (trackedType != null) { + double accurateTime = clock.CurrentTimeAccurate; + // We don't have an efficient way of looking up groups currently, only individual point types. // To improve the efficiency of this in the future, we should reconsider the overall structure of ControlPointInfo. // Find the next group which has the same type as the selected one. - var found = Beatmap.ControlPointInfo.Groups - .Where(g => g.ControlPoints.Any(cp => cp.GetType() == trackedType)) - .LastOrDefault(g => g.Time <= clock.CurrentTimeAccurate); + ControlPointGroup? found = null; + + for (int i = 0; i < Beatmap.ControlPointInfo.Groups.Count; i++) + { + var g = Beatmap.ControlPointInfo.Groups[i]; + + if (g.Time > accurateTime) + continue; + + for (int j = 0; j < g.ControlPoints.Count; j++) + { + if (g.ControlPoints[j].GetType() == trackedType) + { + found = g; + break; + } + } + } if (found != null) selectedGroup.Value = found; From e08651668c46f3c7cbef87b2fadd23d609e9fee2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 9 Mar 2024 21:55:00 +0300 Subject: [PATCH 757/915] Fix TestSceneSkinnableSound failing --- osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs index 3f78dbfd96..6c8dc6a220 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Gameplay private TestSkinSourceContainer skinSource = null!; private PausableSkinnableSound skinnableSound = null!; - private const string sample_lookup = "Gameplay/normal-sliderslide"; + private const string sample_lookup = "Gameplay/Argon/normal-sliderslide"; [SetUpSteps] public void SetUpSteps() From 6ff4b1d7e3d461adf4b67c676a62f39ecfd7ec21 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 10 Mar 2024 15:42:03 +0300 Subject: [PATCH 758/915] Don't update SubTreeMasking in OsuPlayfield --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 411a02c5af..80379094ae 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -9,6 +9,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -35,6 +36,8 @@ namespace osu.Game.Rulesets.Osu.UI private readonly JudgementPooler judgementPooler; + public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; + public SmokeContainer Smoke { get; } public FollowPointRenderer FollowPoints { get; } From 6ecef33fd7a9dcee06349e1075e10ed3bce9e7c7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 10 Mar 2024 22:45:29 +0300 Subject: [PATCH 759/915] Fic incorrect ExtendableCircle gradient --- .../Components/Timeline/TimelineHitObjectBlueprint.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index d4afcc0151..7e6e886ff7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -471,6 +471,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline /// public partial class ExtendableCircle : CompositeDrawable { + public new ColourInfo Colour + { + get => Content.Colour; + set => Content.Colour = value; + } + protected readonly Circle Content; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Content.ReceivePositionalInputAt(screenSpacePos); From 283de215d37aca9605bbf5b0a11dc440455bb348 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 11 Mar 2024 01:01:26 +0300 Subject: [PATCH 760/915] Adjust log message and comment --- osu.Desktop/DiscordRichPresence.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index b4a7e80d48..2e5db2f5c1 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -189,20 +189,14 @@ namespace osu.Desktop private void onJoin(object sender, JoinMessage args) { game.Window?.Raise(); - Logger.Log($"Received room secret from Discord RPC Client: {args.Secret}", LoggingTarget.Network, LogLevel.Debug); - // Stable and Lazer share the same Discord client ID, meaning they can accept join requests from each other. + Logger.Log($"Received room secret from Discord RPC Client: \"{args.Secret}\"", LoggingTarget.Network, LogLevel.Debug); + + // Stable and lazer share the same Discord client ID, meaning they can accept join requests from each other. // Since they aren't compatible in multi, see if stable's format is being used and log to avoid confusion. - // https://discord.com/channels/188630481301012481/188630652340404224/1214697229063946291 - if (args.Secret[0] != '{') + if (args.Secret[0] != '{' || !tryParseRoomSecret(args.Secret, out long roomId, out string? password)) { - Logger.Log("osu!stable rooms are not compatible with lazer.", LoggingTarget.Network, LogLevel.Important); - return; - } - - if (!tryParseRoomSecret(args.Secret, out long roomId, out string? password)) - { - Logger.Log("Could not join multiplayer room.", LoggingTarget.Network, LogLevel.Important); + Logger.Log("Could not join multiplayer room, invitation is invalid or incompatible.", LoggingTarget.Network, LogLevel.Important); return; } @@ -211,7 +205,7 @@ namespace osu.Desktop { game.PresentMultiplayerMatch(room, password); }); - request.Failure += _ => Logger.Log($"Could not find room {roomId} from Discord RPC Client", LoggingTarget.Network, LogLevel.Important); + request.Failure += _ => Logger.Log($"Could not join multiplayer room, room could not be found (room ID: {roomId}).", LoggingTarget.Network, LogLevel.Important); api.Queue(request); } From 2be6d1f1c60f6e146b056f3fc42c1205cea22826 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Mar 2024 11:26:03 +0800 Subject: [PATCH 761/915] Apply NRT to `OsuPlayfield` --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 80379094ae..9b8128a107 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Diagnostics; using System.Linq; @@ -79,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.UI NewResult += onNewResult; } - private IHitPolicy hitPolicy; + private IHitPolicy hitPolicy = null!; public IHitPolicy HitPolicy { @@ -119,12 +117,12 @@ namespace osu.Game.Rulesets.Osu.UI judgementAboveHitObjectLayer.Add(judgement.ProxiedAboveHitObjectsContent); } - [BackgroundDependencyLoader(true)] - private void load(OsuRulesetConfigManager config, IBeatmap beatmap) + [BackgroundDependencyLoader] + private void load(OsuRulesetConfigManager? config, IBeatmap? beatmap) { config?.BindWith(OsuRulesetSetting.PlayfieldBorderStyle, playfieldBorder.PlayfieldBorderStyle); - var osuBeatmap = (OsuBeatmap)beatmap; + var osuBeatmap = (OsuBeatmap?)beatmap; RegisterPool(20, 100); From f3d154a9955697cd25db6a2dd3393daf668acac2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Mar 2024 11:28:15 +0800 Subject: [PATCH 762/915] Add inline comment explaining optimisation --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 9b8128a107..63030293ac 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -34,6 +34,8 @@ namespace osu.Game.Rulesets.Osu.UI private readonly JudgementPooler judgementPooler; + // For osu! gameplay, everything is always on screen. + // Skipping masking calculations improves performance in intense beatmaps (ie. https://osu.ppy.sh/beatmapsets/150945#osu/372245) public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; public SmokeContainer Smoke { get; } From e3936930c7df32ccd53f6c8f4ea2dca14dec3934 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Mar 2024 13:11:57 +0800 Subject: [PATCH 763/915] Remove local optimisation in `DrawableHitObject` --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index de05219212..28aa2ccb79 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -15,7 +15,6 @@ using osu.Framework.Extensions.ListExtensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Primitives; using osu.Framework.Lists; using osu.Framework.Threading; using osu.Framework.Utils; @@ -632,8 +631,6 @@ namespace osu.Game.Rulesets.Objects.Drawables #endregion - public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); From d12b11e234f0e9d279e70c71ab595a063ec98e47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Mar 2024 13:14:29 +0800 Subject: [PATCH 764/915] Revert "Remove local optimisation in `DrawableHitObject`" This reverts commit e3936930c7df32ccd53f6c8f4ea2dca14dec3934. --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 28aa2ccb79..de05219212 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -15,6 +15,7 @@ using osu.Framework.Extensions.ListExtensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Primitives; using osu.Framework.Lists; using osu.Framework.Threading; using osu.Framework.Utils; @@ -631,6 +632,8 @@ namespace osu.Game.Rulesets.Objects.Drawables #endregion + public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); From 091425db3091104269531f28218b3b309e50c426 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Mar 2024 14:43:54 +0800 Subject: [PATCH 765/915] Fix nullability hint --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 63030293ac..a55a55f760 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.UI public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); - protected override GameplayCursorContainer CreateCursor() => new OsuCursorContainer(); + protected override GameplayCursorContainer? CreateCursor() => new OsuCursorContainer(); private readonly Container judgementAboveHitObjectLayer; From fc05268fc33fc16f214501f3dffe1ec33a301e29 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Mar 2024 14:45:52 +0800 Subject: [PATCH 766/915] Apply NRT to `DrawableOsuEditorRuleset` too --- osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs index 14e7b93f3a..68c565af4d 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; @@ -25,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Edit private partial class OsuEditorPlayfield : OsuPlayfield { - protected override GameplayCursorContainer CreateCursor() => null; + protected override GameplayCursorContainer? CreateCursor() => null; public OsuEditorPlayfield() { From e0f1f70b820030452c2f32d1d7dfe6417230f9c7 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 11 Mar 2024 15:52:38 +0900 Subject: [PATCH 767/915] Adjust NRT to prevent future issues This way, it will yet at us if the setter is ever moved out of the ctor. --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index a55a55f760..4933eb4041 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -79,11 +80,12 @@ namespace osu.Game.Rulesets.Osu.UI NewResult += onNewResult; } - private IHitPolicy hitPolicy = null!; + private IHitPolicy hitPolicy; public IHitPolicy HitPolicy { get => hitPolicy; + [MemberNotNull(nameof(hitPolicy))] set { hitPolicy = value ?? throw new ArgumentNullException(nameof(value)); From 226df7163e1b34eb4a78f02f0038493b673a8dce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Mar 2024 16:55:49 +0800 Subject: [PATCH 768/915] Update client ID --- osu.Desktop/DiscordRichPresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 2e5db2f5c1..4e3db2db2d 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -25,7 +25,7 @@ namespace osu.Desktop { internal partial class DiscordRichPresence : Component { - private const string client_id = "367827983903490050"; + private const string client_id = "1216669957799018608"; private DiscordRpcClient client = null!; From 169e2e1b4e21c824e586cd1be88b33875e9a2e30 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 11 Mar 2024 09:54:49 +0300 Subject: [PATCH 769/915] Change maximum room number to closest powers of two --- osu.Desktop/DiscordRichPresence.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 4e3db2db2d..886038bcf0 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -142,9 +142,8 @@ namespace osu.Desktop Privacy = string.IsNullOrEmpty(room.Settings.Password) ? Party.PrivacySetting.Public : Party.PrivacySetting.Private, ID = room.RoomID.ToString(), // technically lobbies can have infinite users, but Discord needs this to be set to something. - // 1024 just happens to look nice. - // https://discord.com/channels/188630481301012481/188630652340404224/1212967974793642034 - Max = 1024, + // to make party display sensible, assign a powers of two above participants count (8 at minimum). + Max = (int)Math.Max(8, Math.Pow(2, Math.Ceiling(Math.Log2(room.Users.Count)))), Size = room.Users.Count, }; From 8b730acb082379174f9a48b5fd132b184b4e9a81 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 11 Mar 2024 11:18:59 +0300 Subject: [PATCH 770/915] Update presence on changes to multiplayer room --- osu.Desktop/DiscordRichPresence.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 886038bcf0..8de1a08e7a 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -8,6 +8,7 @@ using DiscordRPC.Message; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game; @@ -91,6 +92,8 @@ namespace osu.Desktop activity.BindValueChanged(_ => updateStatus()); privacyMode.BindValueChanged(_ => updateStatus()); + multiplayerClient.RoomUpdated += updateStatus; + client.Initialize(); } @@ -269,6 +272,9 @@ namespace osu.Desktop protected override void Dispose(bool isDisposing) { + if (multiplayerClient.IsNotNull()) + multiplayerClient.RoomUpdated -= updateStatus; + client.Dispose(); base.Dispose(isDisposing); } From e5e7c8f26841654a6819f3c88c40a347184c086b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 11 Mar 2024 14:58:28 +0100 Subject: [PATCH 771/915] Wrap beatmap listing filter names too While we're here fixing... Addresses https://github.com/ppy/osu/discussions/15452#discussioncomment-2734237. --- osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs index f79695a123..0b54a921f5 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs @@ -6,10 +6,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osuTK; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Localisation; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.BeatmapListing { @@ -45,9 +45,10 @@ namespace osu.Game.Overlays.BeatmapListing { new[] { - new OsuSpriteText + new OsuTextFlowContainer(t => t.Font = OsuFont.GetFont(size: 13)) { - Font = OsuFont.GetFont(size: 13), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Text = header }, filter = CreateFilter() From f30dfcb728b216659bf80ff513f7c0cdb97d56f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 11 Mar 2024 21:34:10 +0100 Subject: [PATCH 772/915] Fix ruleset medals not displaying due to deserialisation failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦🤦 Reported in https://discord.com/channels/188630481301012481/188630652340404224/1216812697589518386. --- .../Notifications/WebSocket/Events/UserAchievementUnlock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Notifications/WebSocket/Events/UserAchievementUnlock.cs b/osu.Game/Online/Notifications/WebSocket/Events/UserAchievementUnlock.cs index 6c7c8af4f4..3f803a4fe5 100644 --- a/osu.Game/Online/Notifications/WebSocket/Events/UserAchievementUnlock.cs +++ b/osu.Game/Online/Notifications/WebSocket/Events/UserAchievementUnlock.cs @@ -14,7 +14,7 @@ namespace osu.Game.Online.Notifications.WebSocket.Events public uint AchievementId { get; set; } [JsonProperty("achievement_mode")] - public ushort? AchievementMode { get; set; } + public string? AchievementMode { get; set; } [JsonProperty("cover_url")] public string CoverUrl { get; set; } = string.Empty; From 5580ce31fa6c37c7c65a703cfe820705928453bd Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 11 Mar 2024 18:15:18 -0400 Subject: [PATCH 773/915] Log Discord RPC updates --- osu.Desktop/DiscordRichPresence.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 8de1a08e7a..6c8bd26d3d 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -114,6 +114,8 @@ namespace osu.Desktop return; } + Logger.Log("Updating Discord RPC", LoggingTarget.Network, LogLevel.Debug); + if (activity.Value != null) { bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; From e4e7dd14f30ee5c2d28ccc967a0a891fbbd076b7 Mon Sep 17 00:00:00 2001 From: jvyden Date: Mon, 11 Mar 2024 18:16:13 -0400 Subject: [PATCH 774/915] Revert "Update presence on changes to multiplayer room" This reverts commit 8b730acb082379174f9a48b5fd132b184b4e9a81. --- osu.Desktop/DiscordRichPresence.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 6c8bd26d3d..ca26cab0fd 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -8,7 +8,6 @@ using DiscordRPC.Message; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game; @@ -92,8 +91,6 @@ namespace osu.Desktop activity.BindValueChanged(_ => updateStatus()); privacyMode.BindValueChanged(_ => updateStatus()); - multiplayerClient.RoomUpdated += updateStatus; - client.Initialize(); } @@ -274,9 +271,6 @@ namespace osu.Desktop protected override void Dispose(bool isDisposing) { - if (multiplayerClient.IsNotNull()) - multiplayerClient.RoomUpdated -= updateStatus; - client.Dispose(); base.Dispose(isDisposing); } From 83052fe1d98174a832e4ed7e9c52b04c5eb7c6c3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Mar 2024 15:41:50 +0800 Subject: [PATCH 775/915] Downgrade realm to work around crashes on latest release See https://github.com/ppy/osu/issues/27577. --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 55bd68dea0..0b70515abf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -35,7 +35,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From 961058f5c8ca538b1a96a82651b30e49b92c90c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 12 Mar 2024 09:05:28 +0100 Subject: [PATCH 776/915] Add failing test case --- .../Archives/skin-with-subfolder-zip-entries.osk | Bin 0 -> 894 bytes osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 10 ++++++++++ 2 files changed, 10 insertions(+) create mode 100644 osu.Game.Tests/Resources/Archives/skin-with-subfolder-zip-entries.osk diff --git a/osu.Game.Tests/Resources/Archives/skin-with-subfolder-zip-entries.osk b/osu.Game.Tests/Resources/Archives/skin-with-subfolder-zip-entries.osk new file mode 100644 index 0000000000000000000000000000000000000000..013bca3801866f95f7139fbed30f96fb2a6b2639 GIT binary patch literal 894 zcmWIWW@Zs#0D)fToCq)jN+aJ8o04|V8AWw2I zfK1XY?5o`hL%~fhOr?=4GDkw_SJ0K%k|1ep1|jmnGM2G-Y{9ME;m|BpsAa zdiX}EdTqz%zyg(Z44p4_Fr3YD|D0*^dB@$=T(75H%;>qrZuxLUl1|$^qZKpCQXYC3 z#yQ^GeEcET*{AILmN4?)b)Ee8k;Bi_RSP&LwpzKFwp97OxN&0g#UpQ@>CDl1clVL& zm59~7Cw(RLCr>>h`BUbIZ}-+&SvgO1Zgt--I_0?Z*!?H>cjm9{y*o)W$#hTc2C>C+ z_D=kJe3g2DHzSih1FjfU0eTMvKmi5@6ekwJnX*M{T1U&$?CAfWZSSn=z9F%;pB5t+Rm`J%J$Gz#u;>J*p6w-*6=rWE-9W ZZGa^l;!I{`18QMl0m2o)Fg*YcR{%bq?(hHr literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 606a5afac2..62e7a80435 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -173,6 +173,16 @@ namespace osu.Game.Tests.Skins.IO assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", 1.0m, osu); }); + [Test] + public Task TestImportWithSubfolder() => runSkinTest(async osu => + { + const string filename = "Archives/skin-with-subfolder-zip-entries.osk"; + var import = await loadSkinIntoOsu(osu, new ImportTask(TestResources.OpenResource(filename), filename)); + + assertCorrectMetadata(import, $"Totally fully features skin [Real Skin with Real Features] [{filename[..^4]}]", "Unknown", 2.7m, osu); + Assert.That(import.PerformRead(r => r.Files.Count), Is.EqualTo(3)); + }); + #endregion #region Cases where imports should be uniquely imported From 83e47b3c4c1c3a59c6ded7249797daa436d46572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 12 Mar 2024 09:06:24 +0100 Subject: [PATCH 777/915] Fix exports containing zero byte files after import from specific ZIP archives Closes https://github.com/ppy/osu/issues/27540. As it turns out, some ZIP archivers (like 7zip) will decide to add fake entries for directories, and some (like windows zipfolders) won't. The "directory" entries aren't really properly supported using any actual data or attributes, they're detected by sharpcompress basically by heuristics: https://github.com/adamhathcock/sharpcompress/blob/ab5535eba365ec8fae58f92d53763ddf2dbf45af/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs#L19-L31 When importing into realm we have thus far presumed that these directory entries will not be a thing. Having them be a thing breaks multiple things, like: - When importing from ZIPs with separate directory entries, a separate `RealmFile` is created for a directory entry even though it doesn't represent a real file - As a result, when re-exporting a model with files imported from such an archive, a zero-byte file would be created because to the database it looks like it was originally a zero-byte file. If you want to have fun, google "zip empty directories". You'll see a whole gamut of languages, libraries, and developers stepping on this rake. Yet another episode of underspecced mistakes from decades ago that were somebody's "good idea" but continue to wreak havoc forevermore because now there are two competing conventions you can't just pick one. --- osu.Game/IO/Archives/ZipArchiveReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index 7d7ce858dd..cc5c65d184 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -46,7 +46,7 @@ namespace osu.Game.IO.Archives archiveStream.Dispose(); } - public override IEnumerable Filenames => archive.Entries.Select(e => e.Key).ExcludeSystemFileNames(); + public override IEnumerable Filenames => archive.Entries.Where(e => !e.IsDirectory).Select(e => e.Key).ExcludeSystemFileNames(); private class MemoryOwnerMemoryStream : Stream { From 88ec0cdbc704e041bd6b77ff24d1a4206d888896 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Mar 2024 17:35:00 +0800 Subject: [PATCH 778/915] Fix seek ending too early in sample playback test --- .../TestSceneGameplaySamplePlayback.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs index 057197e819..ad3fe7cb7e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs @@ -18,6 +18,8 @@ namespace osu.Game.Tests.Visual.Gameplay { protected override bool AllowBackwardsSeeks => true; + private bool seek; + [Test] public void TestAllSamplesStopDuringSeek() { @@ -42,7 +44,7 @@ namespace osu.Game.Tests.Visual.Gameplay if (!samples.Any(s => s.Playing)) return false; - Player.ChildrenOfType().First().Seek(40000); + seek = true; return true; }); @@ -55,10 +57,27 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("sample playback still disabled", () => sampleDisabler.SamplePlaybackDisabled.Value); + AddStep("stop seeking", () => seek = false); + AddUntilStep("seek finished, sample playback enabled", () => !sampleDisabler.SamplePlaybackDisabled.Value); AddUntilStep("any sample is playing", () => Player.ChildrenOfType().Any(s => s.IsPlaying)); } + protected override void Update() + { + base.Update(); + + if (seek) + { + // Frame stable playback is too fast to catch up these days. + // + // We want to keep seeking while asserting various test conditions, so + // continue to seek until we unset the flag. + var gameplayClockContainer = Player.ChildrenOfType().First(); + gameplayClockContainer.Seek(gameplayClockContainer.CurrentTime > 30000 ? 0 : 60000); + } + } + private IEnumerable allSounds => Player.ChildrenOfType(); private IEnumerable allLoopingSounds => allSounds.Where(sound => sound.Looping); From a4a433b92add36153d8f9b06ffa757480ff3b5ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Mar 2024 20:14:50 +0800 Subject: [PATCH 779/915] Remember login by default Kinda what is expected from a user's perspective --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index a71460ded7..f4a4c553d8 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -75,7 +75,7 @@ namespace osu.Game.Configuration #pragma warning restore CS0618 // Type or member is obsolete SetDefault(OsuSetting.AutomaticallyDownloadMissingBeatmaps, false); - SetDefault(OsuSetting.SavePassword, false).ValueChanged += enabled => + SetDefault(OsuSetting.SavePassword, true).ValueChanged += enabled => { if (enabled.NewValue) SetValue(OsuSetting.SaveUsername, true); From e2e99fc5cc392b57276a1c79f3b68c2831c64ac0 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 12 Mar 2024 21:07:21 -0700 Subject: [PATCH 780/915] Rearrange rankings overlay tabs to match web --- osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs | 2 +- osu.Game/Overlays/Rankings/RankingsScope.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index cf132ed4da..0eaa6ce827 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -52,9 +52,9 @@ namespace osu.Game.Overlays.Rankings switch (scope) { case RankingsScope.Performance: - case RankingsScope.Spotlights: case RankingsScope.Score: case RankingsScope.Country: + case RankingsScope.Spotlights: return true; default: diff --git a/osu.Game/Overlays/Rankings/RankingsScope.cs b/osu.Game/Overlays/Rankings/RankingsScope.cs index 356a861764..0740c17e8c 100644 --- a/osu.Game/Overlays/Rankings/RankingsScope.cs +++ b/osu.Game/Overlays/Rankings/RankingsScope.cs @@ -11,15 +11,15 @@ namespace osu.Game.Overlays.Rankings [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypePerformance))] Performance, - [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCharts))] - Spotlights, - [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeScore))] Score, [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCountry))] Country, + [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCharts))] + Spotlights, + [LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeKudosu))] Kudosu, } From 20c760835ab81c4a90c46656f69d8b59b0903fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 13 Mar 2024 13:55:49 +0100 Subject: [PATCH 781/915] Fix audio in video check crashing on unexpected failures --- osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs index f712a7867d..38976dd4b5 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs @@ -1,8 +1,10 @@ // 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.IO; +using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.IO.FileAbstraction; using osu.Game.Rulesets.Edit.Checks.Components; @@ -75,6 +77,11 @@ namespace osu.Game.Rulesets.Edit.Checks { issue = new IssueTemplateFileError(this).Create(filename, "Unsupported format"); } + catch (Exception ex) + { + issue = new IssueTemplateFileError(this).Create(filename, "Internal failure - see logs for more info"); + Logger.Log($"Failed when running {nameof(CheckAudioInVideo)}: {ex}"); + } yield return issue; } From d32f19b546e63e844acaa3c4c3911225cb757ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 13 Mar 2024 15:18:20 +0100 Subject: [PATCH 782/915] Fix first word bold not applying correctly after first language change Closes https://github.com/ppy/osu/issues/27549. I'm not entirely sure why the old solution failed exactly, but also think it's unimportant because I think past me was an idiot and was playing stupid games with the juggling of indices between two callbacks with no ordering guarantees and expecting not to win stupid prizes. I'm not sure this requires any follow-up reconsiderations of that entire text flow API, but if opinions differ, I'll re-examine. --- osu.Game/Overlays/Mods/ModSelectColumn.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectColumn.cs b/osu.Game/Overlays/Mods/ModSelectColumn.cs index b2c5a054e1..61b29ef65b 100644 --- a/osu.Game/Overlays/Mods/ModSelectColumn.cs +++ b/osu.Game/Overlays/Mods/ModSelectColumn.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.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -8,9 +9,11 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; +using System.Linq; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -181,17 +184,15 @@ namespace osu.Game.Overlays.Mods { headerText.Clear(); - int wordIndex = 0; + ITextPart part = headerText.AddText(text); + part.DrawablePartsRecreated += applySemiBoldToFirstWord; + applySemiBoldToFirstWord(part.Drawables); - ITextPart part = headerText.AddText(text, t => + void applySemiBoldToFirstWord(IEnumerable d) { - if (wordIndex == 0) - t.Font = t.Font.With(weight: FontWeight.SemiBold); - wordIndex += 1; - }); - - // Reset the index so that if the parts are refreshed (e.g. through changes in localisation) the correct word is re-emboldened. - part.DrawablePartsRecreated += _ => wordIndex = 0; + if (d.FirstOrDefault() is OsuSpriteText firstWord) + firstWord.Font = firstWord.Font.With(weight: FontWeight.SemiBold); + } } [BackgroundDependencyLoader] From 789a9f4dfa071dacc9157914e93792231d568923 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 14 Mar 2024 11:01:57 +0900 Subject: [PATCH 783/915] Initial redesign following flyte's design --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 125 +++++++++++------- 1 file changed, 79 insertions(+), 46 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index ba49810b2b..e9dd26a06b 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -3,10 +3,12 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Framework.Threading; using osu.Game.Graphics; @@ -21,7 +23,12 @@ namespace osu.Game.Screens.Play /// public partial class DelayedResumeOverlay : ResumeOverlay { - private const double countdown_time = 800; + private const float outer_size = 200; + private const float inner_size = 150; + private const float progress_stroke_width = 7; + private const float progress_size = inner_size + progress_stroke_width / 2f; + + private const double countdown_time = 3000; protected override LocalisableString Message => string.Empty; @@ -31,9 +38,15 @@ namespace osu.Game.Screens.Play private ScheduledDelegate? scheduledResume; private int countdownCount = 3; private double countdownStartTime; + private bool countdownComplete; - private Drawable content = null!; - private SpriteText countdown = null!; + private Drawable outerContent = null!; + private Container innerContent = null!; + + private Container countdownComponents = null!; + private Drawable countdownBackground = null!; + private SpriteText countdownText = null!; + private CircularProgress countdownProgress = null!; public DelayedResumeOverlay() { @@ -44,44 +57,48 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - Add(content = new CircularContainer + Add(outerContent = new Circle { Anchor = Anchor.Centre, Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Masking = true, - BorderColour = colours.Yellow, - BorderThickness = 2, - Children = new Drawable[] + Size = new Vector2(outer_size), + Colour = Color4.Black.Opacity(0.25f) + }); + + Add(innerContent = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Children = new[] { - new Box - { - Size = new Vector2(250, 40), - Colour = Color4.Black, - Alpha = 0.8f - }, - new Container + countdownBackground = new Circle { Anchor = Anchor.Centre, Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, + Size = new Vector2(inner_size), + Colour = Color4.Black.Opacity(0.25f) + }, + countdownComponents = new Container + { + RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new FillFlowContainer + countdownProgress = new CircularProgress { Anchor = Anchor.Centre, Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(5), - Colour = colours.Yellow, - Child = countdown = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - UseFullGlyphHeight = false, - AlwaysPresent = true, - Font = OsuFont.Numeric.With(size: 20, fixedWidth: true) - }, + Size = new Vector2(progress_size), + InnerRadius = progress_stroke_width / progress_size, + RoundedCaps = true + }, + countdownText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + UseFullGlyphHeight = false, + AlwaysPresent = true, + Font = OsuFont.Torus.With(size: 70, weight: FontWeight.Light) } } } @@ -93,14 +110,26 @@ namespace osu.Game.Screens.Play { this.FadeIn(); - content.FadeInFromZero(150, Easing.OutQuint); - content.ScaleTo(new Vector2(1.5f, 1)).Then().ScaleTo(1, 150, Easing.OutElasticQuarter); + // The transition effects. + outerContent.FadeIn().ScaleTo(Vector2.Zero).Then().ScaleTo(Vector2.One, 200, Easing.OutQuint); + innerContent.FadeIn().ScaleTo(Vector2.Zero).Then().ScaleTo(Vector2.One, 400, Easing.OutElasticHalf); + countdownComponents.FadeOut().Then().Delay(50).FadeTo(1, 100); + // Reset states for various components. + countdownBackground.FadeIn(); + countdownText.FadeIn(); + countdownProgress.FadeIn().ScaleTo(1); + + countdownComplete = false; countdownCount = 3; countdownStartTime = Time.Current; scheduledResume?.Cancel(); - scheduledResume = Scheduler.AddDelayed(Resume, countdown_time); + scheduledResume = Scheduler.AddDelayed(() => + { + countdownComplete = true; + Resume(); + }, countdown_time); } protected override void Update() @@ -114,20 +143,14 @@ namespace osu.Game.Screens.Play double amountTimePassed = Math.Min(countdown_time, Time.Current - countdownStartTime) / countdown_time; int newCount = 3 - (int)Math.Floor(amountTimePassed * 3); - if (newCount > 0) - { - countdown.Alpha = 1; - countdown.Text = newCount.ToString(); - } - else - countdown.Alpha = 0; + countdownProgress.Current.Value = amountTimePassed; + countdownText.Text = Math.Max(1, newCount).ToString(); + countdownProgress.InnerRadius = progress_stroke_width / progress_size / countdownProgress.Scale.X; - if (newCount != countdownCount) + if (countdownCount != newCount && newCount > 0) { - if (newCount == 0) - content.ScaleTo(new Vector2(1.5f, 1), 150, Easing.OutQuint); - else - content.ScaleTo(new Vector2(1.05f, 1), 50, Easing.OutQuint).Then().ScaleTo(1, 50, Easing.Out); + countdownText.ScaleTo(0.25f).Then().ScaleTo(1, 200, Easing.OutQuint); + outerContent.Delay(25).Then().ScaleTo(1.05f, 100).Then().ScaleTo(1f, 200, Easing.Out); } countdownCount = newCount; @@ -135,9 +158,19 @@ namespace osu.Game.Screens.Play protected override void PopOut() { - this.Delay(150).FadeOut(); + this.Delay(300).FadeOut(); - content.FadeOut(150, Easing.OutQuint); + outerContent.FadeOut(); + countdownBackground.FadeOut(); + countdownText.FadeOut(); + + if (countdownComplete) + { + countdownProgress.ScaleTo(2f, 300, Easing.OutQuint); + countdownProgress.Delay(200).FadeOut(100, Easing.Out); + } + else + countdownProgress.FadeOut(); scheduledResume?.Cancel(); } From b431bb11764c4c4088eea49f4cd7f5e7611e4aa9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 14 Mar 2024 12:24:12 +0900 Subject: [PATCH 784/915] Resolve post-merge issues --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index e9dd26a06b..196ca24358 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -32,9 +32,6 @@ namespace osu.Game.Screens.Play protected override LocalisableString Message => string.Empty; - [Resolved] - private OsuColour colours { get; set; } = null!; - private ScheduledDelegate? scheduledResume; private int countdownCount = 3; private double countdownStartTime; @@ -143,7 +140,7 @@ namespace osu.Game.Screens.Play double amountTimePassed = Math.Min(countdown_time, Time.Current - countdownStartTime) / countdown_time; int newCount = 3 - (int)Math.Floor(amountTimePassed * 3); - countdownProgress.Current.Value = amountTimePassed; + countdownProgress.Progress = amountTimePassed; countdownText.Text = Math.Max(1, newCount).ToString(); countdownProgress.InnerRadius = progress_stroke_width / progress_size / countdownProgress.Scale.X; From b309aad895b001e042ec85f2c6103457fdd801a1 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 8 Mar 2024 13:13:08 -0800 Subject: [PATCH 785/915] Fix noticeable masking artifact of beatmap cards when already downloaded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Had a similar fix before seeing https://github.com/ppy/osu/pull/20743#discussion_r994955470, but using that diff instead so co-authoring. Co-Authored-By: Bartłomiej Dach --- .../Drawables/Cards/CollapsibleButtonContainer.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs index fe2ee8c7cc..32df1755a7 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs @@ -77,7 +77,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards downloadTracker, background = new Container { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.Y, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Child = new Box @@ -165,9 +165,11 @@ namespace osu.Game.Beatmaps.Drawables.Cards private void updateState() { - float targetWidth = Width - (ShowDetails.Value ? ButtonsExpandedWidth : ButtonsCollapsedWidth); + float buttonAreaWidth = ShowDetails.Value ? ButtonsExpandedWidth : ButtonsCollapsedWidth; + float mainAreaWidth = Width - buttonAreaWidth; - mainArea.ResizeWidthTo(targetWidth, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + mainArea.ResizeWidthTo(mainAreaWidth, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + background.ResizeWidthTo(buttonAreaWidth + BeatmapCard.CORNER_RADIUS, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); background.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); buttons.FadeTo(ShowDetails.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); From b4cee12db96644a8364ed1525aea51f526c1dcb6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 14 Mar 2024 09:21:29 +0300 Subject: [PATCH 786/915] Use defined colours for counter background --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index 196ca24358..c6cfeca142 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -3,7 +3,6 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -13,8 +12,8 @@ using osu.Framework.Localisation; using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Play { @@ -54,12 +53,15 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { + // todo: this shouldn't define its own colour provider, but nothing in Player screen does, so let's do that for now. + var colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + Add(outerContent = new Circle { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(outer_size), - Colour = Color4.Black.Opacity(0.25f) + Colour = colourProvider.Background6, }); Add(innerContent = new Container @@ -74,7 +76,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(inner_size), - Colour = Color4.Black.Opacity(0.25f) + Colour = colourProvider.Background4, }, countdownComponents = new Container { From f8a841e907e9b2deb3ca08c425a0e665a5c07775 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 14 Mar 2024 00:17:22 -0700 Subject: [PATCH 787/915] Add comment explaining why width is limited to the button area Same comment as https://github.com/ppy/osu/blob/a47ccb8edd2392258b6b7e176b222a9ecd511fc0/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs#L91-L92. --- osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs index 32df1755a7..a29724032e 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs @@ -169,6 +169,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards float mainAreaWidth = Width - buttonAreaWidth; mainArea.ResizeWidthTo(mainAreaWidth, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + + // By limiting the width we avoid this box showing up as an outline around the drawables that are on top of it. background.ResizeWidthTo(buttonAreaWidth + BeatmapCard.CORNER_RADIUS, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); background.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); From 42bd558d7c159857ca7356b8485d710802685fc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Mar 2024 22:41:29 +0800 Subject: [PATCH 788/915] Only update text when necessary (reducing unnecessary string allocadtions) --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index c6cfeca142..468e67901d 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Play protected override LocalisableString Message => string.Empty; private ScheduledDelegate? scheduledResume; - private int countdownCount = 3; + private int? countdownCount; private double countdownStartTime; private bool countdownComplete; @@ -120,7 +120,7 @@ namespace osu.Game.Screens.Play countdownProgress.FadeIn().ScaleTo(1); countdownComplete = false; - countdownCount = 3; + countdownCount = null; countdownStartTime = Time.Current; scheduledResume?.Cancel(); @@ -143,11 +143,11 @@ namespace osu.Game.Screens.Play int newCount = 3 - (int)Math.Floor(amountTimePassed * 3); countdownProgress.Progress = amountTimePassed; - countdownText.Text = Math.Max(1, newCount).ToString(); countdownProgress.InnerRadius = progress_stroke_width / progress_size / countdownProgress.Scale.X; if (countdownCount != newCount && newCount > 0) { + countdownText.Text = Math.Max(1, newCount).ToString(); countdownText.ScaleTo(0.25f).Then().ScaleTo(1, 200, Easing.OutQuint); outerContent.Delay(25).Then().ScaleTo(1.05f, 100).Then().ScaleTo(1f, 200, Easing.Out); } From d7769ec3e25cc985fea44e6fb0d02ab668e2dd33 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Mar 2024 22:38:59 +0800 Subject: [PATCH 789/915] Adjust animation --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index 468e67901d..7c34050bbf 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -112,7 +112,7 @@ namespace osu.Game.Screens.Play // The transition effects. outerContent.FadeIn().ScaleTo(Vector2.Zero).Then().ScaleTo(Vector2.One, 200, Easing.OutQuint); innerContent.FadeIn().ScaleTo(Vector2.Zero).Then().ScaleTo(Vector2.One, 400, Easing.OutElasticHalf); - countdownComponents.FadeOut().Then().Delay(50).FadeTo(1, 100); + countdownComponents.FadeOut().Delay(50).FadeTo(1, 100); // Reset states for various components. countdownBackground.FadeIn(); @@ -166,7 +166,7 @@ namespace osu.Game.Screens.Play if (countdownComplete) { countdownProgress.ScaleTo(2f, 300, Easing.OutQuint); - countdownProgress.Delay(200).FadeOut(100, Easing.Out); + countdownProgress.FadeOut(100, Easing.Out); } else countdownProgress.FadeOut(); From 888245b44fa13e46a7fb23b4a801f3fd36d38fee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Mar 2024 22:44:26 +0800 Subject: [PATCH 790/915] Reorder methods --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index 7c34050bbf..4b703ec3cf 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -131,6 +131,25 @@ namespace osu.Game.Screens.Play }, countdown_time); } + protected override void PopOut() + { + this.Delay(300).FadeOut(); + + outerContent.FadeOut(); + countdownBackground.FadeOut(); + countdownText.FadeOut(); + + if (countdownComplete) + { + countdownProgress.ScaleTo(2f, 300, Easing.OutQuint); + countdownProgress.FadeOut(100, Easing.Out); + } + else + countdownProgress.FadeOut(); + + scheduledResume?.Cancel(); + } + protected override void Update() { base.Update(); @@ -154,24 +173,5 @@ namespace osu.Game.Screens.Play countdownCount = newCount; } - - protected override void PopOut() - { - this.Delay(300).FadeOut(); - - outerContent.FadeOut(); - countdownBackground.FadeOut(); - countdownText.FadeOut(); - - if (countdownComplete) - { - countdownProgress.ScaleTo(2f, 300, Easing.OutQuint); - countdownProgress.FadeOut(100, Easing.Out); - } - else - countdownProgress.FadeOut(); - - scheduledResume?.Cancel(); - } } } From 2845303a74986d4310d7fb4a77b56a1bd980a8d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Mar 2024 22:44:57 +0800 Subject: [PATCH 791/915] Fix non-matching scale outwards animation --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index 4b703ec3cf..c3c98510e3 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -142,7 +142,7 @@ namespace osu.Game.Screens.Play if (countdownComplete) { countdownProgress.ScaleTo(2f, 300, Easing.OutQuint); - countdownProgress.FadeOut(100, Easing.Out); + countdownProgress.FadeOut(300, Easing.OutQuint); } else countdownProgress.FadeOut(); From 23975d4dd162b503ccb0e79f0c0d570c5606f901 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Mar 2024 22:49:53 +0800 Subject: [PATCH 792/915] Add flash and reduce overall time for countdown to 2 seconds --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index c3c98510e3..fd1ce5d829 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -22,12 +22,15 @@ namespace osu.Game.Screens.Play /// public partial class DelayedResumeOverlay : ResumeOverlay { + // todo: this shouldn't define its own colour provider, but nothing in Player screen does, so let's do that for now. + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); + private const float outer_size = 200; private const float inner_size = 150; private const float progress_stroke_width = 7; private const float progress_size = inner_size + progress_stroke_width / 2f; - private const double countdown_time = 3000; + private const double countdown_time = 2000; protected override LocalisableString Message => string.Empty; @@ -53,9 +56,6 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - // todo: this shouldn't define its own colour provider, but nothing in Player screen does, so let's do that for now. - var colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); - Add(outerContent = new Circle { Anchor = Anchor.Centre, @@ -169,6 +169,8 @@ namespace osu.Game.Screens.Play countdownText.Text = Math.Max(1, newCount).ToString(); countdownText.ScaleTo(0.25f).Then().ScaleTo(1, 200, Easing.OutQuint); outerContent.Delay(25).Then().ScaleTo(1.05f, 100).Then().ScaleTo(1f, 200, Easing.Out); + + countdownBackground.FlashColour(colourProvider.Background3, 400, Easing.Out); } countdownCount = newCount; From 1aa695add9db68d3aef453f476486209a3aeb5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 09:14:17 +0100 Subject: [PATCH 793/915] Implement alternate design of player loader disclaimers --- .../Screens/Play/PlayerLoaderDisclaimer.cs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs diff --git a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs new file mode 100644 index 0000000000..c8112055c8 --- /dev/null +++ b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs @@ -0,0 +1,67 @@ +// 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.Graphics.Shapes; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Overlays; +using osuTK; + +namespace osu.Game.Screens.Play +{ + public partial class PlayerLoaderDisclaimer : CompositeDrawable + { + private readonly LocalisableString title; + private readonly LocalisableString content; + + public PlayerLoaderDisclaimer(LocalisableString title, LocalisableString content) + { + this.title = title; + this.content = content; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Width = SettingsToolboxGroup.CONTAINER_WIDTH; + AutoSizeAxes = Axes.Y; + + InternalChildren = new Drawable[] + { + new Circle + { + Width = 7, + Height = 15, + Margin = new MarginPadding { Top = 2 }, + Colour = colours.Orange1, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = 12 }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 2), + Children = new[] + { + new TextFlowContainer(t => t.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = title, + }, + new TextFlowContainer(t => t.Font = OsuFont.GetFont(size: 16)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = content, + } + } + } + }; + } + } +} From 42ae18976ff4287567f1b69c27d27215353573a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 09:27:33 +0100 Subject: [PATCH 794/915] Replace existing epilepsy warning with inline display --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 35 +----- osu.Game/Screens/Play/EpilepsyWarning.cs | 102 ------------------ osu.Game/Screens/Play/PlayerLoader.cs | 67 +++++------- 3 files changed, 26 insertions(+), 178 deletions(-) delete mode 100644 osu.Game/Screens/Play/EpilepsyWarning.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index c6827d4197..dac8545729 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -334,13 +334,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddAssert($"epilepsy warning {(warning ? "present" : "absent")}", () => (getWarning() != null) == warning); - - if (warning) - { - AddUntilStep("sound volume decreased", () => Beatmap.Value.Track.AggregateVolume.Value == 0.25); - AddUntilStep("sound volume restored", () => Beatmap.Value.Track.AggregateVolume.Value == 1); - } + AddAssert($"epilepsy warning {(warning ? "present" : "absent")}", () => this.ChildrenOfType().Count(), () => Is.EqualTo(warning ? 1 : 0)); restoreVolumes(); } @@ -357,30 +351,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddUntilStep("epilepsy warning absent", () => getWarning() == null); - - restoreVolumes(); - } - - [Test] - public void TestEpilepsyWarningEarlyExit() - { - saveVolumes(); - setFullVolume(); - - AddStep("enable storyboards", () => config.SetValue(OsuSetting.ShowStoryboard, true)); - AddStep("set epilepsy warning", () => epilepsyWarning = true); - AddStep("load dummy beatmap", () => resetPlayer(false)); - - AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - - AddUntilStep("wait for epilepsy warning", () => getWarning().Alpha > 0); - AddUntilStep("warning is shown", () => getWarning().State.Value == Visibility.Visible); - - AddStep("exit early", () => loader.Exit()); - - AddUntilStep("warning is hidden", () => getWarning().State.Value == Visibility.Hidden); - AddUntilStep("sound volume restored", () => Beatmap.Value.Track.AggregateVolume.Value == 1); + AddUntilStep("epilepsy warning absent", () => this.ChildrenOfType().Single().Alpha, () => Is.Zero); restoreVolumes(); } @@ -479,8 +450,6 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("click notification", () => notification.TriggerClick()); } - private EpilepsyWarning getWarning() => loader.ChildrenOfType().SingleOrDefault(w => w.IsAlive); - private partial class TestPlayerLoader : PlayerLoader { public new VisualSettings VisualSettings => base.VisualSettings; diff --git a/osu.Game/Screens/Play/EpilepsyWarning.cs b/osu.Game/Screens/Play/EpilepsyWarning.cs deleted file mode 100644 index 6316bbdb4e..0000000000 --- a/osu.Game/Screens/Play/EpilepsyWarning.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Screens.Backgrounds; -using osuTK; - -namespace osu.Game.Screens.Play -{ - public partial class EpilepsyWarning : VisibilityContainer - { - public const double FADE_DURATION = 250; - - public EpilepsyWarning() - { - RelativeSizeAxes = Axes.Both; - Alpha = 0f; - } - - private BackgroundScreenBeatmap dimmableBackground; - - public BackgroundScreenBeatmap DimmableBackground - { - get => dimmableBackground; - set - { - dimmableBackground = value; - - if (IsLoaded) - updateBackgroundFade(); - } - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Children = new Drawable[] - { - new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new SpriteIcon - { - Colour = colours.Yellow, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Icon = FontAwesome.Solid.ExclamationTriangle, - Size = new Vector2(50), - }, - new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 25)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - TextAnchor = Anchor.Centre, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }.With(tfc => - { - tfc.AddText("This beatmap contains scenes with "); - tfc.AddText("rapidly flashing colours", s => - { - s.Font = s.Font.With(weight: FontWeight.Bold); - s.Colour = colours.Yellow; - }); - tfc.AddText("."); - - tfc.NewParagraph(); - tfc.AddText("Please take caution if you are affected by epilepsy."); - }), - } - } - }; - } - - protected override void PopIn() - { - updateBackgroundFade(); - - this.FadeIn(FADE_DURATION, Easing.OutQuint); - } - - private void updateBackgroundFade() - { - DimmableBackground?.FadeColour(OsuColour.Gray(0.5f), FADE_DURATION, Easing.OutQuint); - } - - protected override void PopOut() => this.FadeOut(FADE_DURATION); - } -} diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index aa730a8e0f..75240ba2ba 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -71,6 +71,7 @@ namespace osu.Game.Screens.Play protected Task? DisposalTask { get; private set; } + private FillFlowContainer disclaimers = null!; private OsuScrollContainer settingsScroll = null!; private Bindable showStoryboards = null!; @@ -137,7 +138,7 @@ namespace osu.Game.Screens.Play private ScheduledDelegate? scheduledPushPlayer; - private EpilepsyWarning? epilepsyWarning; + private PlayerLoaderDisclaimer? epilepsyWarning; private bool quickRestart; @@ -188,6 +189,16 @@ namespace osu.Game.Screens.Play Origin = Anchor.Centre, }, }), + disclaimers = new FillFlowContainer + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(padding), + Spacing = new Vector2(padding), + }, settingsScroll = new OsuScrollContainer { Anchor = Anchor.TopRight, @@ -216,11 +227,7 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.BeatmapInfo.EpilepsyWarning) { - AddInternal(epilepsyWarning = new EpilepsyWarning - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); + disclaimers.Add(epilepsyWarning = new PlayerLoaderDisclaimer("This beatmap contains scenes with rapidly flashing colours", "Please take caution if you are affected by epilepsy.")); } } @@ -229,6 +236,9 @@ namespace osu.Game.Screens.Play base.LoadComplete(); inputManager = GetContainingInputManager(); + + showStoryboards.BindValueChanged(val => epilepsyWarning?.FadeTo(val.NewValue ? 1 : 0, 250, Easing.OutQuint), true); + epilepsyWarning?.FinishTransforms(true); } #region Screen handling @@ -237,15 +247,10 @@ namespace osu.Game.Screens.Play { base.OnEntering(e); - ApplyToBackground(b => - { - if (epilepsyWarning != null) - epilepsyWarning.DimmableBackground = b; - }); - Beatmap.Value.Track.AddAdjustment(AdjustableProperty.Volume, volumeAdjustment); - // Start off-screen. + // Start side content off-screen. + disclaimers.MoveToX(-disclaimers.DrawWidth); settingsScroll.MoveToX(settingsScroll.DrawWidth); content.ScaleTo(0.7f); @@ -301,9 +306,6 @@ namespace osu.Game.Screens.Play cancelLoad(); ContentOut(); - // If the load sequence was interrupted, the epilepsy warning may already be displayed (or in the process of being displayed). - epilepsyWarning?.Hide(); - // Ensure the screen doesn't expire until all the outwards fade operations have completed. this.Delay(CONTENT_OUT_DURATION).FadeOut(); @@ -433,6 +435,8 @@ namespace osu.Game.Screens.Play content.FadeInFromZero(500, Easing.OutQuint); content.ScaleTo(1, 650, Easing.OutQuint).Then().Schedule(prepareNewPlayer); + disclaimers.FadeInFromZero(500, Easing.Out) + .MoveToX(0, 500, Easing.OutQuint); settingsScroll.FadeInFromZero(500, Easing.Out) .MoveToX(0, 500, Easing.OutQuint); @@ -466,6 +470,8 @@ namespace osu.Game.Screens.Play lowPassFilter = null; }); + disclaimers.FadeOut(CONTENT_OUT_DURATION, Easing.Out) + .MoveToX(-disclaimers.DrawWidth, CONTENT_OUT_DURATION * 2, Easing.OutQuint); settingsScroll.FadeOut(CONTENT_OUT_DURATION, Easing.OutQuint) .MoveToX(settingsScroll.DrawWidth, CONTENT_OUT_DURATION * 2, Easing.OutQuint); @@ -503,33 +509,8 @@ namespace osu.Game.Screens.Play TransformSequence pushSequence = this.Delay(0); - // only show if the warning was created (i.e. the beatmap needs it) - // and this is not a restart of the map (the warning expires after first load). - // - // note the late check of storyboard enable as the user may have just changed it - // from the settings on the loader screen. - if (epilepsyWarning?.IsAlive == true && showStoryboards.Value) - { - const double epilepsy_display_length = 3000; - - pushSequence - .Delay(CONTENT_OUT_DURATION) - .Schedule(() => epilepsyWarning.State.Value = Visibility.Visible) - .TransformBindableTo(volumeAdjustment, 0.25, EpilepsyWarning.FADE_DURATION, Easing.OutQuint) - .Delay(epilepsy_display_length) - .Schedule(() => - { - epilepsyWarning.Hide(); - epilepsyWarning.Expire(); - }) - .Delay(EpilepsyWarning.FADE_DURATION); - } - else - { - // This goes hand-in-hand with the restoration of low pass filter in contentOut(). - this.TransformBindableTo(volumeAdjustment, 0, CONTENT_OUT_DURATION, Easing.OutCubic); - epilepsyWarning?.Expire(); - } + // This goes hand-in-hand with the restoration of low pass filter in contentOut(). + this.TransformBindableTo(volumeAdjustment, 0, CONTENT_OUT_DURATION, Easing.OutCubic); pushSequence.Schedule(() => { From f3a444b7aca2295e92d473e7fe84a23aefd239b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 09:41:37 +0100 Subject: [PATCH 795/915] Add disclaimer for loved/qualified status --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 43 ++++++++++++++++++- osu.Game/Screens/Play/PlayerLoader.cs | 12 ++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index dac8545729..91e35b067b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -16,6 +16,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Framework.Utils; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -37,6 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay private TestPlayer player; private bool epilepsyWarning; + private BeatmapOnlineStatus onlineStatus; [Resolved] private AudioManager audioManager { get; set; } @@ -118,8 +120,9 @@ namespace osu.Game.Tests.Visual.Gameplay // Add intro time to test quick retry skipping (TestQuickRetry). workingBeatmap.BeatmapInfo.AudioLeadIn = 60000; - // Turn on epilepsy warning to test warning display (TestEpilepsyWarning). + // Set up data for testing disclaimer display. workingBeatmap.BeatmapInfo.EpilepsyWarning = epilepsyWarning; + workingBeatmap.BeatmapInfo.Status = onlineStatus; Beatmap.Value = workingBeatmap; @@ -356,6 +359,44 @@ namespace osu.Game.Tests.Visual.Gameplay restoreVolumes(); } + [TestCase(BeatmapOnlineStatus.Loved, 1)] + [TestCase(BeatmapOnlineStatus.Qualified, 1)] + [TestCase(BeatmapOnlineStatus.Graveyard, 0)] + public void TestStatusWarning(BeatmapOnlineStatus status, int expectedDisclaimerCount) + { + saveVolumes(); + setFullVolume(); + + AddStep("enable storyboards", () => config.SetValue(OsuSetting.ShowStoryboard, true)); + AddStep("disable epilepsy warning", () => epilepsyWarning = false); + AddStep("set beatmap status", () => onlineStatus = status); + AddStep("load dummy beatmap", () => resetPlayer(false)); + + AddUntilStep("wait for current", () => loader.IsCurrentScreen()); + + AddAssert($"disclaimer count is {expectedDisclaimerCount}", () => this.ChildrenOfType().Count(), () => Is.EqualTo(expectedDisclaimerCount)); + + restoreVolumes(); + } + + [Test] + public void TestCombinedWarnings() + { + saveVolumes(); + setFullVolume(); + + AddStep("enable storyboards", () => config.SetValue(OsuSetting.ShowStoryboard, true)); + AddStep("disable epilepsy warning", () => epilepsyWarning = true); + AddStep("set beatmap status", () => onlineStatus = BeatmapOnlineStatus.Loved); + AddStep("load dummy beatmap", () => resetPlayer(false)); + + AddUntilStep("wait for current", () => loader.IsCurrentScreen()); + + AddAssert($"disclaimer count is 2", () => this.ChildrenOfType().Count(), () => Is.EqualTo(2)); + + restoreVolumes(); + } + [TestCase(true, 1.0, false)] // on battery, above cutoff --> no warning [TestCase(false, 0.1, false)] // not on battery, below cutoff --> no warning [TestCase(true, 0.25, true)] // on battery, at cutoff --> warning diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 75240ba2ba..2d75b69b4a 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -18,6 +18,7 @@ using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Audio; using osu.Game.Audio.Effects; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -229,6 +230,17 @@ namespace osu.Game.Screens.Play { disclaimers.Add(epilepsyWarning = new PlayerLoaderDisclaimer("This beatmap contains scenes with rapidly flashing colours", "Please take caution if you are affected by epilepsy.")); } + + switch (Beatmap.Value.BeatmapInfo.Status) + { + case BeatmapOnlineStatus.Loved: + disclaimers.Add(new PlayerLoaderDisclaimer("This beatmap is loved", "No performance points will be awarded.\nLeaderboards may be reset by the beatmap creator.")); + break; + + case BeatmapOnlineStatus.Qualified: + disclaimers.Add(new PlayerLoaderDisclaimer("This beatmap is qualified", "No performance points will be awarded.\nLeaderboards will be reset when the beatmap is ranked.")); + break; + } } protected override void LoadComplete() From 4688a53cf435861af05f8253d029f30a4e5db342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 09:43:09 +0100 Subject: [PATCH 796/915] Stay on player loader a bit longer if disclaimers are present Just to make reading the text easier. --- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 2d75b69b4a..29ad6d2a47 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play protected const double CONTENT_OUT_DURATION = 300; - protected virtual double PlayerPushDelay => 1800; + protected virtual double PlayerPushDelay => 1800 + disclaimers.Count * 500; public override bool HideOverlaysOnEnter => hideOverlays; From 4e2098adb86c73f8391255331c08dc5349567e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 09:46:18 +0100 Subject: [PATCH 797/915] Fix test crosstalk --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 91e35b067b..0ec4284a00 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -37,8 +37,8 @@ namespace osu.Game.Tests.Visual.Gameplay private TestPlayerLoader loader; private TestPlayer player; - private bool epilepsyWarning; - private BeatmapOnlineStatus onlineStatus; + private bool? epilepsyWarning; + private BeatmapOnlineStatus? onlineStatus; [Resolved] private AudioManager audioManager { get; set; } @@ -83,7 +83,12 @@ namespace osu.Game.Tests.Visual.Gameplay } [SetUp] - public void Setup() => Schedule(() => player = null); + public void Setup() => Schedule(() => + { + player = null; + epilepsyWarning = null; + onlineStatus = null; + }); [SetUpSteps] public override void SetUpSteps() @@ -121,8 +126,8 @@ namespace osu.Game.Tests.Visual.Gameplay workingBeatmap.BeatmapInfo.AudioLeadIn = 60000; // Set up data for testing disclaimer display. - workingBeatmap.BeatmapInfo.EpilepsyWarning = epilepsyWarning; - workingBeatmap.BeatmapInfo.Status = onlineStatus; + workingBeatmap.BeatmapInfo.EpilepsyWarning = epilepsyWarning ?? false; + workingBeatmap.BeatmapInfo.Status = onlineStatus ?? BeatmapOnlineStatus.Ranked; Beatmap.Value = workingBeatmap; From 49a087f7fcf764fe4764e4dff0c178287f2dc5f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 10:58:00 +0100 Subject: [PATCH 798/915] Add localisation support --- osu.Game/Localisation/PlayerLoaderStrings.cs | 48 ++++++++++++++++++++ osu.Game/Screens/Play/PlayerLoader.cs | 6 +-- 2 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Localisation/PlayerLoaderStrings.cs diff --git a/osu.Game/Localisation/PlayerLoaderStrings.cs b/osu.Game/Localisation/PlayerLoaderStrings.cs new file mode 100644 index 0000000000..eba98c7aa7 --- /dev/null +++ b/osu.Game/Localisation/PlayerLoaderStrings.cs @@ -0,0 +1,48 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class PlayerLoaderStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.PlayerLoader"; + + /// + /// "This beatmap contains scenes with rapidly flashing colours" + /// + public static LocalisableString EpilepsyWarningTitle => new TranslatableString(getKey(@"epilepsy_warning_title"), @"This beatmap contains scenes with rapidly flashing colours"); + + /// + /// "Please take caution if you are affected by epilepsy." + /// + public static LocalisableString EpilepsyWarningContent => new TranslatableString(getKey(@"epilepsy_warning_content"), @"Please take caution if you are affected by epilepsy."); + + /// + /// "This beatmap is loved" + /// + public static LocalisableString LovedBeatmapDisclaimerTitle => new TranslatableString(getKey(@"loved_beatmap_disclaimer_title"), @"This beatmap is loved"); + + /// + /// "No performance points will be awarded. + /// Leaderboards may be reset by the beatmap creator." + /// + public static LocalisableString LovedBeatmapDisclaimerContent => new TranslatableString(getKey(@"loved_beatmap_disclaimer_content"), @"No performance points will be awarded. +Leaderboards may be reset by the beatmap creator."); + + /// + /// "This beatmap is qualified" + /// + public static LocalisableString QualifiedBeatmapDisclaimerTitle => new TranslatableString(getKey(@"qualified_beatmap_disclaimer_title"), @"This beatmap is qualified"); + + /// + /// "No performance points will be awarded. + /// Leaderboards will be reset when the beatmap is ranked." + /// + public static LocalisableString QualifiedBeatmapDisclaimerContent => new TranslatableString(getKey(@"qualified_beatmap_disclaimer_content"), @"No performance points will be awarded. +Leaderboards will be reset when the beatmap is ranked."); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 29ad6d2a47..ad9814e8c9 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -228,17 +228,17 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.BeatmapInfo.EpilepsyWarning) { - disclaimers.Add(epilepsyWarning = new PlayerLoaderDisclaimer("This beatmap contains scenes with rapidly flashing colours", "Please take caution if you are affected by epilepsy.")); + disclaimers.Add(epilepsyWarning = new PlayerLoaderDisclaimer(PlayerLoaderStrings.EpilepsyWarningTitle, PlayerLoaderStrings.EpilepsyWarningContent)); } switch (Beatmap.Value.BeatmapInfo.Status) { case BeatmapOnlineStatus.Loved: - disclaimers.Add(new PlayerLoaderDisclaimer("This beatmap is loved", "No performance points will be awarded.\nLeaderboards may be reset by the beatmap creator.")); + disclaimers.Add(new PlayerLoaderDisclaimer(PlayerLoaderStrings.LovedBeatmapDisclaimerTitle, PlayerLoaderStrings.LovedBeatmapDisclaimerContent)); break; case BeatmapOnlineStatus.Qualified: - disclaimers.Add(new PlayerLoaderDisclaimer("This beatmap is qualified", "No performance points will be awarded.\nLeaderboards will be reset when the beatmap is ranked.")); + disclaimers.Add(new PlayerLoaderDisclaimer(PlayerLoaderStrings.QualifiedBeatmapDisclaimerTitle, PlayerLoaderStrings.QualifiedBeatmapDisclaimerContent)); break; } } From 5513a727488fb1825a2ca60514ab478b92623b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 10:33:32 +0100 Subject: [PATCH 799/915] Improve hiding transition when multiple disclaimers are visible --- osu.Game/Screens/Play/PlayerLoader.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index ad9814e8c9..0cc8ed0f4b 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -194,8 +194,10 @@ namespace osu.Game.Screens.Play { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, + Width = SettingsToolboxGroup.CONTAINER_WIDTH + padding * 2, + AutoSizeAxes = Axes.Y, + AutoSizeDuration = 250, + AutoSizeEasing = Easing.OutQuint, Direction = FillDirection.Vertical, Padding = new MarginPadding(padding), Spacing = new Vector2(padding), From 87682008fd0de936edb734c69d49cb0e7e4c4b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 11:26:48 +0100 Subject: [PATCH 800/915] Fix code quality inspection --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 0ec4284a00..4b00a86950 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -397,7 +397,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddAssert($"disclaimer count is 2", () => this.ChildrenOfType().Count(), () => Is.EqualTo(2)); + AddAssert("disclaimer count is 2", () => this.ChildrenOfType().Count(), () => Is.EqualTo(2)); restoreVolumes(); } From 51568ba06a0465b3e3c3de13f4d9ce885c6e82ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 11:31:45 +0100 Subject: [PATCH 801/915] Add background to disclaimers --- .../Screens/Play/PlayerLoaderDisclaimer.cs | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs index c8112055c8..b41a2d3112 100644 --- a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs +++ b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs @@ -24,40 +24,56 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, OverlayColourProvider colourProvider) { - Width = SettingsToolboxGroup.CONTAINER_WIDTH; + RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + Masking = true; + CornerRadius = 5; InternalChildren = new Drawable[] { - new Circle + new Box { - Width = 7, - Height = 15, - Margin = new MarginPadding { Top = 2 }, - Colour = colours.Orange1, + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background4, }, - new FillFlowContainer + new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 12 }, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 2), - Children = new[] + Padding = new MarginPadding(10), + Children = new Drawable[] { - new TextFlowContainer(t => t.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17)) + new Circle { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Text = title, + Width = 7, + Height = 15, + Margin = new MarginPadding { Top = 2 }, + Colour = colours.Orange1, }, - new TextFlowContainer(t => t.Font = OsuFont.GetFont(size: 16)) + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Text = content, + Padding = new MarginPadding { Left = 12 }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 2), + Children = new[] + { + new TextFlowContainer(t => t.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = title, + }, + new TextFlowContainer(t => t.Font = OsuFont.GetFont(size: 16)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = content, + } + } } } } From e6883b841802c5a8689ca80b13ca277022901b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 11:38:51 +0100 Subject: [PATCH 802/915] Tweak visuals further --- osu.Game/Screens/Play/PlayerLoader.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 0cc8ed0f4b..196180f3dd 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -200,7 +200,7 @@ namespace osu.Game.Screens.Play AutoSizeEasing = Easing.OutQuint, Direction = FillDirection.Vertical, Padding = new MarginPadding(padding), - Spacing = new Vector2(padding), + Spacing = new Vector2(20), }, settingsScroll = new OsuScrollContainer { @@ -269,9 +269,12 @@ namespace osu.Game.Screens.Play content.ScaleTo(0.7f); - contentIn(); + const double metadata_delay = 750; - MetadataInfo.Delay(750).FadeIn(500, Easing.OutQuint); + contentIn(); + MetadataInfo.Delay(metadata_delay).FadeIn(500, Easing.OutQuint); + disclaimers.Delay(metadata_delay).FadeInFromZero(500, Easing.Out) + .MoveToX(0, 500, Easing.OutQuint); // after an initial delay, start the debounced load check. // this will continue to execute even after resuming back on restart. @@ -449,8 +452,6 @@ namespace osu.Game.Screens.Play content.FadeInFromZero(500, Easing.OutQuint); content.ScaleTo(1, 650, Easing.OutQuint).Then().Schedule(prepareNewPlayer); - disclaimers.FadeInFromZero(500, Easing.Out) - .MoveToX(0, 500, Easing.OutQuint); settingsScroll.FadeInFromZero(500, Easing.Out) .MoveToX(0, 500, Easing.OutQuint); From a78210c88f6d3d519c4aa884033b3a30e8e82657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Mar 2024 11:45:27 +0100 Subject: [PATCH 803/915] Handle hover so that users can hover disclaimer to block load & read it --- osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs index b41a2d3112..9dd5a3832c 100644 --- a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs +++ b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Overlays; @@ -79,5 +80,8 @@ namespace osu.Game.Screens.Play } }; } + + // handle hover so that users can hover the disclaimer to delay load if they want to read it. + protected override bool OnHover(HoverEvent e) => true; } } From 0f8d526453b1ada099a52fa7d69340b9cb04963f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 16 Mar 2024 10:09:49 +0800 Subject: [PATCH 804/915] Adjust timings and delay disclaimers the same as settings --- osu.Game/Screens/Play/PlayerLoader.cs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 196180f3dd..75c97d594d 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -269,12 +269,10 @@ namespace osu.Game.Screens.Play content.ScaleTo(0.7f); - const double metadata_delay = 750; + const double metadata_delay = 500; - contentIn(); MetadataInfo.Delay(metadata_delay).FadeIn(500, Easing.OutQuint); - disclaimers.Delay(metadata_delay).FadeInFromZero(500, Easing.Out) - .MoveToX(0, 500, Easing.OutQuint); + contentIn(metadata_delay + 250); // after an initial delay, start the debounced load check. // this will continue to execute even after resuming back on restart. @@ -352,7 +350,7 @@ namespace osu.Game.Screens.Play { if (this.IsCurrentScreen()) content.StartTracking(logo, resuming ? 0 : 500, Easing.InOutExpo); - }, resuming ? 0 : 500); + }, resuming ? 0 : 250); } protected override void LogoExiting(OsuLogo logo) @@ -445,15 +443,21 @@ namespace osu.Game.Screens.Play this.MakeCurrent(); } - private void contentIn() + private void contentIn(double delayBeforeSideDisplays = 0) { MetadataInfo.Loading = true; content.FadeInFromZero(500, Easing.OutQuint); content.ScaleTo(1, 650, Easing.OutQuint).Then().Schedule(prepareNewPlayer); - settingsScroll.FadeInFromZero(500, Easing.Out) - .MoveToX(0, 500, Easing.OutQuint); + using (BeginDelayedSequence(delayBeforeSideDisplays)) + { + settingsScroll.FadeInFromZero(500, Easing.Out) + .MoveToX(0, 500, Easing.OutQuint); + + disclaimers.FadeInFromZero(500, Easing.Out) + .MoveToX(0, 500, Easing.OutQuint); + } AddRangeInternal(new[] { From a49c4ebea634cff84243192ef59e1fa273f5042f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 16 Mar 2024 10:23:21 +0800 Subject: [PATCH 805/915] Match settings panels' backgrounds visually and behaviourally --- .../Screens/Play/PlayerLoaderDisclaimer.cs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs index 9dd5a3832c..3637a4b210 100644 --- a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs +++ b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs @@ -18,6 +18,8 @@ namespace osu.Game.Screens.Play private readonly LocalisableString title; private readonly LocalisableString content; + private Box background = null!; + public PlayerLoaderDisclaimer(LocalisableString title, LocalisableString content) { this.title = title; @@ -34,10 +36,11 @@ namespace osu.Game.Screens.Play InternalChildren = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background4, + Alpha = 0.1f, }, new Container { @@ -81,7 +84,24 @@ namespace osu.Game.Screens.Play }; } - // handle hover so that users can hover the disclaimer to delay load if they want to read it. - protected override bool OnHover(HoverEvent e) => true; + protected override bool OnHover(HoverEvent e) + { + updateFadeState(); + + // handle hover so that users can hover the disclaimer to delay load if they want to read it. + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateFadeState(); + base.OnHoverLost(e); + } + + private void updateFadeState() + { + // Matches SettingsToolboxGroup + background.FadeTo(IsHovered ? 1 : 0.1f, (float)500, Easing.OutQuint); + } } } From bde3da2746c4f80e33dd9a632a8a9d95e7bef186 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 16 Mar 2024 11:11:42 +0800 Subject: [PATCH 806/915] Fix failing test --- .../Visual/Background/TestSceneUserDimBackgrounds.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index 204dea39b2..7d517b3155 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions; +using osu.Framework.Extensions.PolygonExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; @@ -90,12 +91,13 @@ namespace osu.Game.Tests.Visual.Background AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer { BlockLoad = true }))); AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false); AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent()); - AddStep("Trigger background preview", () => + + AddUntilStep("Screen is dimmed and blur applied", () => { - InputManager.MoveMouseTo(playerLoader.ScreenPos); InputManager.MoveMouseTo(playerLoader.VisualSettingsPos); + return songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied(); }); - AddUntilStep("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); + AddStep("Stop background preview", () => InputManager.MoveMouseTo(playerLoader.ScreenPos)); AddUntilStep("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && songSelect.CheckBackgroundBlur(playerLoader.ExpectedBackgroundBlur)); } From a598ea5b97fd467395e901f8dbe08de4b620120b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 16 Mar 2024 12:14:32 +0800 Subject: [PATCH 807/915] Remove unused using statement --- osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index 7d517b3155..c5540eae88 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -9,7 +9,6 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.Extensions.PolygonExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; From c0ae94dc60d6ac9df97784760cee4b5e6baa046b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 16 Mar 2024 12:15:12 +0800 Subject: [PATCH 808/915] Attempt to fix test better --- .../Visual/Background/TestSceneUserDimBackgrounds.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index c5540eae88..aac7689b1b 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -89,7 +89,11 @@ namespace osu.Game.Tests.Visual.Background setupUserSettings(); AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer { BlockLoad = true }))); AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false); - AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent()); + AddAssert("Background retained from song select", () => + { + InputManager.MoveMouseTo(playerLoader); + return songSelect.IsBackgroundCurrent(); + }); AddUntilStep("Screen is dimmed and blur applied", () => { From 15c0b1a2ec786dbdac2263655229430764f2a1d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 16 Mar 2024 13:18:42 +0800 Subject: [PATCH 809/915] Remove redundant cast --- osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs index 3637a4b210..592af166ba 100644 --- a/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs +++ b/osu.Game/Screens/Play/PlayerLoaderDisclaimer.cs @@ -101,7 +101,7 @@ namespace osu.Game.Screens.Play private void updateFadeState() { // Matches SettingsToolboxGroup - background.FadeTo(IsHovered ? 1 : 0.1f, (float)500, Easing.OutQuint); + background.FadeTo(IsHovered ? 1 : 0.1f, 500, Easing.OutQuint); } } } From ea3a9314f9dd3bb19fcc0aff6c1b212cf96cc560 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Mar 2024 23:08:00 +0300 Subject: [PATCH 810/915] Improve TimelineControlPointDisplay performance --- .../Timeline/TimelineControlPointDisplay.cs | 104 +++++++++++++----- .../Components/Timeline/TopPointPiece.cs | 6 +- 2 files changed, 78 insertions(+), 32 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index cd97b293ba..60d113ef58 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -1,10 +1,9 @@ // 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.Specialized; -using System.Diagnostics; -using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Caching; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; @@ -15,6 +14,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline /// public partial class TimelineControlPointDisplay : TimelinePart { + [Resolved] + private Timeline? timeline { get; set; } + + /// + /// The visible time/position range of the timeline. + /// + private (float min, float max) visibleRange = (float.MinValue, float.MaxValue); + + private readonly Cached groupCache = new Cached(); + private readonly IBindableList controlPointGroups = new BindableList(); protected override void LoadBeatmap(EditorBeatmap beatmap) @@ -23,34 +32,71 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline controlPointGroups.UnbindAll(); controlPointGroups.BindTo(beatmap.ControlPointInfo.Groups); - controlPointGroups.BindCollectionChanged((_, args) => + controlPointGroups.BindCollectionChanged((_, _) => { - switch (args.Action) - { - case NotifyCollectionChangedAction.Reset: - Clear(); - break; - - case NotifyCollectionChangedAction.Add: - Debug.Assert(args.NewItems != null); - - foreach (var group in args.NewItems.OfType()) - Add(new TimelineControlPointGroup(group)); - break; - - case NotifyCollectionChangedAction.Remove: - Debug.Assert(args.OldItems != null); - - foreach (var group in args.OldItems.OfType()) - { - var matching = Children.SingleOrDefault(gv => ReferenceEquals(gv.Group, group)); - - matching?.Expire(); - } - - break; - } + invalidateGroups(); }, true); } + + protected override void Update() + { + base.Update(); + + if (timeline == null || DrawWidth <= 0) return; + + (float, float) newRange = ( + (ToLocalSpace(timeline.ScreenSpaceDrawQuad.TopLeft).X - TopPointPiece.WIDTH) / DrawWidth * Content.RelativeChildSize.X, + (ToLocalSpace(timeline.ScreenSpaceDrawQuad.TopRight).X) / DrawWidth * Content.RelativeChildSize.X); + + if (visibleRange != newRange) + { + visibleRange = newRange; + invalidateGroups(); + } + + if (!groupCache.IsValid) + recreateDrawableGroups(); + } + + private void invalidateGroups() => groupCache.Invalidate(); + + private void recreateDrawableGroups() + { + // Remove groups outside the visible range + for (int i = Count - 1; i >= 0; i--) + { + var g = Children[i]; + + if (!shouldBeVisible(g.Group)) + g.Expire(); + } + + // Add remaining ones + foreach (var group in controlPointGroups) + { + if (!shouldBeVisible(group)) + continue; + + bool alreadyVisible = false; + + foreach (var g in this) + { + if (ReferenceEquals(g.Group, group)) + { + alreadyVisible = true; + break; + } + } + + if (alreadyVisible) + continue; + + Add(new TimelineControlPointGroup(group)); + } + + groupCache.Validate(); + } + + private bool shouldBeVisible(ControlPointGroup group) => group.Time >= visibleRange.min && group.Time <= visibleRange.max; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs index 243cdc6ddd..a40a805361 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs @@ -19,12 +19,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline protected OsuSpriteText Label { get; private set; } = null!; - private const float width = 80; + public const float WIDTH = 80; public TopPointPiece(ControlPoint point) { Point = point; - Width = width; + Width = WIDTH; Height = 16; Margin = new MarginPadding { Vertical = 4 }; @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline new Container { RelativeSizeAxes = Axes.Y, - Width = width - triangle_portion, + Width = WIDTH - triangle_portion, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Colour = Point.GetRepresentingColour(colours), From e825db61eeebc0e1f94b2f62b6dba30c478dd58a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 16 Mar 2024 12:26:56 +0300 Subject: [PATCH 811/915] Fix enumerator allocation --- .../Components/Timeline/TimelineControlPointDisplay.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index 60d113ef58..950b717ffb 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -72,8 +72,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } // Add remaining ones - foreach (var group in controlPointGroups) + for (int i = 0; i < controlPointGroups.Count; i++) { + var group = controlPointGroups[i]; + if (!shouldBeVisible(group)) continue; From 981ee54cdca16653753c85a71192f404cb80e85c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 16 Mar 2024 15:05:52 +0300 Subject: [PATCH 812/915] Fix transforms overhead in TimelineTickDisplay --- .../Edit/Compose/Components/Timeline/TimelineTickDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 7e7bef8cf2..5348d03a38 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -165,7 +165,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline // save a few drawables beyond the currently used for edge cases. while (drawableIndex < Math.Min(usedDrawables + 16, Count)) - Children[drawableIndex++].Hide(); + Children[drawableIndex++].Alpha = 0; // expire any excess while (drawableIndex < Count) @@ -182,7 +182,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline point = Children[drawableIndex]; drawableIndex++; - point.Show(); + point.Alpha = 1; return point; } From 34a5e2d606070ba043afc501030933bd4f158412 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 16 Mar 2024 15:20:37 +0300 Subject: [PATCH 813/915] Don't update subtree masking in TimelineTickDisplay --- .../Edit/Compose/Components/Timeline/TimelineTickDisplay.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 5348d03a38..c3adb43032 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Graphics; +using osu.Framework.Graphics.Primitives; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -18,6 +19,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public partial class TimelineTickDisplay : TimelinePart { + // With current implementation every tick in the sub-tree should be visible, no need to check whether they are masked away. + public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds) => false; + [Resolved] private EditorBeatmap beatmap { get; set; } = null!; From 0a6960296ec1947594b06623cfd925433e09d380 Mon Sep 17 00:00:00 2001 From: Vlad Frangu Date: Sat, 16 Mar 2024 21:32:55 +0200 Subject: [PATCH 814/915] feat: Support filtering for multiple statuses --- .../Filtering/FilterQueryParserTest.cs | 22 ++++++++++---- osu.Game/Screens/Select/FilterCriteria.cs | 17 ++++++++++- osu.Game/Screens/Select/FilterQueryParser.cs | 29 ++++++++++++++++++- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index bf888348ee..c109e5bad2 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -256,8 +256,9 @@ namespace osu.Game.Tests.NonVisual.Filtering const string query = "status=r"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); - Assert.AreEqual(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Min); - Assert.AreEqual(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Max); + Assert.IsNotNull(filterCriteria.OnlineStatus.Values); + Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values!); + Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); } [Test] @@ -268,10 +269,19 @@ namespace osu.Game.Tests.NonVisual.Filtering FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual("I want the pp", filterCriteria.SearchText.Trim()); Assert.AreEqual(4, filterCriteria.SearchTerms.Length); - Assert.AreEqual(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Min); - Assert.IsTrue(filterCriteria.OnlineStatus.IsLowerInclusive); - Assert.AreEqual(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Max); - Assert.IsTrue(filterCriteria.OnlineStatus.IsUpperInclusive); + Assert.IsNotNull(filterCriteria.OnlineStatus.Values); + Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); + } + + [Test] + public void TestApplyStatusMatches() + { + const string query = "status=ranked status=loved"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.IsNotNull(filterCriteria.OnlineStatus.Values); + Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); + Assert.Contains(BeatmapOnlineStatus.Loved, filterCriteria.OnlineStatus.Values); } [TestCase("creator")] diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 46083f7c88..dd6b602ade 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Select public OptionalRange Length; public OptionalRange BPM; public OptionalRange BeatDivisor; - public OptionalRange OnlineStatus; + public OptionalArray OnlineStatus; public OptionalRange LastPlayed; public OptionalTextFilter Creator; public OptionalTextFilter Artist; @@ -114,6 +114,21 @@ namespace osu.Game.Screens.Select public IRulesetFilterCriteria? RulesetCriteria { get; set; } + public struct OptionalArray : IEquatable> + where T : struct + { + public bool HasFilter => Values?.Length > 0; + + public bool IsInRange(T value) + { + return Values?.Contains(value) ?? false; + } + + public T[]? Values; + + public bool Equals(OptionalArray other) => Values?.SequenceEqual(other.Values ?? Array.Empty()) ?? false; + } + public struct OptionalRange : IEquatable> where T : struct { diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 2c4077dacf..208e7f559e 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Select return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt); case "status": - return TryUpdateCriteriaRange(ref criteria.OnlineStatus, op, value, tryParseEnum); + return TryUpdateArrayRange(ref criteria.OnlineStatus, op, value, tryParseEnum); case "creator": case "author": @@ -300,6 +300,33 @@ namespace osu.Game.Screens.Select where T : struct => parseFunction.Invoke(val, out var converted) && tryUpdateCriteriaRange(ref range, op, converted); + /// + /// Attempts to parse a keyword filter of type , + /// from the specified and . + /// If can be parsed into using , the function returns true + /// and the resulting range constraint is stored into the 's expected values. + /// + /// The to store the parsed data into, if successful. + /// The operator for the keyword filter. Currently, only can be used. + /// The value of the keyword filter. + /// Function used to determine if can be converted to type . + public static bool TryUpdateArrayRange(ref FilterCriteria.OptionalArray range, Operator op, string val, TryParseFunction parseFunction) + where T : struct + => parseFunction.Invoke(val, out var converted) && tryUpdateArrayRange(ref range, op, converted); + + private static bool tryUpdateArrayRange(ref FilterCriteria.OptionalArray range, Operator op, T value) + where T : struct + { + if (op != Operator.Equal) + return false; + + range.Values ??= Array.Empty(); + + range.Values = range.Values.Append(value).ToArray(); + + return true; + } + private static bool tryUpdateCriteriaRange(ref FilterCriteria.OptionalRange range, Operator op, T value) where T : struct { From e1c1609271bee3b21c38383596f20f31c2a3573e Mon Sep 17 00:00:00 2001 From: Vlad Frangu Date: Sat, 16 Mar 2024 21:48:44 +0200 Subject: [PATCH 815/915] chore: correct equal logic --- osu.Game/Screens/Select/FilterCriteria.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index dd6b602ade..6cec7a387d 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -126,7 +126,13 @@ namespace osu.Game.Screens.Select public T[]? Values; - public bool Equals(OptionalArray other) => Values?.SequenceEqual(other.Values ?? Array.Empty()) ?? false; + public bool Equals(OptionalArray other) + { + if (Values is null && other.Values is null) + return true; + + return Values?.SequenceEqual(other.Values ?? Array.Empty()) ?? false; + } } public struct OptionalRange : IEquatable> From 63816adbc081065fe68b9bc20b49b9329c4abbd2 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Sat, 16 Mar 2024 21:20:12 -0300 Subject: [PATCH 816/915] Add verify checks to unused audio at the end --- .../Checks/CheckUnusedAudioAtEndTest.cs | 90 +++++++++++++++++++ .../CheckUnusedAudioAtEndStrings.cs | 19 ++++ osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 2 + .../Edit/Checks/CheckUnusedAudioAtEnd.cs | 50 +++++++++++ 4 files changed, 161 insertions(+) create mode 100644 osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs create mode 100644 osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs diff --git a/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs new file mode 100644 index 0000000000..687feae63d --- /dev/null +++ b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs @@ -0,0 +1,90 @@ +// 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 Moq; +using NUnit.Framework; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; + +namespace osu.Game.Tests.Editing.Checks +{ + public class CheckUnusedAudioTest + { + private CheckUnusedAudioAtEnd check = null!; + + private IBeatmap beatmapNotFullyMapped = null!; + + private IBeatmap beatmapFullyMapped = null!; + + [SetUp] + public void Setup() + { + check = new CheckUnusedAudioAtEnd(); + beatmapNotFullyMapped = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 1_298 }, + }, + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata { AudioFile = "abc123.jpg" } + } + }; + beatmapFullyMapped = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 9000 }, + }, + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata { AudioFile = "abc123.jpg" } + } + }; + } + + [Test] + public void TestAudioNotFullyUsed() + { + var context = getContext(beatmapNotFullyMapped); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckUnusedAudioAtEnd.IssueTemplateUnusedAudioAtEnd); + } + + [Test] + public void TestAudioFullyUsed() + { + var context = getContext(beatmapFullyMapped); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + private BeatmapVerifierContext getContext(IBeatmap beatmap) + { + return new BeatmapVerifierContext(beatmap, getMockWorkingBeatmap(beatmap).Object); + } + + private Mock getMockWorkingBeatmap(IBeatmap beatmap) + { + var mockTrack = new TrackVirtualStore(new FramedClock()).GetVirtual(10000, "virtual"); + + var mockWorkingBeatmap = new Mock(); + mockWorkingBeatmap.SetupGet(w => w.Beatmap).Returns(beatmap); + mockWorkingBeatmap.SetupGet(w => w.Track).Returns(mockTrack); + + return mockWorkingBeatmap; + } + } +} diff --git a/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs b/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs new file mode 100644 index 0000000000..46f92237a9 --- /dev/null +++ b/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs @@ -0,0 +1,19 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class CheckUnusedAudioAtEndStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.CheckUnusedAudioAtEnd"; + + /// + /// "{0}% of the audio is not mapped." + /// + public static LocalisableString OfTheAudioIsNot(double percentageLeft) => new TranslatableString(getKey(@"of_the_audio_is_not"), @"{0}% of the audio is not mapped.", percentageLeft); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index dcf5eb4da9..4bba72d828 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -36,12 +36,14 @@ namespace osu.Game.Rulesets.Edit new CheckConcurrentObjects(), new CheckZeroLengthObjects(), new CheckDrainLength(), + new CheckUnusedAudioAtEnd(), // Timing new CheckPreviewTime(), // Events new CheckBreaks() + }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs new file mode 100644 index 0000000000..c120e0993a --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs @@ -0,0 +1,50 @@ +// 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 osu.Game.Rulesets.Edit.Checks.Components; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckUnusedAudioAtEnd : ICheck + { + public CheckMetadata Metadata => new CheckMetadata(CheckCategory.Compose, "More than 20% unused audio at the end"); + + public IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateUnusedAudioAtEnd(this), + }; + + public IEnumerable Run(BeatmapVerifierContext context) + { + double mappedLength = context.Beatmap.HitObjects.Last().GetEndTime(); + double trackLength = context.WorkingBeatmap.Track.Length; + + double mappedPercentage = calculatePercentage(mappedLength, trackLength); + + if (mappedPercentage < 80) + { + yield return new IssueTemplateUnusedAudioAtEnd(this).Create(); + } + + } + + private double calculatePercentage(double mappedLenght, double trackLenght) + { + return Math.Round(mappedLenght / trackLenght * 100); + } + + public class IssueTemplateUnusedAudioAtEnd : IssueTemplate + { + public IssueTemplateUnusedAudioAtEnd(ICheck check) + : base(check, IssueType.Problem, "There is more than 20% unused audio at the end.") + { + } + + public Issue Create() => new Issue(this); + } + } +} From f7aff76592c108ff3df1b97b3d2b8e8d7ded6938 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Sat, 16 Mar 2024 23:03:06 -0300 Subject: [PATCH 817/915] Fix codefactor issues --- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 1 - osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 4bba72d828..4a316afd22 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -43,7 +43,6 @@ namespace osu.Game.Rulesets.Edit // Events new CheckBreaks() - }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs index c120e0993a..9c1f2748e9 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs @@ -29,7 +29,6 @@ namespace osu.Game.Rulesets.Edit.Checks { yield return new IssueTemplateUnusedAudioAtEnd(this).Create(); } - } private double calculatePercentage(double mappedLenght, double trackLenght) From 80f24a07916e9ae03fa4631e7f9018812139214d Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Sat, 16 Mar 2024 23:30:59 -0300 Subject: [PATCH 818/915] Fix test class name not matching file name --- osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs index 687feae63d..29c5cb96fd 100644 --- a/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs @@ -14,7 +14,7 @@ using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; namespace osu.Game.Tests.Editing.Checks { - public class CheckUnusedAudioTest + public class CheckUnusedAudioAtEndTest { private CheckUnusedAudioAtEnd check = null!; From d0678bfbee7952e2b82c6d25bd2abc5952937421 Mon Sep 17 00:00:00 2001 From: Vlad Frangu Date: Mon, 18 Mar 2024 15:30:43 +0200 Subject: [PATCH 819/915] chore: requested changes --- .../Filtering/FilterQueryParserTest.cs | 20 ++++++-- osu.Game/Screens/Select/FilterCriteria.cs | 19 +++---- osu.Game/Screens/Select/FilterQueryParser.cs | 50 +++++++++++++++---- 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index c109e5bad2..98d3286409 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -256,8 +256,7 @@ namespace osu.Game.Tests.NonVisual.Filtering const string query = "status=r"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); - Assert.IsNotNull(filterCriteria.OnlineStatus.Values); - Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values!); + Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); } @@ -269,7 +268,7 @@ namespace osu.Game.Tests.NonVisual.Filtering FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.AreEqual("I want the pp", filterCriteria.SearchText.Trim()); Assert.AreEqual(4, filterCriteria.SearchTerms.Length); - Assert.IsNotNull(filterCriteria.OnlineStatus.Values); + Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); } @@ -279,11 +278,24 @@ namespace osu.Game.Tests.NonVisual.Filtering const string query = "status=ranked status=loved"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); - Assert.IsNotNull(filterCriteria.OnlineStatus.Values); + Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); Assert.Contains(BeatmapOnlineStatus.Loved, filterCriteria.OnlineStatus.Values); } + [Test] + public void TestApplyRangeStatusMatches() + { + const string query = "status>=r"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); + Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); + Assert.Contains(BeatmapOnlineStatus.Approved, filterCriteria.OnlineStatus.Values); + Assert.Contains(BeatmapOnlineStatus.Qualified, filterCriteria.OnlineStatus.Values); + Assert.Contains(BeatmapOnlineStatus.Loved, filterCriteria.OnlineStatus.Values); + } + [TestCase("creator")] [TestCase("author")] [TestCase("mapper")] diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 6cec7a387d..1d155574cf 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Select public OptionalRange Length; public OptionalRange BPM; public OptionalRange BeatDivisor; - public OptionalArray OnlineStatus; + public OptionalSet OnlineStatus = new OptionalSet(); public OptionalRange LastPlayed; public OptionalTextFilter Creator; public OptionalTextFilter Artist; @@ -114,24 +114,25 @@ namespace osu.Game.Screens.Select public IRulesetFilterCriteria? RulesetCriteria { get; set; } - public struct OptionalArray : IEquatable> + public struct OptionalSet : IEquatable> where T : struct { - public bool HasFilter => Values?.Length > 0; + public bool HasFilter => Values.Count > 0; public bool IsInRange(T value) { - return Values?.Contains(value) ?? false; + return Values.Contains(value); } - public T[]? Values; + public SortedSet Values = new SortedSet(); - public bool Equals(OptionalArray other) + public OptionalSet() { - if (Values is null && other.Values is null) - return true; + } - return Values?.SequenceEqual(other.Values ?? Array.Empty()) ?? false; + public bool Equals(OptionalSet other) + { + return Values.SetEquals(other.Values); } } diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 208e7f559e..fbb09b93bd 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Select return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt); case "status": - return TryUpdateArrayRange(ref criteria.OnlineStatus, op, value, tryParseEnum); + return TryUpdateSetRange(ref criteria.OnlineStatus, op, value, tryParseEnum); case "creator": case "author": @@ -306,23 +306,55 @@ namespace osu.Game.Screens.Select /// If can be parsed into using , the function returns true /// and the resulting range constraint is stored into the 's expected values. /// - /// The to store the parsed data into, if successful. + /// The to store the parsed data into, if successful. /// The operator for the keyword filter. Currently, only can be used. /// The value of the keyword filter. /// Function used to determine if can be converted to type . - public static bool TryUpdateArrayRange(ref FilterCriteria.OptionalArray range, Operator op, string val, TryParseFunction parseFunction) + public static bool TryUpdateSetRange(ref FilterCriteria.OptionalSet range, Operator op, string val, TryParseFunction parseFunction) where T : struct - => parseFunction.Invoke(val, out var converted) && tryUpdateArrayRange(ref range, op, converted); + => parseFunction.Invoke(val, out var converted) && tryUpdateSetRange(ref range, op, converted); - private static bool tryUpdateArrayRange(ref FilterCriteria.OptionalArray range, Operator op, T value) + private static bool tryUpdateSetRange(ref FilterCriteria.OptionalSet range, Operator op, T value) where T : struct { - if (op != Operator.Equal) - return false; + var enumValues = (T[])Enum.GetValues(typeof(T)); - range.Values ??= Array.Empty(); + foreach (var enumValue in enumValues) + { + switch (op) + { + case Operator.Less: + if (Comparer.Default.Compare(enumValue, value) < 0) + range.Values.Add(enumValue); - range.Values = range.Values.Append(value).ToArray(); + break; + + case Operator.LessOrEqual: + if (Comparer.Default.Compare(enumValue, value) <= 0) + range.Values.Add(enumValue); + + break; + + case Operator.Equal: + range.Values.Add(value); + break; + + case Operator.GreaterOrEqual: + if (Comparer.Default.Compare(enumValue, value) >= 0) + range.Values.Add(enumValue); + + break; + + case Operator.Greater: + if (Comparer.Default.Compare(enumValue, value) > 0) + range.Values.Add(enumValue); + + break; + + default: + return false; + } + } return true; } From 77119b2cdb1c4f2b743aa9a99eac1f48f74064d1 Mon Sep 17 00:00:00 2001 From: Vlad Frangu Date: Mon, 18 Mar 2024 16:44:42 +0200 Subject: [PATCH 820/915] chore: correct doc string --- osu.Game/Screens/Select/FilterQueryParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index fbb09b93bd..76d58963e7 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -307,7 +307,7 @@ namespace osu.Game.Screens.Select /// and the resulting range constraint is stored into the 's expected values. /// /// The to store the parsed data into, if successful. - /// The operator for the keyword filter. Currently, only can be used. + /// The operator for the keyword filter. /// The value of the keyword filter. /// Function used to determine if can be converted to type . public static bool TryUpdateSetRange(ref FilterCriteria.OptionalSet range, Operator op, string val, TryParseFunction parseFunction) From a3f3dcf853b6148c6c2cbebe41b88711c01d468a Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Mon, 18 Mar 2024 13:27:43 -0300 Subject: [PATCH 821/915] Inline percentage calculation --- osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs index 9c1f2748e9..8795eeac2d 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Edit.Checks double mappedLength = context.Beatmap.HitObjects.Last().GetEndTime(); double trackLength = context.WorkingBeatmap.Track.Length; - double mappedPercentage = calculatePercentage(mappedLength, trackLength); + double mappedPercentage = Math.Round(mappedLength / trackLength * 100); if (mappedPercentage < 80) { @@ -31,11 +31,6 @@ namespace osu.Game.Rulesets.Edit.Checks } } - private double calculatePercentage(double mappedLenght, double trackLenght) - { - return Math.Round(mappedLenght / trackLenght * 100); - } - public class IssueTemplateUnusedAudioAtEnd : IssueTemplate { public IssueTemplateUnusedAudioAtEnd(ICheck check) From 915a9682b5be54b090d39ae2a44beae8ea2c9ce7 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Mon, 18 Mar 2024 13:51:36 -0300 Subject: [PATCH 822/915] Fix issue type and display percentage left --- osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs index 8795eeac2d..d22303b7df 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs @@ -27,18 +27,19 @@ namespace osu.Game.Rulesets.Edit.Checks if (mappedPercentage < 80) { - yield return new IssueTemplateUnusedAudioAtEnd(this).Create(); + double percentageLeft = Math.Abs(mappedPercentage - 100); + yield return new IssueTemplateUnusedAudioAtEnd(this).Create(percentageLeft); } } public class IssueTemplateUnusedAudioAtEnd : IssueTemplate { public IssueTemplateUnusedAudioAtEnd(ICheck check) - : base(check, IssueType.Problem, "There is more than 20% unused audio at the end.") + : base(check, IssueType.Warning, "Currently there is {0}% unused audio at the end. Ensure the outro significantly contributes to the song, otherwise cut the outro.") { } - public Issue Create() => new Issue(this); + public Issue Create(double percentageLeft) => new Issue(this, percentageLeft); } } } From c23212f4efad0c58207265877a5130177f47d2e5 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Mon, 18 Mar 2024 14:02:33 -0300 Subject: [PATCH 823/915] Use `GetLastObjectTime` to calculate mapped length --- osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs index d22303b7df..d9a675fd17 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs @@ -3,9 +3,8 @@ using System; using System.Collections.Generic; -using System.Linq; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; -using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Edit.Checks { @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - double mappedLength = context.Beatmap.HitObjects.Last().GetEndTime(); + double mappedLength = context.Beatmap.GetLastObjectTime(); double trackLength = context.WorkingBeatmap.Track.Length; double mappedPercentage = Math.Round(mappedLength / trackLength * 100); From 0edc249637d56208bca655db17e274738df0b70e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 18 Mar 2024 20:38:19 +0300 Subject: [PATCH 824/915] Make Timeline non-nullable --- .../Components/Timeline/TimelineControlPointDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index 950b717ffb..1bf12e40d1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public partial class TimelineControlPointDisplay : TimelinePart { [Resolved] - private Timeline? timeline { get; set; } + private Timeline timeline { get; set; } = null!; /// /// The visible time/position range of the timeline. @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { base.Update(); - if (timeline == null || DrawWidth <= 0) return; + if (DrawWidth <= 0) return; (float, float) newRange = ( (ToLocalSpace(timeline.ScreenSpaceDrawQuad.TopLeft).X - TopPointPiece.WIDTH) / DrawWidth * Content.RelativeChildSize.X, From 7ca45c75b3348f66c0ec86e02a72c114abb27c8c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 18 Mar 2024 20:46:38 +0300 Subject: [PATCH 825/915] Don't iterate backwards on children without a reason --- .../Components/Timeline/TimelineControlPointDisplay.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index 1bf12e40d1..8e522fa715 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -63,12 +63,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void recreateDrawableGroups() { // Remove groups outside the visible range - for (int i = Count - 1; i >= 0; i--) + foreach (var drawableGroup in this) { - var g = Children[i]; - - if (!shouldBeVisible(g.Group)) - g.Expire(); + if (!shouldBeVisible(drawableGroup.Group)) + drawableGroup.Expire(); } // Add remaining ones From f6d7f18f2592071d98872e2cda18f8de9d20cfa1 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Mon, 18 Mar 2024 15:59:19 -0300 Subject: [PATCH 826/915] Remove unused localisation file --- .../CheckUnusedAudioAtEndStrings.cs | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs diff --git a/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs b/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs deleted file mode 100644 index 46f92237a9..0000000000 --- a/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs +++ /dev/null @@ -1,19 +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 osu.Framework.Localisation; - -namespace osu.Game.Localisation -{ - public static class CheckUnusedAudioAtEndStrings - { - private const string prefix = @"osu.Game.Resources.Localisation.CheckUnusedAudioAtEnd"; - - /// - /// "{0}% of the audio is not mapped." - /// - public static LocalisableString OfTheAudioIsNot(double percentageLeft) => new TranslatableString(getKey(@"of_the_audio_is_not"), @"{0}% of the audio is not mapped.", percentageLeft); - - private static string getKey(string key) => $@"{prefix}:{key}"; - } -} From 5241c999c1f3300f36723a1d070c23240936c8da Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Mon, 18 Mar 2024 16:08:41 -0300 Subject: [PATCH 827/915] Add different warning to maps with storyboard/video --- .../Checks/CheckUnusedAudioAtEndTest.cs | 51 +++++++++++++++++-- .../Edit/Checks/CheckUnusedAudioAtEnd.cs | 37 +++++++++++++- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs index 29c5cb96fd..33d73a8086 100644 --- a/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs @@ -4,12 +4,15 @@ using System.Linq; using Moq; using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Storyboards; +using osuTK; using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; namespace osu.Game.Tests.Editing.Checks @@ -47,7 +50,7 @@ namespace osu.Game.Tests.Editing.Checks }, BeatmapInfo = new BeatmapInfo { - Metadata = new BeatmapMetadata { AudioFile = "abc123.jpg" } + Metadata = new BeatmapMetadata { AudioFile = "abc123.jpg" }, } }; } @@ -62,6 +65,42 @@ namespace osu.Game.Tests.Editing.Checks Assert.That(issues.Single().Template is CheckUnusedAudioAtEnd.IssueTemplateUnusedAudioAtEnd); } + [Test] + public void TestAudioNotFullyUsedWithVideo() + { + var storyboard = new Storyboard(); + + var video = new StoryboardVideo("abc123.mp4", 0); + + storyboard.GetLayer("Video").Add(video); + + var mockWorkingBeatmap = getMockWorkingBeatmap(beatmapNotFullyMapped, storyboard); + + var context = getContext(beatmapNotFullyMapped, mockWorkingBeatmap); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckUnusedAudioAtEnd.IssueTemplateUnusedAudioAtEndStoryboardOrVideo); + } + + [Test] + public void TestAudioNotFullyUsedWithStoryboardElement() + { + var storyboard = new Storyboard(); + + var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero); + + storyboard.GetLayer("Background").Add(sprite); + + var mockWorkingBeatmap = getMockWorkingBeatmap(beatmapNotFullyMapped, storyboard); + + var context = getContext(beatmapNotFullyMapped, mockWorkingBeatmap); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckUnusedAudioAtEnd.IssueTemplateUnusedAudioAtEndStoryboardOrVideo); + } + [Test] public void TestAudioFullyUsed() { @@ -73,16 +112,22 @@ namespace osu.Game.Tests.Editing.Checks private BeatmapVerifierContext getContext(IBeatmap beatmap) { - return new BeatmapVerifierContext(beatmap, getMockWorkingBeatmap(beatmap).Object); + return new BeatmapVerifierContext(beatmap, getMockWorkingBeatmap(beatmap, new Storyboard()).Object); } - private Mock getMockWorkingBeatmap(IBeatmap beatmap) + private BeatmapVerifierContext getContext(IBeatmap beatmap, Mock workingBeatmap) + { + return new BeatmapVerifierContext(beatmap, workingBeatmap.Object); + } + + private Mock getMockWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard) { var mockTrack = new TrackVirtualStore(new FramedClock()).GetVirtual(10000, "virtual"); var mockWorkingBeatmap = new Mock(); mockWorkingBeatmap.SetupGet(w => w.Beatmap).Returns(beatmap); mockWorkingBeatmap.SetupGet(w => w.Track).Returns(mockTrack); + mockWorkingBeatmap.SetupGet(w => w.Storyboard).Returns(storyboard); return mockWorkingBeatmap; } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs index d9a675fd17..2f768b6ffa 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; +using osu.Game.Storyboards; namespace osu.Game.Rulesets.Edit.Checks { @@ -15,6 +16,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable PossibleTemplates => new IssueTemplate[] { new IssueTemplateUnusedAudioAtEnd(this), + new IssueTemplateUnusedAudioAtEndStoryboardOrVideo(this), }; public IEnumerable Run(BeatmapVerifierContext context) @@ -27,10 +29,33 @@ namespace osu.Game.Rulesets.Edit.Checks if (mappedPercentage < 80) { double percentageLeft = Math.Abs(mappedPercentage - 100); - yield return new IssueTemplateUnusedAudioAtEnd(this).Create(percentageLeft); + + bool storyboardIsPresent = isAnyStoryboardElementPresent(context.WorkingBeatmap.Storyboard); + + if (storyboardIsPresent) + { + yield return new IssueTemplateUnusedAudioAtEndStoryboardOrVideo(this).Create(percentageLeft); + } + else + { + yield return new IssueTemplateUnusedAudioAtEnd(this).Create(percentageLeft); + } } } + private bool isAnyStoryboardElementPresent(Storyboard storyboard) + { + foreach (var layer in storyboard.Layers) + { + foreach (var _ in layer.Elements) + { + return true; + } + } + + return false; + } + public class IssueTemplateUnusedAudioAtEnd : IssueTemplate { public IssueTemplateUnusedAudioAtEnd(ICheck check) @@ -40,5 +65,15 @@ namespace osu.Game.Rulesets.Edit.Checks public Issue Create(double percentageLeft) => new Issue(this, percentageLeft); } + + public class IssueTemplateUnusedAudioAtEndStoryboardOrVideo : IssueTemplate + { + public IssueTemplateUnusedAudioAtEndStoryboardOrVideo(ICheck check) + : base(check, IssueType.Warning, "Currently there is {0}% unused audio at the end. Ensure the outro significantly contributes to the song, or is being occupied by the video or storyboard, otherwise cut the outro.") + { + } + + public Issue Create(double percentageLeft) => new Issue(this, percentageLeft); + } } } From a8ce6a0bba5c65ab12360191d7589365d0996133 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 19 Mar 2024 02:43:34 +0300 Subject: [PATCH 828/915] Use `Slice` method instead of index range operators for readability --- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 2b058d5e1f..283a59b7ed 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -303,16 +303,16 @@ namespace osu.Game.Rulesets.Objects.Legacy { int startIndex = segmentsBuffer[i].StartIndex; int endIndex = segmentsBuffer[i + 1].StartIndex; - controlPoints.AddRange(convertPoints(segmentsBuffer[i].Type, allPoints[startIndex..endIndex], pointsBuffer[endIndex])); + controlPoints.AddRange(convertPoints(segmentsBuffer[i].Type, allPoints.Slice(startIndex, endIndex - startIndex), pointsBuffer[endIndex])); } else { int startIndex = segmentsBuffer[i].StartIndex; - controlPoints.AddRange(convertPoints(segmentsBuffer[i].Type, allPoints[startIndex..], null)); + controlPoints.AddRange(convertPoints(segmentsBuffer[i].Type, allPoints.Slice(startIndex), null)); } } - return mergePointsLists(controlPoints); + return mergeControlPointsLists(controlPoints); } finally { @@ -402,7 +402,7 @@ namespace osu.Game.Rulesets.Objects.Legacy - (p1.X - p0.X) * (p2.Y - p0.Y)); } - private PathControlPoint[] mergePointsLists(List> controlPointList) + private PathControlPoint[] mergeControlPointsLists(List> controlPointList) { int totalCount = 0; From af713a78695f4abd3e8023a98245f034fbb55da8 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 19 Mar 2024 17:20:59 +0900 Subject: [PATCH 829/915] Fix incorrectly encoded score IsPerfect value --- .../Formats/LegacyScoreEncoderTest.cs | 38 ++++++++++++++++--- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 7 +++- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 2 +- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs index c0a7285f39..c0bf47dfc9 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs @@ -6,6 +6,7 @@ using System.IO; using NUnit.Framework; using osu.Game.Beatmaps.Formats; using osu.Game.Rulesets.Catch; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; @@ -21,9 +22,9 @@ namespace osu.Game.Tests.Beatmaps.Formats public void CatchMergesFruitAndDropletMisses(int missCount, int largeTickMissCount) { var ruleset = new CatchRuleset().RulesetInfo; - var scoreInfo = TestResources.CreateTestScoreInfo(ruleset); var beatmap = new TestBeatmap(ruleset); + scoreInfo.Statistics = new Dictionary { [HitResult.Great] = 50, @@ -31,14 +32,41 @@ namespace osu.Game.Tests.Beatmaps.Formats [HitResult.Miss] = missCount, [HitResult.LargeTickMiss] = largeTickMissCount }; - var score = new Score { ScoreInfo = scoreInfo }; - var decodedAfterEncode = encodeThenDecode(LegacyBeatmapDecoder.LATEST_VERSION, score, beatmap); + var score = new Score { ScoreInfo = scoreInfo }; + var decodedAfterEncode = encodeThenDecode(LegacyBeatmapDecoder.LATEST_VERSION, score, beatmap, out _); Assert.That(decodedAfterEncode.ScoreInfo.GetCountMiss(), Is.EqualTo(missCount + largeTickMissCount)); } - private static Score encodeThenDecode(int beatmapVersion, Score score, TestBeatmap beatmap) + [Test] + public void ScoreWithMissIsNotPerfect() + { + var ruleset = new OsuRuleset().RulesetInfo; + var scoreInfo = TestResources.CreateTestScoreInfo(ruleset); + var beatmap = new TestBeatmap(ruleset); + + scoreInfo.Statistics = new Dictionary + { + [HitResult.Great] = 2, + [HitResult.Miss] = 1, + }; + + scoreInfo.MaximumStatistics = new Dictionary + { + [HitResult.Great] = 3 + }; + + // Hit -> Miss -> Hit + scoreInfo.Combo = 1; + scoreInfo.MaxCombo = 1; + + encodeThenDecode(LegacyBeatmapDecoder.LATEST_VERSION, new Score { ScoreInfo = scoreInfo }, beatmap, out var decoder); + + Assert.That(decoder.DecodedPerfectValue, Is.False); + } + + private static Score encodeThenDecode(int beatmapVersion, Score score, TestBeatmap beatmap, out LegacyScoreDecoderTest.TestLegacyScoreDecoder decoder) { var encodeStream = new MemoryStream(); @@ -47,7 +75,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decodeStream = new MemoryStream(encodeStream.GetBuffer()); - var decoder = new LegacyScoreDecoderTest.TestLegacyScoreDecoder(beatmapVersion); + decoder = new LegacyScoreDecoderTest.TestLegacyScoreDecoder(beatmapVersion); var decodedAfterEncode = decoder.Parse(decodeStream); return decodedAfterEncode; } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index 65e2c02655..f2c096da15 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -27,6 +27,11 @@ namespace osu.Game.Scoring.Legacy { public abstract class LegacyScoreDecoder { + /// + /// The decoded "IsPerfect" value. This isn't used by osu!lazer. + /// + public bool DecodedPerfectValue { get; private set; } + private IBeatmap currentBeatmap; private Ruleset currentRuleset; @@ -82,7 +87,7 @@ namespace osu.Game.Scoring.Legacy scoreInfo.MaxCombo = sr.ReadUInt16(); /* score.Perfect = */ - sr.ReadBoolean(); + DecodedPerfectValue = sr.ReadBoolean(); scoreInfo.Mods = currentRuleset.ConvertFromLegacyMods((LegacyMods)sr.ReadInt32()).ToArray(); diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 4ee4231925..1df54565e9 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -93,7 +93,7 @@ namespace osu.Game.Scoring.Legacy sw.Write((ushort)(score.ScoreInfo.GetCountMiss() ?? 0)); sw.Write((int)(score.ScoreInfo.TotalScore)); sw.Write((ushort)score.ScoreInfo.MaxCombo); - sw.Write(score.ScoreInfo.Combo == score.ScoreInfo.MaxCombo); + sw.Write(score.ScoreInfo.Combo == score.ScoreInfo.GetMaximumAchievableCombo()); sw.Write((int)score.ScoreInfo.Ruleset.CreateInstance().ConvertToLegacyMods(score.ScoreInfo.Mods)); sw.Write(getHpGraphFormatted()); From 6e3350941749a87b21ed2c819c063e7a556509f0 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 19 Mar 2024 17:44:37 +0900 Subject: [PATCH 830/915] Remove added property, use local decoding instead --- .../Formats/LegacyScoreEncoderTest.cs | 34 ++++++++++++++++--- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 7 +--- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs index c0bf47dfc9..806f538249 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreEncoderTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using NUnit.Framework; using osu.Game.Beatmaps.Formats; +using osu.Game.IO.Legacy; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; @@ -34,7 +35,7 @@ namespace osu.Game.Tests.Beatmaps.Formats }; var score = new Score { ScoreInfo = scoreInfo }; - var decodedAfterEncode = encodeThenDecode(LegacyBeatmapDecoder.LATEST_VERSION, score, beatmap, out _); + var decodedAfterEncode = encodeThenDecode(LegacyBeatmapDecoder.LATEST_VERSION, score, beatmap); Assert.That(decodedAfterEncode.ScoreInfo.GetCountMiss(), Is.EqualTo(missCount + largeTickMissCount)); } @@ -61,12 +62,35 @@ namespace osu.Game.Tests.Beatmaps.Formats scoreInfo.Combo = 1; scoreInfo.MaxCombo = 1; - encodeThenDecode(LegacyBeatmapDecoder.LATEST_VERSION, new Score { ScoreInfo = scoreInfo }, beatmap, out var decoder); + using (var ms = new MemoryStream()) + { + new LegacyScoreEncoder(new Score { ScoreInfo = scoreInfo }, beatmap).Encode(ms, true); - Assert.That(decoder.DecodedPerfectValue, Is.False); + ms.Seek(0, SeekOrigin.Begin); + + using (var sr = new SerializationReader(ms)) + { + sr.ReadByte(); // ruleset id + sr.ReadInt32(); // version + sr.ReadString(); // beatmap hash + sr.ReadString(); // username + sr.ReadString(); // score hash + sr.ReadInt16(); // count300 + sr.ReadInt16(); // count100 + sr.ReadInt16(); // count50 + sr.ReadInt16(); // countGeki + sr.ReadInt16(); // countKatu + sr.ReadInt16(); // countMiss + sr.ReadInt32(); // total score + sr.ReadInt16(); // max combo + bool isPerfect = sr.ReadBoolean(); // full combo + + Assert.That(isPerfect, Is.False); + } + } } - private static Score encodeThenDecode(int beatmapVersion, Score score, TestBeatmap beatmap, out LegacyScoreDecoderTest.TestLegacyScoreDecoder decoder) + private static Score encodeThenDecode(int beatmapVersion, Score score, TestBeatmap beatmap) { var encodeStream = new MemoryStream(); @@ -75,7 +99,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var decodeStream = new MemoryStream(encodeStream.GetBuffer()); - decoder = new LegacyScoreDecoderTest.TestLegacyScoreDecoder(beatmapVersion); + var decoder = new LegacyScoreDecoderTest.TestLegacyScoreDecoder(beatmapVersion); var decodedAfterEncode = decoder.Parse(decodeStream); return decodedAfterEncode; } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index f2c096da15..65e2c02655 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -27,11 +27,6 @@ namespace osu.Game.Scoring.Legacy { public abstract class LegacyScoreDecoder { - /// - /// The decoded "IsPerfect" value. This isn't used by osu!lazer. - /// - public bool DecodedPerfectValue { get; private set; } - private IBeatmap currentBeatmap; private Ruleset currentRuleset; @@ -87,7 +82,7 @@ namespace osu.Game.Scoring.Legacy scoreInfo.MaxCombo = sr.ReadUInt16(); /* score.Perfect = */ - DecodedPerfectValue = sr.ReadBoolean(); + sr.ReadBoolean(); scoreInfo.Mods = currentRuleset.ConvertFromLegacyMods((LegacyMods)sr.ReadInt32()).ToArray(); From f6069d8d93b05c752b1aeaa36e4c269580880f26 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 19 Mar 2024 17:46:18 +0900 Subject: [PATCH 831/915] Compare against MaxCombo instead --- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 1df54565e9..93f51ee74d 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -93,7 +93,7 @@ namespace osu.Game.Scoring.Legacy sw.Write((ushort)(score.ScoreInfo.GetCountMiss() ?? 0)); sw.Write((int)(score.ScoreInfo.TotalScore)); sw.Write((ushort)score.ScoreInfo.MaxCombo); - sw.Write(score.ScoreInfo.Combo == score.ScoreInfo.GetMaximumAchievableCombo()); + sw.Write(score.ScoreInfo.MaxCombo == score.ScoreInfo.GetMaximumAchievableCombo()); sw.Write((int)score.ScoreInfo.Ruleset.CreateInstance().ConvertToLegacyMods(score.ScoreInfo.Mods)); sw.Write(getHpGraphFormatted()); From 0de5ca8d2df633b044b41d121bb3ed97aee73e47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Mar 2024 01:26:39 +0800 Subject: [PATCH 832/915] Update incorrect xmldoc --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index fd1ce5d829..8bb3ae8182 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -18,7 +18,7 @@ using osuTK; namespace osu.Game.Screens.Play { /// - /// Simple that resumes after 800ms. + /// Simple that resumes after a short delay. /// public partial class DelayedResumeOverlay : ResumeOverlay { From feaf59e15f701e1348122e17c4650420b8a581ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 19 Mar 2024 18:19:06 +0100 Subject: [PATCH 833/915] Use `HashSet` instead of `SortedSet` No need for it to be sorted. --- .../NonVisual/Filtering/FilterQueryParserTest.cs | 16 ++++++++-------- osu.Game/Screens/Select/FilterCriteria.cs | 12 +++--------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 98d3286409..bd706b5b4c 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -257,7 +257,7 @@ namespace osu.Game.Tests.NonVisual.Filtering var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); - Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); + Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Ranked)); } [Test] @@ -269,7 +269,7 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.AreEqual("I want the pp", filterCriteria.SearchText.Trim()); Assert.AreEqual(4, filterCriteria.SearchTerms.Length); Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); - Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); + Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Ranked)); } [Test] @@ -279,8 +279,8 @@ namespace osu.Game.Tests.NonVisual.Filtering var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); - Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); - Assert.Contains(BeatmapOnlineStatus.Loved, filterCriteria.OnlineStatus.Values); + Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Ranked)); + Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Loved)); } [Test] @@ -290,10 +290,10 @@ namespace osu.Game.Tests.NonVisual.Filtering var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); - Assert.Contains(BeatmapOnlineStatus.Ranked, filterCriteria.OnlineStatus.Values); - Assert.Contains(BeatmapOnlineStatus.Approved, filterCriteria.OnlineStatus.Values); - Assert.Contains(BeatmapOnlineStatus.Qualified, filterCriteria.OnlineStatus.Values); - Assert.Contains(BeatmapOnlineStatus.Loved, filterCriteria.OnlineStatus.Values); + Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Ranked)); + Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Approved)); + Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Qualified)); + Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Loved)); } [TestCase("creator")] diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 1d155574cf..6750b07aba 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -119,21 +119,15 @@ namespace osu.Game.Screens.Select { public bool HasFilter => Values.Count > 0; - public bool IsInRange(T value) - { - return Values.Contains(value); - } + public bool IsInRange(T value) => Values.Contains(value); - public SortedSet Values = new SortedSet(); + public HashSet Values = new HashSet(); public OptionalSet() { } - public bool Equals(OptionalSet other) - { - return Values.SetEquals(other.Values); - } + public bool Equals(OptionalSet other) => Values.SetEquals(other.Values); } public struct OptionalRange : IEquatable> From 320373e3e0a50c5b94a0f5a68a108ce24b3da2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 19 Mar 2024 18:28:13 +0100 Subject: [PATCH 834/915] Rename method to match convention better --- osu.Game/Screens/Select/FilterQueryParser.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 76d58963e7..194a288426 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Select return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt); case "status": - return TryUpdateSetRange(ref criteria.OnlineStatus, op, value, tryParseEnum); + return TryUpdateCriteriaSet(ref criteria.OnlineStatus, op, value, tryParseEnum); case "creator": case "author": @@ -310,11 +310,11 @@ namespace osu.Game.Screens.Select /// The operator for the keyword filter. /// The value of the keyword filter. /// Function used to determine if can be converted to type . - public static bool TryUpdateSetRange(ref FilterCriteria.OptionalSet range, Operator op, string val, TryParseFunction parseFunction) + public static bool TryUpdateCriteriaSet(ref FilterCriteria.OptionalSet range, Operator op, string val, TryParseFunction parseFunction) where T : struct - => parseFunction.Invoke(val, out var converted) && tryUpdateSetRange(ref range, op, converted); + => parseFunction.Invoke(val, out var converted) && tryUpdateCriteriaSet(ref range, op, converted); - private static bool tryUpdateSetRange(ref FilterCriteria.OptionalSet range, Operator op, T value) + private static bool tryUpdateCriteriaSet(ref FilterCriteria.OptionalSet range, Operator op, T value) where T : struct { var enumValues = (T[])Enum.GetValues(typeof(T)); From af3f7dcbbfb3e5b955f45e56815238eae71ccbdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 19 Mar 2024 18:31:07 +0100 Subject: [PATCH 835/915] Retouch update criteria method --- osu.Game/Screens/Select/FilterQueryParser.cs | 30 ++++++++------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 194a288426..32b533e18d 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -311,44 +311,38 @@ namespace osu.Game.Screens.Select /// The value of the keyword filter. /// Function used to determine if can be converted to type . public static bool TryUpdateCriteriaSet(ref FilterCriteria.OptionalSet range, Operator op, string val, TryParseFunction parseFunction) - where T : struct + where T : struct, Enum => parseFunction.Invoke(val, out var converted) && tryUpdateCriteriaSet(ref range, op, converted); - private static bool tryUpdateCriteriaSet(ref FilterCriteria.OptionalSet range, Operator op, T value) - where T : struct + private static bool tryUpdateCriteriaSet(ref FilterCriteria.OptionalSet range, Operator op, T pivotValue) + where T : struct, Enum { - var enumValues = (T[])Enum.GetValues(typeof(T)); + var allDefinedValues = Enum.GetValues(); - foreach (var enumValue in enumValues) + foreach (var val in allDefinedValues) { + int compareResult = Comparer.Default.Compare(val, pivotValue); + switch (op) { case Operator.Less: - if (Comparer.Default.Compare(enumValue, value) < 0) - range.Values.Add(enumValue); - + if (compareResult < 0) range.Values.Add(val); break; case Operator.LessOrEqual: - if (Comparer.Default.Compare(enumValue, value) <= 0) - range.Values.Add(enumValue); - + if (compareResult <= 0) range.Values.Add(val); break; case Operator.Equal: - range.Values.Add(value); + if (compareResult == 0) range.Values.Add(val); break; case Operator.GreaterOrEqual: - if (Comparer.Default.Compare(enumValue, value) >= 0) - range.Values.Add(enumValue); - + if (compareResult >= 0) range.Values.Add(val); break; case Operator.Greater: - if (Comparer.Default.Compare(enumValue, value) > 0) - range.Values.Add(enumValue); - + if (compareResult > 0) range.Values.Add(val); break; default: From 0211ae12adbed9b0d37881fbc87774ca901a0953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 19 Mar 2024 19:16:33 +0100 Subject: [PATCH 836/915] Add failing test case for crash on empty beatmap --- .../Editing/Checks/CheckUnusedAudioAtEndTest.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs index 33d73a8086..bf996b06ea 100644 --- a/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs @@ -55,6 +55,16 @@ namespace osu.Game.Tests.Editing.Checks }; } + [Test] + public void TestEmptyBeatmap() + { + var context = getContext(new Beatmap()); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckUnusedAudioAtEnd.IssueTemplateUnusedAudioAtEnd); + } + [Test] public void TestAudioNotFullyUsed() { From 2b83e6bc4cc325375f1db483e84af25f73330087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 19 Mar 2024 19:17:22 +0100 Subject: [PATCH 837/915] Fix check crash on empty beatmap --- osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs index 2f768b6ffa..2e97fbeb99 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Storyboards; @@ -21,7 +22,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - double mappedLength = context.Beatmap.GetLastObjectTime(); + double mappedLength = context.Beatmap.HitObjects.Any() ? context.Beatmap.GetLastObjectTime() : 0; double trackLength = context.WorkingBeatmap.Track.Length; double mappedPercentage = Math.Round(mappedLength / trackLength * 100); From e4418547feba011e5461d2a9d5358d198d341427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 19 Mar 2024 19:19:07 +0100 Subject: [PATCH 838/915] Document `GetLastObjectTime()` exception on empty beatmap --- osu.Game/Beatmaps/IBeatmap.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index b5bb6ccafc..6fe494ca0f 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.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 osu.Game.Beatmaps.ControlPoints; @@ -129,6 +130,7 @@ namespace osu.Game.Beatmaps /// /// It's not super efficient so calls should be kept to a minimum. /// + /// If has no objects. public static double GetLastObjectTime(this IBeatmap beatmap) => beatmap.HitObjects.Max(h => h.GetEndTime()); #region Helper methods From 808d6e09436468c8690311f235852ed0dd7834c9 Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 19 Mar 2024 16:02:06 -0400 Subject: [PATCH 839/915] Prevent potential threading issues --- osu.Desktop/DiscordRichPresence.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index ca26cab0fd..080032a298 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -97,11 +97,13 @@ namespace osu.Desktop private void onReady(object _, ReadyMessage __) { Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug); - updateStatus(); + Schedule(updateStatus); } private void updateStatus() { + Debug.Assert(ThreadSafety.IsUpdateThread); + if (!client.IsInitialized) return; From 0ecfa580d7a48d247ab9fa9907fdd0f1d739d732 Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 19 Mar 2024 16:03:32 -0400 Subject: [PATCH 840/915] Move room code from activity code, prevent duplicate RPC updates --- osu.Desktop/DiscordRichPresence.cs | 68 +++++++++++++++++------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 080032a298..633b6324b7 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -2,12 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Text; using DiscordRPC; using DiscordRPC.Message; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game; @@ -48,6 +50,8 @@ namespace osu.Desktop private readonly Bindable privacyMode = new Bindable(); + private int usersCurrentlyInLobby = 0; + private readonly RichPresence presence = new RichPresence { Assets = new Assets { LargeImageKey = "osu_logo_lazer" }, @@ -115,10 +119,10 @@ namespace osu.Desktop Logger.Log("Updating Discord RPC", LoggingTarget.Network, LogLevel.Debug); + bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; + if (activity.Value != null) { - bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; - presence.State = truncate(activity.Value.GetStatus(hideIdentifiableInformation)); presence.Details = truncate(activity.Value.GetDetails(hideIdentifiableInformation) ?? string.Empty); @@ -137,33 +141,6 @@ namespace osu.Desktop { presence.Buttons = null; } - - if (!hideIdentifiableInformation && multiplayerClient.Room != null) - { - MultiplayerRoom room = multiplayerClient.Room; - presence.Party = new Party - { - Privacy = string.IsNullOrEmpty(room.Settings.Password) ? Party.PrivacySetting.Public : Party.PrivacySetting.Private, - ID = room.RoomID.ToString(), - // technically lobbies can have infinite users, but Discord needs this to be set to something. - // to make party display sensible, assign a powers of two above participants count (8 at minimum). - Max = (int)Math.Max(8, Math.Pow(2, Math.Ceiling(Math.Log2(room.Users.Count)))), - Size = room.Users.Count, - }; - - RoomSecret roomSecret = new RoomSecret - { - RoomID = room.RoomID, - Password = room.Settings.Password, - }; - - presence.Secrets.JoinSecret = JsonConvert.SerializeObject(roomSecret); - } - else - { - presence.Party = null; - presence.Secrets.JoinSecret = null; - } } else { @@ -171,6 +148,39 @@ namespace osu.Desktop presence.Details = string.Empty; } + if (!hideIdentifiableInformation && multiplayerClient.Room != null) + { + MultiplayerRoom room = multiplayerClient.Room; + + if (room.Users.Count == usersCurrentlyInLobby) + return; + + presence.Party = new Party + { + Privacy = string.IsNullOrEmpty(room.Settings.Password) ? Party.PrivacySetting.Public : Party.PrivacySetting.Private, + ID = room.RoomID.ToString(), + // technically lobbies can have infinite users, but Discord needs this to be set to something. + // to make party display sensible, assign a powers of two above participants count (8 at minimum). + Max = (int)Math.Max(8, Math.Pow(2, Math.Ceiling(Math.Log2(room.Users.Count)))), + Size = room.Users.Count, + }; + + RoomSecret roomSecret = new RoomSecret + { + RoomID = room.RoomID, + Password = room.Settings.Password, + }; + + presence.Secrets.JoinSecret = JsonConvert.SerializeObject(roomSecret); + usersCurrentlyInLobby = room.Users.Count; + } + else + { + presence.Party = null; + presence.Secrets.JoinSecret = null; + usersCurrentlyInLobby = 0; + } + // update user information if (privacyMode.Value == DiscordRichPresenceMode.Limited) presence.Assets.LargeImageText = string.Empty; From c71daba4f663164a8180561bbadc8e0ee6f78a46 Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 19 Mar 2024 16:05:13 -0400 Subject: [PATCH 841/915] Improve logging of RPC Co-authored-by: Salman Ahmed --- osu.Desktop/DiscordRichPresence.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 633b6324b7..f47b2eaba5 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -117,8 +117,6 @@ namespace osu.Desktop return; } - Logger.Log("Updating Discord RPC", LoggingTarget.Network, LogLevel.Debug); - bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; if (activity.Value != null) @@ -181,6 +179,8 @@ namespace osu.Desktop usersCurrentlyInLobby = 0; } + Logger.Log($"Updating Discord RPC presence with activity status: {presence.State}, details: {presence.Details}", LoggingTarget.Network, LogLevel.Debug); + // update user information if (privacyMode.Value == DiscordRichPresenceMode.Limited) presence.Assets.LargeImageText = string.Empty; From 4305c3db5b70b70d1e28ba1deeb807b28742481e Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 19 Mar 2024 16:15:22 -0400 Subject: [PATCH 842/915] Show login overlay when joining room while not logged in --- osu.Desktop/DiscordRichPresence.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index f47b2eaba5..a2d7ace0e0 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -19,6 +19,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; +using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Users; using LogLevel = osu.Framework.Logging.LogLevel; @@ -42,6 +43,8 @@ namespace osu.Desktop [Resolved] private OsuGame game { get; set; } = null!; + private LoginOverlay? login { get; set; } + [Resolved] private MultiplayerClient multiplayerClient { get; set; } = null!; @@ -65,6 +68,8 @@ namespace osu.Desktop [BackgroundDependencyLoader] private void load(OsuConfigManager config) { + login = game.Dependencies.Get(); + client = new DiscordRpcClient(client_id) { SkipIdenticalPresence = false // handles better on discord IPC loss, see updateStatus call in onReady. @@ -203,6 +208,12 @@ namespace osu.Desktop { game.Window?.Raise(); + if (!api.IsLoggedIn) + { + Schedule(() => login?.Show()); + return; + } + Logger.Log($"Received room secret from Discord RPC Client: \"{args.Secret}\"", LoggingTarget.Network, LogLevel.Debug); // Stable and lazer share the same Discord client ID, meaning they can accept join requests from each other. From 1a08dbaa2ba929c26e3463163f3c8ac9523809c5 Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 19 Mar 2024 17:03:30 -0400 Subject: [PATCH 843/915] Fix code style --- osu.Desktop/DiscordRichPresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index a2d7ace0e0..d8013aabfe 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -53,7 +53,7 @@ namespace osu.Desktop private readonly Bindable privacyMode = new Bindable(); - private int usersCurrentlyInLobby = 0; + private int usersCurrentlyInLobby; private readonly RichPresence presence = new RichPresence { From d83a53fc944eea90ad8244e248ec762e6d6d6ad3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Mar 2024 12:10:05 +0800 Subject: [PATCH 844/915] Remove unused `ScreenBreadcrumbControl` See https://github.com/ppy/osu-framework/pull/6218#discussion_r1529932798. --- .../TestSceneScreenBreadcrumbControl.cs | 138 ------------------ .../UserInterface/ScreenBreadcrumbControl.cs | 48 ------ 2 files changed, 186 deletions(-) delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs delete mode 100644 osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs deleted file mode 100644 index 968cf9f9db..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs +++ /dev/null @@ -1,138 +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 NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Screens; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Screens; -using osuTK; - -namespace osu.Game.Tests.Visual.UserInterface -{ - [TestFixture] - public partial class TestSceneScreenBreadcrumbControl : OsuTestScene - { - private readonly ScreenBreadcrumbControl breadcrumbs; - private readonly OsuScreenStack screenStack; - - public TestSceneScreenBreadcrumbControl() - { - OsuSpriteText titleText; - - IScreen startScreen = new TestScreenOne(); - - screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; - screenStack.Push(startScreen); - - Children = new Drawable[] - { - screenStack, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(10), - Children = new Drawable[] - { - breadcrumbs = new ScreenBreadcrumbControl(screenStack) - { - RelativeSizeAxes = Axes.X, - }, - titleText = new OsuSpriteText(), - }, - }, - }; - - breadcrumbs.Current.ValueChanged += screen => titleText.Text = $"Changed to {screen.NewValue}"; - breadcrumbs.Current.TriggerChange(); - - waitForCurrent(); - pushNext(); - waitForCurrent(); - pushNext(); - waitForCurrent(); - - AddStep(@"make start current", () => startScreen.MakeCurrent()); - - waitForCurrent(); - pushNext(); - waitForCurrent(); - AddAssert(@"only 2 items", () => breadcrumbs.Items.Count == 2); - AddStep(@"exit current", () => screenStack.CurrentScreen.Exit()); - AddAssert(@"current screen is first", () => startScreen == screenStack.CurrentScreen); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - breadcrumbs.StripColour = colours.Blue; - } - - private void pushNext() => AddStep(@"push next screen", () => ((TestScreen)screenStack.CurrentScreen).PushNext()); - private void waitForCurrent() => AddUntilStep("current screen", () => screenStack.CurrentScreen.IsCurrentScreen()); - - private abstract partial class TestScreen : OsuScreen - { - protected abstract string NextTitle { get; } - protected abstract TestScreen CreateNextScreen(); - - public TestScreen PushNext() - { - TestScreen screen = CreateNextScreen(); - this.Push(screen); - - return screen; - } - - protected TestScreen() - { - InternalChild = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(10), - Children = new Drawable[] - { - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = Title, - }, - new RoundedButton - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 100, - Text = $"Push {NextTitle}", - Action = () => PushNext(), - }, - }, - }; - } - } - - private partial class TestScreenOne : TestScreen - { - public override string Title => @"Screen One"; - protected override string NextTitle => @"Two"; - protected override TestScreen CreateNextScreen() => new TestScreenTwo(); - } - - private partial class TestScreenTwo : TestScreen - { - public override string Title => @"Screen Two"; - protected override string NextTitle => @"One"; - protected override TestScreen CreateNextScreen() => new TestScreenOne(); - } - } -} diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs deleted file mode 100644 index 65dce422d6..0000000000 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Screens; - -namespace osu.Game.Graphics.UserInterface -{ - /// - /// A which follows the active screen (and allows navigation) in a stack. - /// - public partial class ScreenBreadcrumbControl : BreadcrumbControl - { - public ScreenBreadcrumbControl(ScreenStack stack) - { - stack.ScreenPushed += onPushed; - stack.ScreenExited += onExited; - - if (stack.CurrentScreen != null) - onPushed(null, stack.CurrentScreen); - } - - protected override void SelectTab(TabItem tab) - { - // override base method to prevent current item from being changed on click. - // depend on screen push/exit to change current item instead. - tab.Value.MakeCurrent(); - } - - private void onPushed(IScreen lastScreen, IScreen newScreen) - { - AddItem(newScreen); - Current.Value = newScreen; - } - - private void onExited(IScreen lastScreen, IScreen newScreen) - { - if (newScreen != null) - Current.Value = newScreen; - - Items.ToList().SkipWhile(s => s != Current.Value).Skip(1).ForEach(RemoveItem); - } - } -} From b11ae1c5714b43d33ebbec569faf6569d0304c25 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 20 Mar 2024 06:40:18 +0300 Subject: [PATCH 845/915] Organise code, still hook up to `RoomChanged` to update room privacy mode, and use `SkipIdenticalPresence` + scheduling to avoid potential rate-limits --- osu.Desktop/DiscordRichPresence.cs | 87 ++++++++++++++++++------------ 1 file changed, 54 insertions(+), 33 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index d8013aabfe..8e4af5c5b1 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -2,16 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics; using System.Text; using DiscordRPC; using DiscordRPC.Message; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Development; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Logging; +using osu.Framework.Threading; using osu.Game; using osu.Game.Configuration; using osu.Game.Extensions; @@ -53,8 +53,6 @@ namespace osu.Desktop private readonly Bindable privacyMode = new Bindable(); - private int usersCurrentlyInLobby; - private readonly RichPresence presence = new RichPresence { Assets = new Assets { LargeImageKey = "osu_logo_lazer" }, @@ -72,7 +70,9 @@ namespace osu.Desktop client = new DiscordRpcClient(client_id) { - SkipIdenticalPresence = false // handles better on discord IPC loss, see updateStatus call in onReady. + // SkipIdenticalPresence allows us to fire SetPresence at any point and leave it to the underlying implementation + // to check whether a difference has actually occurred before sending a command to Discord (with a minor caveat that's handled in onReady). + SkipIdenticalPresence = true }; client.OnReady += onReady; @@ -95,10 +95,11 @@ namespace osu.Desktop activity.BindTo(u.NewValue.Activity); }, true); - ruleset.BindValueChanged(_ => updateStatus()); - status.BindValueChanged(_ => updateStatus()); - activity.BindValueChanged(_ => updateStatus()); - privacyMode.BindValueChanged(_ => updateStatus()); + ruleset.BindValueChanged(_ => updatePresence()); + status.BindValueChanged(_ => updatePresence()); + activity.BindValueChanged(_ => updatePresence()); + privacyMode.BindValueChanged(_ => updatePresence()); + multiplayerClient.RoomUpdated += onRoomUpdated; client.Initialize(); } @@ -106,24 +107,44 @@ namespace osu.Desktop private void onReady(object _, ReadyMessage __) { Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug); - Schedule(updateStatus); + + // when RPC is lost and reconnected, we have to clear presence state for updatePresence to work (see DiscordRpcClient.SkipIdenticalPresence). + if (client.CurrentPresence != null) + client.SetPresence(null); + + updatePresence(); } - private void updateStatus() + private void onRoomUpdated() => updatePresence(); + + private ScheduledDelegate? presenceUpdateDelegate; + + private void updatePresence() { - Debug.Assert(ThreadSafety.IsUpdateThread); - - if (!client.IsInitialized) - return; - - if (status.Value == UserStatus.Offline || privacyMode.Value == DiscordRichPresenceMode.Off) + presenceUpdateDelegate?.Cancel(); + presenceUpdateDelegate = Scheduler.AddDelayed(() => { - client.ClearPresence(); - return; - } + if (!client.IsInitialized) + return; - bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; + if (status.Value == UserStatus.Offline || privacyMode.Value == DiscordRichPresenceMode.Off) + { + client.ClearPresence(); + return; + } + bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; + + updatePresenceStatus(hideIdentifiableInformation); + updatePresenceParty(hideIdentifiableInformation); + updatePresenceAssets(); + + client.SetPresence(presence); + }, 200); + } + + private void updatePresenceStatus(bool hideIdentifiableInformation) + { if (activity.Value != null) { presence.State = truncate(activity.Value.GetStatus(hideIdentifiableInformation)); @@ -150,14 +171,14 @@ namespace osu.Desktop presence.State = "Idle"; presence.Details = string.Empty; } + } + private void updatePresenceParty(bool hideIdentifiableInformation) + { if (!hideIdentifiableInformation && multiplayerClient.Room != null) { MultiplayerRoom room = multiplayerClient.Room; - if (room.Users.Count == usersCurrentlyInLobby) - return; - presence.Party = new Party { Privacy = string.IsNullOrEmpty(room.Settings.Password) ? Party.PrivacySetting.Public : Party.PrivacySetting.Private, @@ -175,17 +196,16 @@ namespace osu.Desktop }; presence.Secrets.JoinSecret = JsonConvert.SerializeObject(roomSecret); - usersCurrentlyInLobby = room.Users.Count; } else { presence.Party = null; presence.Secrets.JoinSecret = null; - usersCurrentlyInLobby = 0; } + } - Logger.Log($"Updating Discord RPC presence with activity status: {presence.State}, details: {presence.Details}", LoggingTarget.Network, LogLevel.Debug); - + private void updatePresenceAssets() + { // update user information if (privacyMode.Value == DiscordRichPresenceMode.Limited) presence.Assets.LargeImageText = string.Empty; @@ -200,17 +220,15 @@ namespace osu.Desktop // update ruleset presence.Assets.SmallImageKey = ruleset.Value.IsLegacyRuleset() ? $"mode_{ruleset.Value.OnlineID}" : "mode_custom"; presence.Assets.SmallImageText = ruleset.Value.Name; - - client.SetPresence(presence); } - private void onJoin(object sender, JoinMessage args) + private void onJoin(object sender, JoinMessage args) => Scheduler.AddOnce(() => { game.Window?.Raise(); if (!api.IsLoggedIn) { - Schedule(() => login?.Show()); + login?.Show(); return; } @@ -231,7 +249,7 @@ namespace osu.Desktop }); request.Failure += _ => Logger.Log($"Could not join multiplayer room, room could not be found (room ID: {roomId}).", LoggingTarget.Network, LogLevel.Important); api.Queue(request); - } + }); private static readonly int ellipsis_length = Encoding.UTF8.GetByteCount(new[] { '…' }); @@ -294,6 +312,9 @@ namespace osu.Desktop protected override void Dispose(bool isDisposing) { + if (multiplayerClient.IsNotNull()) + multiplayerClient.RoomUpdated -= onRoomUpdated; + client.Dispose(); base.Dispose(isDisposing); } From 5f86b5a2fa2b109ec63d283a84356dc46efb67ac Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 20 Mar 2024 07:36:15 +0300 Subject: [PATCH 846/915] Use DI correctly --- osu.Desktop/DiscordRichPresence.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 8e4af5c5b1..d78459ff28 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -43,6 +43,7 @@ namespace osu.Desktop [Resolved] private OsuGame game { get; set; } = null!; + [Resolved] private LoginOverlay? login { get; set; } [Resolved] @@ -66,8 +67,6 @@ namespace osu.Desktop [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - login = game.Dependencies.Get(); - client = new DiscordRpcClient(client_id) { // SkipIdenticalPresence allows us to fire SetPresence at any point and leave it to the underlying implementation From fd509c82f50a59293fee0978769bcaa02c28f852 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Mar 2024 12:52:54 +0800 Subject: [PATCH 847/915] Adjust code structure slightly --- .../Timeline/TimelineControlPointDisplay.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index 8e522fa715..116a3ee105 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -32,10 +32,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline controlPointGroups.UnbindAll(); controlPointGroups.BindTo(beatmap.ControlPointInfo.Groups); - controlPointGroups.BindCollectionChanged((_, _) => - { - invalidateGroups(); - }, true); + controlPointGroups.BindCollectionChanged((_, _) => groupCache.Invalidate(), true); } protected override void Update() @@ -51,19 +48,20 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (visibleRange != newRange) { visibleRange = newRange; - invalidateGroups(); + groupCache.Invalidate(); } if (!groupCache.IsValid) + { recreateDrawableGroups(); + groupCache.Validate(); + } } - private void invalidateGroups() => groupCache.Invalidate(); - private void recreateDrawableGroups() { // Remove groups outside the visible range - foreach (var drawableGroup in this) + foreach (TimelineControlPointGroup drawableGroup in this) { if (!shouldBeVisible(drawableGroup.Group)) drawableGroup.Expire(); @@ -93,8 +91,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Add(new TimelineControlPointGroup(group)); } - - groupCache.Validate(); } private bool shouldBeVisible(ControlPointGroup group) => group.Time >= visibleRange.min && group.Time <= visibleRange.max; From 1f343b75454c416b8c17d98428330096213c7fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 20 Mar 2024 08:27:49 +0100 Subject: [PATCH 848/915] Add extended logging when discarding online metadata lookup results Related to: https://github.com/ppy/osu/issues/27674 Relevant log output for that particular case: [network] 2024-03-20 07:25:30 [verbose]: Performing request osu.Game.Online.API.Requests.GetBeatmapRequest [network] 2024-03-20 07:25:30 [verbose]: Request to https://dev.ppy.sh/api/v2/beatmaps/lookup successfully completed! [network] 2024-03-20 07:25:30 [verbose]: GetBeatmapRequest finished with response size of 3,170 bytes [database] 2024-03-20 07:25:30 [verbose]: [4fe02] [APIBeatmapMetadataSource] Online retrieval mapped Tsukiyama Sae - Hana Saku Iro wa Koi no Gotoshi (Log Off Now) [Destiny] to 744883 / 1613507. [database] 2024-03-20 07:25:30 [verbose]: Discarding metadata lookup result due to mismatching online ID (expected: 1570982 actual: 1613507) [network] 2024-03-20 07:25:30 [verbose]: Performing request osu.Game.Online.API.Requests.GetBeatmapRequest [network] 2024-03-20 07:25:30 [verbose]: Request to https://dev.ppy.sh/api/v2/beatmaps/lookup successfully completed! [network] 2024-03-20 07:25:30 [verbose]: GetBeatmapRequest finished with response size of 2,924 bytes [database] 2024-03-20 07:25:30 [verbose]: [4fe02] [APIBeatmapMetadataSource] Online retrieval mapped Tsukiyama Sae - Hana Saku Iro wa Koi no Gotoshi (Log Off Now) [Easy] to 744883 / 1570982. [database] 2024-03-20 07:25:30 [verbose]: Discarding metadata lookup result due to mismatching online ID (expected: 1613507 actual: 1570982) Note that the online IDs are swapped. --- osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index f395718a93..034ec31ee4 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Online.API; @@ -85,10 +86,16 @@ namespace osu.Game.Beatmaps private bool shouldDiscardLookupResult(OnlineBeatmapMetadata result, BeatmapInfo beatmapInfo) { if (beatmapInfo.OnlineID > 0 && result.BeatmapID != beatmapInfo.OnlineID) + { + Logger.Log($"Discarding metadata lookup result due to mismatching online ID (expected: {beatmapInfo.OnlineID} actual: {result.BeatmapID})", LoggingTarget.Database); return true; + } if (beatmapInfo.OnlineID == -1 && result.MD5Hash != beatmapInfo.MD5Hash) + { + Logger.Log($"Discarding metadata lookup result due to mismatching hash (expected: {beatmapInfo.MD5Hash} actual: {result.MD5Hash})", LoggingTarget.Database); return true; + } return false; } From c78e203df5434495a79589559b973917a4088a3e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 20 Mar 2024 17:30:34 +0900 Subject: [PATCH 849/915] Fix infinite health processor loop when no top-level objects This is unlikely to occur in actual gameplay, but occurs in the follow-up test. --- osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs index 2bc3ea80ec..7cee5ebecf 100644 --- a/osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/LegacyDrainingHealthProcessor.cs @@ -108,6 +108,9 @@ namespace osu.Game.Rulesets.Scoring increaseHp(h); } + if (topLevelObjectCount == 0) + return testDrop; + if (!fail && currentHp < lowestHpEnd) { fail = true; From 66ace02e5872bd900acdaf7682a9178eea7dc168 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 20 Mar 2024 17:31:11 +0900 Subject: [PATCH 850/915] Add test for banana shower fail --- osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs index d0a8ce4bbc..1b46be01fb 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchHealthProcessorTest.cs @@ -19,6 +19,7 @@ namespace osu.Game.Rulesets.Catch.Tests [new Droplet(), 0.01, true], [new TinyDroplet(), 0, false], [new Banana(), 0, false], + [new BananaShower(), 0, false] ]; [TestCaseSource(nameof(test_cases))] From bf5640049a73e2eb01c5cc02814aaea43d7c00e5 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 20 Mar 2024 17:31:31 +0900 Subject: [PATCH 851/915] Fix banana showers causing fails when hp is at 0 --- osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs index 2f55f9a85f..b2509091fe 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchHealthProcessor.cs @@ -32,6 +32,10 @@ namespace osu.Game.Rulesets.Catch.Scoring if (result.Type == HitResult.SmallTickMiss) return false; + // on stable, banana showers don't exist as concrete objects themselves, so they can't cause a fail. + if (result.HitObject is BananaShower) + return false; + return base.CheckDefaultFailCondition(result); } From 4904c49c38b418f3a151c34c114be96983bb03b7 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Wed, 20 Mar 2024 09:31:58 -0300 Subject: [PATCH 852/915] Add abnormal difficulty settings checks --- .../CheckAbnormalDifficultySettingsTest.cs | 93 +++++++++++++++++++ osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 5 +- .../Checks/CheckAbnormalDifficultySettings.cs | 82 ++++++++++++++++ 3 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Editing/Checks/CheckAbnormalDifficultySettingsTest.cs create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs diff --git a/osu.Game.Tests/Editing/Checks/CheckAbnormalDifficultySettingsTest.cs b/osu.Game.Tests/Editing/Checks/CheckAbnormalDifficultySettingsTest.cs new file mode 100644 index 0000000000..94305755c4 --- /dev/null +++ b/osu.Game.Tests/Editing/Checks/CheckAbnormalDifficultySettingsTest.cs @@ -0,0 +1,93 @@ +// 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.Rulesets.Edit.Checks; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Edit; +using osu.Game.Tests.Beatmaps; +using System.Linq; + +namespace osu.Game.Tests.Editing.Checks +{ + [TestFixture] + public class CheckAbnormalDifficultySettingsTest + { + private CheckAbnormalDifficultySettings check = null!; + + private IBeatmap beatmap = new Beatmap(); + + [SetUp] + public void Setup() + { + check = new CheckAbnormalDifficultySettings(); + beatmap.Difficulty = new(); + } + + [Test] + public void TestSettingsNormal() + { + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + [Test] + public void TestAllSettingsMoreThanOneDecimal() + { + beatmap.Difficulty = new() + { + ApproachRate = 5.55f, + OverallDifficulty = 7.7777f, + CircleSize = 4.444f, + DrainRate = 1.1111111111f, + }; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(4)); + } + + [Test] + public void TestAllSettingsLessThanZero() + { + beatmap.Difficulty = new() + { + ApproachRate = -1, + OverallDifficulty = -20, + CircleSize = -11, + DrainRate = -34, + }; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(4)); + } + + [Test] + public void TestAllSettingsHigherThanTen() + { + beatmap.Difficulty = new() + { + ApproachRate = 14, + OverallDifficulty = 24, + CircleSize = 30, + DrainRate = 90, + }; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(4)); + } + + private BeatmapVerifierContext getContext() + { + return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + } + } +} diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index dcf5eb4da9..edabe941b7 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -41,7 +41,10 @@ namespace osu.Game.Rulesets.Edit new CheckPreviewTime(), // Events - new CheckBreaks() + new CheckBreaks(), + + // Settings + new CheckAbnormalDifficultySettings(), }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs new file mode 100644 index 0000000000..73049b323d --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs @@ -0,0 +1,82 @@ +// 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 osu.Game.Rulesets.Edit.Checks.Components; + + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckAbnormalDifficultySettings : ICheck + { + public CheckMetadata Metadata => new CheckMetadata(CheckCategory.Settings, "Abnormal difficulty settings"); + + public IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateMoreThanOneDecimal(this), + new IssueTemplateOutOfRange(this), + }; + + public IEnumerable Run(BeatmapVerifierContext context) + { + var diff = context.Beatmap.Difficulty; + + if (hasMoreThanOneDecimalPlace(diff.ApproachRate)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Approach rate", diff.ApproachRate); + + if (isOutOfRange(diff.ApproachRate)) + yield return new IssueTemplateOutOfRange(this).Create("Approach rate", diff.ApproachRate); + + + if (hasMoreThanOneDecimalPlace(diff.OverallDifficulty)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); + + if (isOutOfRange(diff.OverallDifficulty)) + yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); + + + if (hasMoreThanOneDecimalPlace(diff.CircleSize)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Circle size", diff.CircleSize); + + if (isOutOfRange(diff.CircleSize)) + yield return new IssueTemplateOutOfRange(this).Create("Circle size", diff.CircleSize); + + + if (hasMoreThanOneDecimalPlace(diff.DrainRate)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + + if (isOutOfRange(diff.DrainRate)) + yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); + } + + private bool isOutOfRange(float setting) + { + return setting < 0f || setting > 10f; + } + + private bool hasMoreThanOneDecimalPlace(float setting) + { + return float.Round(setting, 1) != setting; + } + + public class IssueTemplateMoreThanOneDecimal : IssueTemplate + { + public IssueTemplateMoreThanOneDecimal(ICheck check) + : base(check, IssueType.Problem, "{0} {1} has more than one decimal place.") + { + } + + public Issue Create(string settingName, float settingValue) => new Issue(this, settingName, settingValue); + } + + public class IssueTemplateOutOfRange : IssueTemplate + { + public IssueTemplateOutOfRange(ICheck check) + : base(check, IssueType.Warning, "{0} is {1} although it is capped between 0 to 10 in-game.") + { + } + + public Issue Create(string settingName, float settingValue) => new Issue(this, settingName, settingValue); + } + } +} From ac7fca10d63e3f92db65572ea77ae0ab4bb58df6 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 21 Mar 2024 00:47:37 +0900 Subject: [PATCH 853/915] Warn about not using an official "deployed" build --- osu.Game/Localisation/NotificationsStrings.cs | 5 +++++ osu.Game/Updater/UpdateManager.cs | 6 ++++++ osu.Game/Utils/OfficialBuildAttribute.cs | 12 ++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 osu.Game/Utils/OfficialBuildAttribute.cs diff --git a/osu.Game/Localisation/NotificationsStrings.cs b/osu.Game/Localisation/NotificationsStrings.cs index f4965e4ebe..5328bcd066 100644 --- a/osu.Game/Localisation/NotificationsStrings.cs +++ b/osu.Game/Localisation/NotificationsStrings.cs @@ -125,6 +125,11 @@ Click to see what's new!", version); /// public static LocalisableString UpdateReadyToInstall => new TranslatableString(getKey(@"update_ready_to_install"), @"Update ready to install. Click to restart!"); + /// + /// "This is not an official build of the game and scores will not be submitted." + /// + public static LocalisableString NotOfficialBuild => new TranslatableString(getKey(@"not_official_build"), @"This is not an official build of the game and scores will not be submitted."); + /// /// "Downloading update..." /// diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs index 8f13e0f42a..bcb28d8b14 100644 --- a/osu.Game/Updater/UpdateManager.cs +++ b/osu.Game/Updater/UpdateManager.cs @@ -1,7 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Reflection; using System.Threading.Tasks; +using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -11,6 +13,7 @@ using osu.Game.Graphics; using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; +using osu.Game.Utils; using osuTK; namespace osu.Game.Updater @@ -51,6 +54,9 @@ namespace osu.Game.Updater // only show a notification if we've previously saved a version to the config file (ie. not the first run). if (!string.IsNullOrEmpty(lastVersion)) Notifications.Post(new UpdateCompleteNotification(version)); + + if (RuntimeInfo.EntryAssembly.GetCustomAttribute() == null) + Notifications.Post(new SimpleNotification { Text = NotificationsStrings.NotOfficialBuild }); } // debug / local compilations will reset to a non-release string. diff --git a/osu.Game/Utils/OfficialBuildAttribute.cs b/osu.Game/Utils/OfficialBuildAttribute.cs new file mode 100644 index 0000000000..66c1ef5591 --- /dev/null +++ b/osu.Game/Utils/OfficialBuildAttribute.cs @@ -0,0 +1,12 @@ +// 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 JetBrains.Annotations; + +namespace osu.Game.Utils +{ + [UsedImplicitly] + [AttributeUsage(AttributeTargets.Assembly)] + public class OfficialBuildAttribute : Attribute; +} From c605e463a41388f43a0493d1246a813f1f7d4ab1 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Wed, 20 Mar 2024 15:52:16 -0300 Subject: [PATCH 854/915] Add mania keycount check --- .../Editor/Checks/CheckKeyCountTest.cs | 75 +++++++++++++++++++ .../Edit/Checks/CheckKeyCount.cs | 55 ++++++++++++++ .../Edit/ManiaBeatmapVerifier.cs | 24 ++++++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 + .../Checks/CheckAbnormalDifficultySettings.cs | 4 +- 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/Checks/CheckKeyCount.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaBeatmapVerifier.cs diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs new file mode 100644 index 0000000000..91361e2a62 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects; +using osu.Game.Tests.Beatmaps; +using osu.Game.Rulesets.Mania.Edit.Checks; +using System.Linq; + +namespace osu.Game.Rulesets.Mania.Tests.Editor.Checks +{ + [TestFixture] + public class CheckKeyCountTest + { + private CheckKeyCount check = null!; + + private IBeatmap beatmap = null!; + + [SetUp] + public void Setup() + { + check = new CheckKeyCount(); + + beatmap = new Beatmap() + { + BeatmapInfo = new BeatmapInfo + { + Ruleset = new ManiaRuleset().RulesetInfo + } + }; + } + + [Test] + public void TestKeycountFour() + { + beatmap.Difficulty.CircleSize = 4; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + [Test] + public void TestKeycountSmallerThanFour() + { + beatmap.Difficulty.CircleSize = 1; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckKeyCount.IssueTemplateKeycountTooLow); + } + + [Test] + public void TestKeycountHigherThanTen() + { + beatmap.Difficulty.CircleSize = 11; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckKeyCount.IssueTemplateKeycountNonStandard); + } + + private BeatmapVerifierContext getContext() + { + return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Checks/CheckKeyCount.cs b/osu.Game.Rulesets.Mania/Edit/Checks/CheckKeyCount.cs new file mode 100644 index 0000000000..57991bd3ff --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Checks/CheckKeyCount.cs @@ -0,0 +1,55 @@ +// 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 osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Mania.Edit.Checks +{ + public class CheckKeyCount : ICheck + { + public CheckMetadata Metadata => new CheckMetadata(CheckCategory.Settings, "Check mania keycount."); + + public IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateKeycountTooLow(this), + new IssueTemplateKeycountNonStandard(this), + }; + + public IEnumerable Run(BeatmapVerifierContext context) + { + var diff = context.Beatmap.Difficulty; + + if (diff.CircleSize < 4) + { + yield return new IssueTemplateKeycountTooLow(this).Create(diff.CircleSize); + } + + if (diff.CircleSize > 10) + { + yield return new IssueTemplateKeycountNonStandard(this).Create(diff.CircleSize); + } + } + + public class IssueTemplateKeycountTooLow : IssueTemplate + { + public IssueTemplateKeycountTooLow(ICheck check) + : base(check, IssueType.Problem, "Key count is {0} and must be 4 or higher.") + { + } + + public Issue Create(float current) => new Issue(this, current); + } + + public class IssueTemplateKeycountNonStandard : IssueTemplate + { + public IssueTemplateKeycountNonStandard(ICheck check) + : base(check, IssueType.Warning, "Key count {0} is higher than 10.") + { + } + + public Issue Create(float current) => new Issue(this, current); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatmapVerifier.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatmapVerifier.cs new file mode 100644 index 0000000000..778dcfc6e1 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatmapVerifier.cs @@ -0,0 +1,24 @@ +// 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.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks.Components; +using osu.Game.Rulesets.Mania.Edit.Checks; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaBeatmapVerifier : IBeatmapVerifier + { + private readonly List checks = new List + { + new CheckKeyCount(), + }; + + public IEnumerable Run(BeatmapVerifierContext context) + { + return checks.SelectMany(check => check.Run(context)); + } + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 0b54fb3da0..3d4803f1e4 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -65,6 +65,8 @@ namespace osu.Game.Rulesets.Mania public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); + public override IBeatmapVerifier CreateBeatmapVerifier() => new ManiaBeatmapVerifier(); + public override ISkin? CreateSkinTransformer(ISkin skin, IBeatmap beatmap) { switch (skin) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs index 73049b323d..3c454a57fe 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using osu.Game.Rulesets.Edit.Checks.Components; - namespace osu.Game.Rulesets.Edit.Checks { public class CheckAbnormalDifficultySettings : ICheck @@ -20,6 +19,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { var diff = context.Beatmap.Difficulty; + string ruleset = context.Beatmap.BeatmapInfo.Ruleset.ShortName; if (hasMoreThanOneDecimalPlace(diff.ApproachRate)) yield return new IssueTemplateMoreThanOneDecimal(this).Create("Approach rate", diff.ApproachRate); @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Edit.Checks if (hasMoreThanOneDecimalPlace(diff.CircleSize)) yield return new IssueTemplateMoreThanOneDecimal(this).Create("Circle size", diff.CircleSize); - if (isOutOfRange(diff.CircleSize)) + if (ruleset != "mania" && isOutOfRange(diff.CircleSize)) yield return new IssueTemplateOutOfRange(this).Create("Circle size", diff.CircleSize); From 2d6a3b8e2b5e3f0023957868a0706f5df162e110 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Wed, 20 Mar 2024 16:51:27 -0300 Subject: [PATCH 855/915] Remove warning for 10K+ --- .../Editor/Checks/CheckKeyCountTest.cs | 12 ------------ .../Edit/Checks/CheckKeyCount.cs | 16 ---------------- 2 files changed, 28 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs index 91361e2a62..564c611548 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs @@ -55,18 +55,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor.Checks Assert.That(issues.Single().Template is CheckKeyCount.IssueTemplateKeycountTooLow); } - [Test] - public void TestKeycountHigherThanTen() - { - beatmap.Difficulty.CircleSize = 11; - - var context = getContext(); - var issues = check.Run(context).ToList(); - - Assert.That(issues, Has.Count.EqualTo(1)); - Assert.That(issues.Single().Template is CheckKeyCount.IssueTemplateKeycountNonStandard); - } - private BeatmapVerifierContext getContext() { return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); diff --git a/osu.Game.Rulesets.Mania/Edit/Checks/CheckKeyCount.cs b/osu.Game.Rulesets.Mania/Edit/Checks/CheckKeyCount.cs index 57991bd3ff..51ead5f423 100644 --- a/osu.Game.Rulesets.Mania/Edit/Checks/CheckKeyCount.cs +++ b/osu.Game.Rulesets.Mania/Edit/Checks/CheckKeyCount.cs @@ -14,7 +14,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Checks public IEnumerable PossibleTemplates => new IssueTemplate[] { new IssueTemplateKeycountTooLow(this), - new IssueTemplateKeycountNonStandard(this), }; public IEnumerable Run(BeatmapVerifierContext context) @@ -25,11 +24,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Checks { yield return new IssueTemplateKeycountTooLow(this).Create(diff.CircleSize); } - - if (diff.CircleSize > 10) - { - yield return new IssueTemplateKeycountNonStandard(this).Create(diff.CircleSize); - } } public class IssueTemplateKeycountTooLow : IssueTemplate @@ -41,15 +35,5 @@ namespace osu.Game.Rulesets.Mania.Edit.Checks public Issue Create(float current) => new Issue(this, current); } - - public class IssueTemplateKeycountNonStandard : IssueTemplate - { - public IssueTemplateKeycountNonStandard(ICheck check) - : base(check, IssueType.Warning, "Key count {0} is higher than 10.") - { - } - - public Issue Create(float current) => new Issue(this, current); - } } } From b132734f9c429da05b976544b266528c765019e6 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Wed, 20 Mar 2024 18:54:38 -0300 Subject: [PATCH 856/915] Fix codefactor issues --- .../Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs index 3c454a57fe..db154f4efc 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs @@ -27,21 +27,18 @@ namespace osu.Game.Rulesets.Edit.Checks if (isOutOfRange(diff.ApproachRate)) yield return new IssueTemplateOutOfRange(this).Create("Approach rate", diff.ApproachRate); - if (hasMoreThanOneDecimalPlace(diff.OverallDifficulty)) yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); if (isOutOfRange(diff.OverallDifficulty)) yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); - if (hasMoreThanOneDecimalPlace(diff.CircleSize)) yield return new IssueTemplateMoreThanOneDecimal(this).Create("Circle size", diff.CircleSize); if (ruleset != "mania" && isOutOfRange(diff.CircleSize)) yield return new IssueTemplateOutOfRange(this).Create("Circle size", diff.CircleSize); - if (hasMoreThanOneDecimalPlace(diff.DrainRate)) yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); From a07d5115bfef749e2b766a554ceb420c82206dd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Mar 2024 11:42:22 +0800 Subject: [PATCH 857/915] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index de7497d58e..0e091dbd37 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ - + From 55d66d4615e65bdbcc794d385da3210aa130d7cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Mar 2024 11:45:46 +0800 Subject: [PATCH 858/915] Add sounds to countdown --- osu.Game/Screens/Play/DelayedResumeOverlay.cs | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/DelayedResumeOverlay.cs b/osu.Game/Screens/Play/DelayedResumeOverlay.cs index 8bb3ae8182..147d48ae02 100644 --- a/osu.Game/Screens/Play/DelayedResumeOverlay.cs +++ b/osu.Game/Screens/Play/DelayedResumeOverlay.cs @@ -3,6 +3,8 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -47,6 +49,8 @@ namespace osu.Game.Screens.Play private SpriteText countdownText = null!; private CircularProgress countdownProgress = null!; + private Sample? sampleCountdown; + public DelayedResumeOverlay() { Anchor = Anchor.Centre; @@ -54,7 +58,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { Add(outerContent = new Circle { @@ -103,6 +107,8 @@ namespace osu.Game.Screens.Play } } }); + + sampleCountdown = audio.Samples.Get(@"Gameplay/resume-countdown"); } protected override void PopIn() @@ -164,13 +170,24 @@ namespace osu.Game.Screens.Play countdownProgress.Progress = amountTimePassed; countdownProgress.InnerRadius = progress_stroke_width / progress_size / countdownProgress.Scale.X; - if (countdownCount != newCount && newCount > 0) + if (countdownCount != newCount) { - countdownText.Text = Math.Max(1, newCount).ToString(); - countdownText.ScaleTo(0.25f).Then().ScaleTo(1, 200, Easing.OutQuint); - outerContent.Delay(25).Then().ScaleTo(1.05f, 100).Then().ScaleTo(1f, 200, Easing.Out); + if (newCount > 0) + { + countdownText.Text = Math.Max(1, newCount).ToString(); + countdownText.ScaleTo(0.25f).Then().ScaleTo(1, 200, Easing.OutQuint); + outerContent.Delay(25).Then().ScaleTo(1.05f, 100).Then().ScaleTo(1f, 200, Easing.Out); - countdownBackground.FlashColour(colourProvider.Background3, 400, Easing.Out); + countdownBackground.FlashColour(colourProvider.Background3, 400, Easing.Out); + } + + var chan = sampleCountdown?.GetChannel(); + + if (chan != null) + { + chan.Frequency.Value = newCount == 0 ? 0.5f : 1; + chan.Play(); + } } countdownCount = newCount; From b99b0337cffd33519b1323adbda98cb13b395f63 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Mar 2024 13:06:25 +0800 Subject: [PATCH 859/915] Adjust text slightly --- osu.Game/Localisation/NotificationsStrings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/NotificationsStrings.cs b/osu.Game/Localisation/NotificationsStrings.cs index 5328bcd066..3188ca5533 100644 --- a/osu.Game/Localisation/NotificationsStrings.cs +++ b/osu.Game/Localisation/NotificationsStrings.cs @@ -126,9 +126,9 @@ Click to see what's new!", version); public static LocalisableString UpdateReadyToInstall => new TranslatableString(getKey(@"update_ready_to_install"), @"Update ready to install. Click to restart!"); /// - /// "This is not an official build of the game and scores will not be submitted." + /// "This is not an official build of the game. Scores will not be submitted and other online systems may not work as intended." /// - public static LocalisableString NotOfficialBuild => new TranslatableString(getKey(@"not_official_build"), @"This is not an official build of the game and scores will not be submitted."); + public static LocalisableString NotOfficialBuild => new TranslatableString(getKey(@"not_official_build"), @"This is not an official build of the game. Scores will not be submitted and other online systems may not work as intended."); /// /// "Downloading update..." From a4822fd615ef983be0399182f98159fc8546e427 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Fri, 22 Mar 2024 01:37:06 -0300 Subject: [PATCH 860/915] Make `CheckAbnormalDifficultySettings` abstract --- .../CheckAbnormalDifficultySettingsTest.cs | 93 ------------------- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 3 - .../Checks/CheckAbnormalDifficultySettings.cs | 41 ++------ 3 files changed, 8 insertions(+), 129 deletions(-) delete mode 100644 osu.Game.Tests/Editing/Checks/CheckAbnormalDifficultySettingsTest.cs diff --git a/osu.Game.Tests/Editing/Checks/CheckAbnormalDifficultySettingsTest.cs b/osu.Game.Tests/Editing/Checks/CheckAbnormalDifficultySettingsTest.cs deleted file mode 100644 index 94305755c4..0000000000 --- a/osu.Game.Tests/Editing/Checks/CheckAbnormalDifficultySettingsTest.cs +++ /dev/null @@ -1,93 +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 osu.Game.Rulesets.Edit.Checks; -using NUnit.Framework; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Edit; -using osu.Game.Tests.Beatmaps; -using System.Linq; - -namespace osu.Game.Tests.Editing.Checks -{ - [TestFixture] - public class CheckAbnormalDifficultySettingsTest - { - private CheckAbnormalDifficultySettings check = null!; - - private IBeatmap beatmap = new Beatmap(); - - [SetUp] - public void Setup() - { - check = new CheckAbnormalDifficultySettings(); - beatmap.Difficulty = new(); - } - - [Test] - public void TestSettingsNormal() - { - var context = getContext(); - var issues = check.Run(context).ToList(); - - Assert.That(issues, Has.Count.EqualTo(0)); - } - - [Test] - public void TestAllSettingsMoreThanOneDecimal() - { - beatmap.Difficulty = new() - { - ApproachRate = 5.55f, - OverallDifficulty = 7.7777f, - CircleSize = 4.444f, - DrainRate = 1.1111111111f, - }; - - var context = getContext(); - var issues = check.Run(context).ToList(); - - Assert.That(issues, Has.Count.EqualTo(4)); - } - - [Test] - public void TestAllSettingsLessThanZero() - { - beatmap.Difficulty = new() - { - ApproachRate = -1, - OverallDifficulty = -20, - CircleSize = -11, - DrainRate = -34, - }; - - var context = getContext(); - var issues = check.Run(context).ToList(); - - Assert.That(issues, Has.Count.EqualTo(4)); - } - - [Test] - public void TestAllSettingsHigherThanTen() - { - beatmap.Difficulty = new() - { - ApproachRate = 14, - OverallDifficulty = 24, - CircleSize = 30, - DrainRate = 90, - }; - - var context = getContext(); - var issues = check.Run(context).ToList(); - - Assert.That(issues, Has.Count.EqualTo(4)); - } - - private BeatmapVerifierContext getContext() - { - return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); - } - } -} diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index edabe941b7..2eb52e88c7 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -42,9 +42,6 @@ namespace osu.Game.Rulesets.Edit // Events new CheckBreaks(), - - // Settings - new CheckAbnormalDifficultySettings(), }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs index db154f4efc..93592a866b 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs @@ -6,9 +6,9 @@ using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Rulesets.Edit.Checks { - public class CheckAbnormalDifficultySettings : ICheck + public abstract class CheckAbnormalDifficultySettings : ICheck { - public CheckMetadata Metadata => new CheckMetadata(CheckCategory.Settings, "Abnormal difficulty settings"); + public abstract CheckMetadata Metadata { get; } public IEnumerable PossibleTemplates => new IssueTemplate[] { @@ -16,42 +16,17 @@ namespace osu.Game.Rulesets.Edit.Checks new IssueTemplateOutOfRange(this), }; - public IEnumerable Run(BeatmapVerifierContext context) - { - var diff = context.Beatmap.Difficulty; - string ruleset = context.Beatmap.BeatmapInfo.Ruleset.ShortName; + public abstract IEnumerable Run(BeatmapVerifierContext context); - if (hasMoreThanOneDecimalPlace(diff.ApproachRate)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Approach rate", diff.ApproachRate); - - if (isOutOfRange(diff.ApproachRate)) - yield return new IssueTemplateOutOfRange(this).Create("Approach rate", diff.ApproachRate); - - if (hasMoreThanOneDecimalPlace(diff.OverallDifficulty)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); - - if (isOutOfRange(diff.OverallDifficulty)) - yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); - - if (hasMoreThanOneDecimalPlace(diff.CircleSize)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Circle size", diff.CircleSize); - - if (ruleset != "mania" && isOutOfRange(diff.CircleSize)) - yield return new IssueTemplateOutOfRange(this).Create("Circle size", diff.CircleSize); - - if (hasMoreThanOneDecimalPlace(diff.DrainRate)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); - - if (isOutOfRange(diff.DrainRate)) - yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); - } - - private bool isOutOfRange(float setting) + /// + /// If the setting is out of the boundaries set by the editor (0 - 10) + /// + protected bool OutOfRange(float setting) { return setting < 0f || setting > 10f; } - private bool hasMoreThanOneDecimalPlace(float setting) + protected bool HasMoreThanOneDecimalPlace(float setting) { return float.Round(setting, 1) != setting; } From e2df0981843c3428fa11a232d341d97ac3e0505f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 22 Mar 2024 08:25:03 +0100 Subject: [PATCH 861/915] Add failing test case for desired artist sort behaviour --- .../SongSelect/TestSceneBeatmapCarousel.cs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index de2ae3708f..c0102b238c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -666,6 +666,56 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert($"Check {zzz_lowercase} is second last", () => carousel.BeatmapSets.SkipLast(1).Last().Metadata.Artist == zzz_lowercase); } + [Test] + public void TestSortByArtistUsesTitleAsTiebreaker() + { + var sets = new List(); + + AddStep("Populuate beatmap sets", () => + { + sets.Clear(); + + for (int i = 0; i < 20; i++) + { + var set = TestResources.CreateTestBeatmapSetInfo(); + + if (i == 4) + { + set.Beatmaps.ForEach(b => + { + b.Metadata.Artist = "ZZZ"; + b.Metadata.Title = "AAA"; + }); + } + + if (i == 8) + { + set.Beatmaps.ForEach(b => + { + b.Metadata.Artist = "ZZZ"; + b.Metadata.Title = "ZZZ"; + }); + } + + sets.Add(set); + } + }); + + loadBeatmaps(sets); + + AddStep("Sort by artist", () => carousel.Filter(new FilterCriteria { Sort = SortMode.Artist }, false)); + AddAssert("Check last item", () => + { + var lastItem = carousel.BeatmapSets.Last(); + return lastItem.Metadata.Artist == "ZZZ" && lastItem.Metadata.Title == "ZZZ"; + }); + AddAssert("Check second last item", () => + { + var secondLastItem = carousel.BeatmapSets.SkipLast(1).Last(); + return secondLastItem.Metadata.Artist == "ZZZ" && secondLastItem.Metadata.Title == "AAA"; + }); + } + /// /// Ensures stability is maintained on different sort modes for items with equal properties. /// From a1880e89c299f55a8907050988b8200e854ed34b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 22 Mar 2024 08:31:59 +0100 Subject: [PATCH 862/915] Use title as tiebreaker when sorting beatmap carousel by artist Closes https://github.com/ppy/osu/issues/27548. Reference: https://github.com/peppy/osu-stable-reference/blob/e53980dd76857ee899f66ce519ba1597e7874f28/osu!/GameplayElements/Beatmaps/BeatmapTreeManager.cs#L341-L347 --- osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 43c9c621e8..7e15699804 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -69,6 +69,8 @@ namespace osu.Game.Screens.Select.Carousel default: case SortMode.Artist: comparison = OrdinalSortByCaseStringComparer.DEFAULT.Compare(BeatmapSet.Metadata.Artist, otherSet.BeatmapSet.Metadata.Artist); + if (comparison == 0) + goto case SortMode.Title; break; case SortMode.Title: From 6fa663c8cac732c6d705955f52565f1f78b7eddd Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Fri, 22 Mar 2024 14:48:22 -0300 Subject: [PATCH 863/915] Make check ruleset specific --- ...heckCatchAbnormalDifficultySettingsTest.cs | 158 ++++++++++++++ .../Edit/CatchBeatmapVerifier.cs | 3 +- .../CheckCatchAbnormalDifficultySettings.cs | 38 ++++ ...heckManiaAbnormalDifficultySettingsTest.cs | 121 +++++++++++ .../CheckManiaAbnormalDifficultySettings.cs | 32 +++ .../Edit/ManiaBeatmapVerifier.cs | 2 + .../CheckOsuAbnormalDifficultySettingsTest.cs | 194 ++++++++++++++++++ .../CheckOsuAbnormalDifficultySettings.cs | 43 ++++ .../Edit/OsuBeatmapVerifier.cs | 3 + ...heckTaikoAbnormalDifficultySettingsTest.cs | 84 ++++++++ .../CheckTaikoAbnormalDifficultySettings.cs | 26 +++ .../Edit/TaikoBeatmapVerifier.cs | 24 +++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 + 13 files changed, 729 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Catch.Tests/Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs create mode 100644 osu.Game.Rulesets.Catch/Edit/Checks/CheckCatchAbnormalDifficultySettings.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/Checks/CheckManiaAbnormalDifficultySettings.cs create mode 100644 osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs create mode 100644 osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs create mode 100644 osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs create mode 100644 osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs create mode 100644 osu.Game.Rulesets.Taiko/Edit/TaikoBeatmapVerifier.cs diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Catch.Tests/Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs new file mode 100644 index 0000000000..2ae2e20215 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs @@ -0,0 +1,158 @@ +// 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.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Edit.Checks; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Objects; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Catch.Tests.Editor.Checks +{ + [TestFixture] + public class CheckCatchAbnormalDifficultySettingsTest + { + private CheckCatchAbnormalDifficultySettings check = null!; + + private IBeatmap beatmap = new Beatmap(); + + [SetUp] + public void Setup() + { + check = new CheckCatchAbnormalDifficultySettings(); + + beatmap.BeatmapInfo.Ruleset = new CatchRuleset().RulesetInfo; + beatmap.Difficulty = new BeatmapDifficulty() + { + ApproachRate = 5, + CircleSize = 5, + DrainRate = 5, + }; + } + + [Test] + public void TestNormalSettings() + { + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + [Test] + public void TestApproachRateTwoDecimals() + { + beatmap.Difficulty.ApproachRate = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestCircleSizeTwoDecimals() + { + beatmap.Difficulty.CircleSize = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestDrainRateTwoDecimals() + { + beatmap.Difficulty.DrainRate = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestApproachRateUnder() + { + beatmap.Difficulty.ApproachRate = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestCircleSizeUnder() + { + beatmap.Difficulty.CircleSize = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestDrainRateUnder() + { + beatmap.Difficulty.DrainRate = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestApproachRateOver() + { + beatmap.Difficulty.ApproachRate = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestCircleSizeOver() + { + beatmap.Difficulty.CircleSize = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestDrainRateOver() + { + beatmap.Difficulty.DrainRate = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + private BeatmapVerifierContext getContext() + { + return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs b/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs index c7a41a4e22..71da6d5014 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs @@ -13,7 +13,8 @@ namespace osu.Game.Rulesets.Catch.Edit { private readonly List checks = new List { - new CheckBananaShowerGap() + new CheckBananaShowerGap(), + new CheckCatchAbnormalDifficultySettings(), }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game.Rulesets.Catch/Edit/Checks/CheckCatchAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Catch/Edit/Checks/CheckCatchAbnormalDifficultySettings.cs new file mode 100644 index 0000000000..8295795f00 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Edit/Checks/CheckCatchAbnormalDifficultySettings.cs @@ -0,0 +1,38 @@ +// 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 osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Catch.Edit.Checks +{ + public class CheckCatchAbnormalDifficultySettings : CheckAbnormalDifficultySettings + { + public override CheckMetadata Metadata => new CheckMetadata(CheckCategory.Settings, "Checks catch relevant settings"); + + public override IEnumerable Run(BeatmapVerifierContext context) + { + var diff = context.Beatmap.Difficulty; + + if (HasMoreThanOneDecimalPlace(diff.ApproachRate)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Approach rate", diff.ApproachRate); + + if (OutOfRange(diff.ApproachRate)) + yield return new IssueTemplateOutOfRange(this).Create("Approach rate", diff.ApproachRate); + + if (HasMoreThanOneDecimalPlace(diff.CircleSize)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Circle size", diff.CircleSize); + + if (OutOfRange(diff.CircleSize)) + yield return new IssueTemplateOutOfRange(this).Create("Circle size", diff.CircleSize); + + if (HasMoreThanOneDecimalPlace(diff.DrainRate)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + + if (OutOfRange(diff.DrainRate)) + yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); + } + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs new file mode 100644 index 0000000000..6c585aace3 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs @@ -0,0 +1,121 @@ +// 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.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Edit.Checks; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Objects; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Mania.Tests.Editor.Checks +{ + [TestFixture] + public class CheckManiaAbnormalDifficultySettingsTest + { + private CheckManiaAbnormalDifficultySettings check = null!; + + private IBeatmap beatmap = new Beatmap(); + + [SetUp] + public void Setup() + { + check = new CheckManiaAbnormalDifficultySettings(); + + beatmap.BeatmapInfo.Ruleset = new ManiaRuleset().RulesetInfo; + beatmap.Difficulty = new BeatmapDifficulty() + { + OverallDifficulty = 5, + DrainRate = 5, + }; + } + + [Test] + public void TestNormalSettings() + { + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + [Test] + public void TestOverallDifficultyTwoDecimals() + { + beatmap.Difficulty.OverallDifficulty = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestDrainRateTwoDecimals() + { + beatmap.Difficulty.DrainRate = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestOverallDifficultyUnder() + { + beatmap.Difficulty.OverallDifficulty = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestDrainRateUnder() + { + beatmap.Difficulty.DrainRate = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestOverallDifficultyOver() + { + beatmap.Difficulty.OverallDifficulty = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestDrainRateOver() + { + beatmap.Difficulty.DrainRate = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + private BeatmapVerifierContext getContext() + { + return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Checks/CheckManiaAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Mania/Edit/Checks/CheckManiaAbnormalDifficultySettings.cs new file mode 100644 index 0000000000..ae0cc3aa4c --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Checks/CheckManiaAbnormalDifficultySettings.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.Collections.Generic; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Mania.Edit.Checks +{ + public class CheckManiaAbnormalDifficultySettings : CheckAbnormalDifficultySettings + { + public override CheckMetadata Metadata => new CheckMetadata(CheckCategory.Settings, "Checks mania relevant settings"); + + public override IEnumerable Run(BeatmapVerifierContext context) + { + var diff = context.Beatmap.Difficulty; + + if (HasMoreThanOneDecimalPlace(diff.OverallDifficulty)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); + + if (OutOfRange(diff.OverallDifficulty)) + yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); + + if (HasMoreThanOneDecimalPlace(diff.DrainRate)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + + if (OutOfRange(diff.DrainRate)) + yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatmapVerifier.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatmapVerifier.cs index 778dcfc6e1..4adabfa4d7 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatmapVerifier.cs @@ -13,7 +13,9 @@ namespace osu.Game.Rulesets.Mania.Edit { private readonly List checks = new List { + // Settings new CheckKeyCount(), + new CheckManiaAbnormalDifficultySettings(), }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs new file mode 100644 index 0000000000..53ccd3c7a7 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs @@ -0,0 +1,194 @@ +// 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.Rulesets.Osu.Edit.Checks; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Edit; +using osu.Game.Tests.Beatmaps; +using System.Linq; + +namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks +{ + [TestFixture] + public class CheckOsuAbnormalDifficultySettingsTest + { + private CheckOsuAbnormalDifficultySettings check = null!; + + private IBeatmap beatmap = new Beatmap(); + + [SetUp] + public void Setup() + { + check = new CheckOsuAbnormalDifficultySettings(); + + beatmap.Difficulty = new BeatmapDifficulty() + { + ApproachRate = 5, + CircleSize = 5, + DrainRate = 5, + OverallDifficulty = 5, + }; + } + + [Test] + public void TestNormalSettings() + { + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + [Test] + public void TestApproachRateTwoDecimals() + { + beatmap.Difficulty.ApproachRate = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestCircleSizeTwoDecimals() + { + beatmap.Difficulty.CircleSize = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestDrainRateTwoDecimals() + { + beatmap.Difficulty.DrainRate = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestOverallDifficultyTwoDecimals() + { + beatmap.Difficulty.OverallDifficulty = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestApproachRateUnder() + { + beatmap.Difficulty.ApproachRate = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestCircleSizeUnder() + { + beatmap.Difficulty.CircleSize = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestDrainRateUnder() + { + beatmap.Difficulty.DrainRate = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestOverallDifficultyUnder() + { + beatmap.Difficulty.OverallDifficulty = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestApproachRateOver() + { + beatmap.Difficulty.ApproachRate = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestCircleSizeOver() + { + beatmap.Difficulty.CircleSize = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestDrainRateOver() + { + beatmap.Difficulty.DrainRate = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestOverallDifficultyOver() + { + beatmap.Difficulty.OverallDifficulty = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + private BeatmapVerifierContext getContext() + { + return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs new file mode 100644 index 0000000000..c1eca7fff7 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs @@ -0,0 +1,43 @@ +// 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 osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Osu.Edit.Checks +{ + public class CheckOsuAbnormalDifficultySettings : CheckAbnormalDifficultySettings + { + public override CheckMetadata Metadata => new CheckMetadata(CheckCategory.Settings, "Checks osu relevant settings"); + public override IEnumerable Run(BeatmapVerifierContext context) + { + var diff = context.Beatmap.Difficulty; + + if (HasMoreThanOneDecimalPlace(diff.ApproachRate)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Approach rate", diff.ApproachRate); + + if (OutOfRange(diff.ApproachRate)) + yield return new IssueTemplateOutOfRange(this).Create("Approach rate", diff.ApproachRate); + + if (HasMoreThanOneDecimalPlace(diff.OverallDifficulty)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); + + if (OutOfRange(diff.OverallDifficulty)) + yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); + + if (HasMoreThanOneDecimalPlace(diff.CircleSize)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Circle size", diff.CircleSize); + + if (OutOfRange(diff.CircleSize)) + yield return new IssueTemplateOutOfRange(this).Create("Circle size", diff.CircleSize); + + if (HasMoreThanOneDecimalPlace(diff.DrainRate)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + + if (OutOfRange(diff.DrainRate)) + yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs index 325e9ed4cb..4b01a1fc39 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs @@ -21,6 +21,9 @@ namespace osu.Game.Rulesets.Osu.Edit new CheckTimeDistanceEquality(), new CheckLowDiffOverlaps(), new CheckTooShortSliders(), + + // Settings + new CheckOsuAbnormalDifficultySettings(), }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs new file mode 100644 index 0000000000..f10e62f3bf --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.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 osu.Game.Rulesets.Taiko.Edit.Checks; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Edit; +using osu.Game.Tests.Beatmaps; +using System.Linq; + +namespace osu.Game.Rulesets.Taiko.Tests.Editor.Checks +{ + [TestFixture] + public class CheckTaikoAbnormalDifficultySettingsTest + { + private CheckTaikoAbnormalDifficultySettings check = null!; + + private IBeatmap beatmap = new Beatmap(); + + [SetUp] + public void Setup() + { + check = new CheckTaikoAbnormalDifficultySettings(); + + beatmap.BeatmapInfo.Ruleset = new TaikoRuleset().RulesetInfo; + beatmap.Difficulty = new BeatmapDifficulty() + { + OverallDifficulty = 5, + }; + } + + [Test] + public void TestNormalSettings() + { + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + [Test] + public void TestOverallDifficultyTwoDecimals() + { + beatmap.Difficulty.OverallDifficulty = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + + [Test] + public void TestOverallDifficultyUnder() + { + beatmap.Difficulty.OverallDifficulty = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestOverallDifficultyOver() + { + beatmap.Difficulty.OverallDifficulty = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + private BeatmapVerifierContext getContext() + { + return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs new file mode 100644 index 0000000000..ce35f21853 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs @@ -0,0 +1,26 @@ +// 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 osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Edit.Checks.Components; + +namespace osu.Game.Rulesets.Taiko.Edit.Checks +{ + public class CheckTaikoAbnormalDifficultySettings : CheckAbnormalDifficultySettings + { + public override CheckMetadata Metadata => new CheckMetadata(CheckCategory.Settings, "Checks taiko relevant settings"); + + public override IEnumerable Run(BeatmapVerifierContext context) + { + var diff = context.Beatmap.Difficulty; + + if (HasMoreThanOneDecimalPlace(diff.OverallDifficulty)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); + + if (OutOfRange(diff.OverallDifficulty)) + yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoBeatmapVerifier.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoBeatmapVerifier.cs new file mode 100644 index 0000000000..f5c3f1846d --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoBeatmapVerifier.cs @@ -0,0 +1,24 @@ +// 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.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks.Components; +using osu.Game.Rulesets.Taiko.Edit.Checks; + +namespace osu.Game.Rulesets.Taiko.Edit +{ + public class TaikoBeatmapVerifier : IBeatmapVerifier + { + private readonly List checks = new List + { + new CheckTaikoAbnormalDifficultySettings(), + }; + + public IEnumerable Run(BeatmapVerifierContext context) + { + return checks.SelectMany(check => check.Run(context)); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 24b0ec5d57..d7184bce60 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -188,6 +188,8 @@ namespace osu.Game.Rulesets.Taiko public override HitObjectComposer CreateHitObjectComposer() => new TaikoHitObjectComposer(this); + public override IBeatmapVerifier CreateBeatmapVerifier() => new TaikoBeatmapVerifier(); + public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new TaikoDifficultyCalculator(RulesetInfo, beatmap); public override PerformanceCalculator CreatePerformanceCalculator() => new TaikoPerformanceCalculator(); From 6fbe1a5b8d1a80c6a5b1e277ee015162b7ea8083 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Sat, 23 Mar 2024 19:22:47 -0300 Subject: [PATCH 864/915] Add video resolution check --- .../Checks/CheckVideoResolutionTest.cs | 86 +++++++++++++ .../Videos/test-video-resolution-high.mp4 | Bin 0 -> 13655 bytes osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 1 + .../Edit/Checks/CheckVideoResolution.cs | 117 ++++++++++++++++++ 4 files changed, 204 insertions(+) create mode 100644 osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs create mode 100644 osu.Game.Tests/Resources/Videos/test-video-resolution-high.mp4 create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs diff --git a/osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs b/osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs new file mode 100644 index 0000000000..ab677a15d4 --- /dev/null +++ b/osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs @@ -0,0 +1,86 @@ +using System.IO; +using System.Linq; +using Moq; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Objects; +using osu.Game.Storyboards; +using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Resources; + +namespace osu.Game.Tests.Editing.Checks +{ + [TestFixture] + public class CheckVideoResolutionTest + { + private CheckVideoResolution check = null!; + + private IBeatmap beatmap = null!; + + [SetUp] + public void Setup() + { + check = new CheckVideoResolution(); + beatmap = new Beatmap + { + BeatmapInfo = new BeatmapInfo + { + BeatmapSet = new BeatmapSetInfo + { + Files = + { + CheckTestHelpers.CreateMockFile("mp4"), + } + } + } + }; + } + + [Test] + public void TestNoVideo() + { + beatmap.BeatmapInfo.BeatmapSet?.Files.Clear(); + + var issues = check.Run(getContext(null)).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + [Test] + public void TestVideoAcceptableResolution() + { + using (var resourceStream = TestResources.OpenResource("Videos/test-video.mp4")) + { + var issues = check.Run(getContext(resourceStream)).ToList(); + Assert.That(issues, Has.Count.EqualTo(0)); + } + } + + [Test] + public void TestVideoHighResolution() + { + using (var resourceStream = TestResources.OpenResource("Videos/test-video-resolution-high.mp4")) + { + var issues = check.Run(getContext(resourceStream)).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckVideoResolution.IssueTemplateHighResolution); + } + } + + private BeatmapVerifierContext getContext(Stream? resourceStream) + { + var storyboard = new Storyboard(); + var layer = storyboard.GetLayer("Video"); + layer.Add(new StoryboardVideo("abc123.mp4", 0)); + + var mockWorkingBeatmap = new Mock(beatmap, null, null); + mockWorkingBeatmap.Setup(w => w.GetStream(It.IsAny())).Returns(resourceStream); + mockWorkingBeatmap.As().SetupGet(w => w.Storyboard).Returns(storyboard); + + return new BeatmapVerifierContext(beatmap, mockWorkingBeatmap.Object); + } + } +} diff --git a/osu.Game.Tests/Resources/Videos/test-video-resolution-high.mp4 b/osu.Game.Tests/Resources/Videos/test-video-resolution-high.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..fbdb00d3ad464a7f2d9d223d5fa9edb67fdaa689 GIT binary patch literal 13655 zcmeHNeQX>@6@PczVL*m4tPP}$L-S}hg&bg*ePO=GZEeMbb5vo#p-P>LJ4)5Ns zch`~B8a%$qmwy`2jYNdw-vopmjfC`>E|#gtJsYT8{RYT1XfIi(P|$oB0*sq zpGtgdCop3W(sEt%T;z?q;d(ye&y`r0=D_UPkB{GRO@&2S21 z&}dfEgEGsv;N9w1a+;yDHdS9Tv$+8j7L1zyp!~F#Yx%lH&CyvKmRS9q5yz17<*GYe zFKwWF+V$LELs*+*Y}1gl#EwF5+qsKNF8ok7uW)6Fy!Ny38Jjq{as2fL>sSr>ss76H3uE$U3*>WF{yW;; zS7^sF$iI3!awdDWcf;49u{YO+Uj+8=_C5X|^ksaRZv88BzT$eSg+46Z3hUPkE&d4T z1?bT2pq~)cuLpgPXkjPl+eC|&f%Zdfmx3N8TKrznZWtB?^fJ+sEudc#E!_+{3U&Pe z=xM0)I?#8Cn&Y4+iCR{H9wSK@P;qSbeTP7$?k0{x8W<{l8{ zvt~W$5K$ZE({_NU^M24Ik&Ly=uMkBupmRjAH0U%@9P^2vAnLjU^gL0`iECI}{{Z+_ zo=GI1LQF|~ttkM0=7S}mr&MI6x3achDOuZ^zPGlvPft+Du4rvtYb3|B`WW7|lC`bA zT(GuvZr<7kZT|^NTm6HArM-WerOm-LVsrgeT6UP~7=o#?l+ay`DLq9dCMH(koK+!T z)Kkx(FgroBZ>$DVJ@26{=copy5EFID92VLDn{E#8&Rf55hC9wNv|}>~h>gXFy))Yt z;ME*n!{N0Y&TK}|el~~Sz~OT^d@hH-hr@5=a3+~xKJz#nN2Q1}+Zym?VhY+XmBZI?cpHbe zb2!{uaU2});yh&zk8(KEgFtRw9KM#r6C8dEhr=8d$A{@7rYn$3=yTKD0rZd9J}~{6 zAu%$T=9cDT-{!;gFM#P^0MlO&-KdA@UkF#Ua38h@`?Kg#m=2tghTU*SIIoN0!W%yc z`W4*KX3$Z%BeAh$M+~HoECS8%R*Y8ZoV8d3r?i6y$fAx}T#+ z&3t$cC*vr#%|^2*}0oF;OLOU>ZK-H zVOmerR8LKP=XZU7I(+_g|BoJS`;ByZ*`>dX#S&doyQEr56N-{R zMSlkxbbfeq-|g*PQty_HXsPKcDmGg7xS(;Fu?DN7h zlw61940bXu9U0Fw(8jX8td(=SB~?i)YBDO}6CxQ+NSdBDEOjUu?UuV`Ny#b3xT`1S zv3R#U7LCUxQ%{bV8Oa?`lrBn7e%2^GINT(D{u|2<(&MGcr zl67>fD=ux-vx6Bg4Q7_D=Td`~joLhDqr;FsjcsjzFMW01iHl#4H$78-=&7z- z4xjYDkRrje_QmgaED5ki<63Bk!l=n^X-e2CzC5w+{s z<0>4<%Q!UP3&&p^b*3;Qfwx5h!@V%cR_`OT+jo9+>Wx=Ks94RF--nr3P~jEgQFw(I zyauYL9p1w7Qi3SIZ& z%Mf(K7%uP7rKTTw9q2M{o*u$IJTOVZS6C0xX!(fObUFh3+6;^T0SSbM0*w|PoaGr8 z*^7+GZM?OX0CtN#FS<<~4c6f5rYbqvVZ z(nW@16+U&ug<=(SORYVicoAHevAaoT#n7$^<57MaF=7Y|I1}+YI4_; zWvcsMx&r+1wrR28bqL9r)&9TvrLxR$iVManI16#X*fgu{@3ydztX$xtgRx>%1PvD# nl9krXg0TnQ0l!rC9a$sfC&QIzd5O0gqJFh2Q*qv;=F9&8=0zb8 literal 0 HcmV?d00001 diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 4a316afd22..95f79391ef 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Edit // Resources new CheckBackgroundPresence(), new CheckBackgroundQuality(), + new CheckVideoResolution(), // Audio new CheckAudioPresence(), diff --git a/osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs b/osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs new file mode 100644 index 0000000000..831962e2e9 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs @@ -0,0 +1,117 @@ +// 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.IO; +using osu.Framework.Logging; +using osu.Game.Beatmaps; +using osu.Game.IO.FileAbstraction; +using osu.Game.Rulesets.Edit.Checks.Components; +using osu.Game.Storyboards; +using TagLib; +using File = TagLib.File; + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckVideoResolution : ICheck + { + private const int max_video_width = 1280; + + private const int max_video_height = 720; + + public CheckMetadata Metadata => new CheckMetadata(CheckCategory.Resources, "Too high video resolution."); + + public IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateHighResolution(this), + new IssueTemplateFileError(this), + }; + + public IEnumerable Run(BeatmapVerifierContext context) + { + var beatmapSet = context.Beatmap.BeatmapInfo.BeatmapSet; + var videoPaths = getVideoPaths(context.WorkingBeatmap.Storyboard); + + foreach (string filename in videoPaths) + { + string? storagePath = beatmapSet?.GetPathForFile(filename); + + // Don't report any issues for missing video here since another check is already doing that (CheckAudioInVideo) + if (storagePath == null) continue; + + Issue issue; + + try + { + using (Stream data = context.WorkingBeatmap.GetStream(storagePath)) + using (File tagFile = File.Create(new StreamFileAbstraction(filename, data))) + { + int height = tagFile.Properties.VideoHeight; + int width = tagFile.Properties.VideoWidth; + + if (height <= max_video_height || width <= max_video_width) + continue; + + issue = new IssueTemplateHighResolution(this).Create(filename, width, height); + } + } + catch (CorruptFileException) + { + issue = new IssueTemplateFileError(this).Create(filename, "Corrupt file"); + } + catch (UnsupportedFormatException) + { + issue = new IssueTemplateFileError(this).Create(filename, "Unsupported format"); + } + catch (Exception ex) + { + issue = new IssueTemplateFileError(this).Create(filename, "Internal failure - see logs for more info"); + Logger.Log($"Failed when running {nameof(CheckVideoResolution)}: {ex}"); + } + + yield return issue; + } + } + + private List getVideoPaths(Storyboard storyboard) + { + var videoPaths = new List(); + + foreach (var layer in storyboard.Layers) + { + foreach (var element in layer.Elements) + { + if (element is not StoryboardVideo video) + continue; + + if (!videoPaths.Contains(video.Path)) + videoPaths.Add(video.Path); + } + } + + return videoPaths; + } + + public class IssueTemplateHighResolution : IssueTemplate + { + public IssueTemplateHighResolution(ICheck check) + : base(check, IssueType.Problem, "\"{0}\" resolution exceeds 1280x720 ({1}x{2})") + { + } + + public Issue Create(string filename, int width, int height) => new Issue(this, filename, width, height); + } + + public class IssueTemplateFileError : IssueTemplate + { + public IssueTemplateFileError(ICheck check) + : base(check, IssueType.Error, "Could not check resolution for \"{0}\" ({1}).") + { + } + + public Issue Create(string filename, string errorReason) => new Issue(this, filename, errorReason); + } + + } +} From eb938272040be14caa292fe65800356a6ae03a1a Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Sat, 23 Mar 2024 23:11:13 -0300 Subject: [PATCH 865/915] Add missing copyright header --- osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs b/osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs index ab677a15d4..1e16c67aab 100644 --- a/osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckVideoResolutionTest.cs @@ -1,3 +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.IO; using System.Linq; using Moq; From 8a05fecad5862d744d49b8febcb389e4e22b9850 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Sat, 23 Mar 2024 23:28:55 -0300 Subject: [PATCH 866/915] Fix formatting issue --- osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs b/osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs index 831962e2e9..1b603b7e47 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckVideoResolution.cs @@ -112,6 +112,5 @@ namespace osu.Game.Rulesets.Edit.Checks public Issue Create(string filename, string errorReason) => new Issue(this, filename, errorReason); } - } } From ef2a16dd8ff260efa5117a10352e6ec771dfa2c3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Mar 2024 16:41:40 +0800 Subject: [PATCH 867/915] Various renaming and class updates to allow multiple menu banners --- .../Visual/Menus/TestSceneMainMenu.cs | 46 +++++++++----- ...tleRequest.cs => GetMenuContentRequest.cs} | 4 +- .../API/Requests/Responses/APIMenuContent.cs | 42 +++++++++++++ .../API/Requests/Responses/APIMenuImage.cs | 57 +++++++++++++++++ .../API/Requests/Responses/APISystemTitle.cs | 30 --------- osu.Game/Screens/Menu/MainMenu.cs | 8 +-- .../{SystemTitle.cs => OnlineMenuBanner.cs} | 62 ++++++++++--------- 7 files changed, 169 insertions(+), 80 deletions(-) rename osu.Game/Online/API/Requests/{GetSystemTitleRequest.cs => GetMenuContentRequest.cs} (74%) create mode 100644 osu.Game/Online/API/Requests/Responses/APIMenuContent.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIMenuImage.cs delete mode 100644 osu.Game/Online/API/Requests/Responses/APISystemTitle.cs rename osu.Game/Screens/Menu/{SystemTitle.cs => OnlineMenuBanner.cs} (79%) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMainMenu.cs b/osu.Game.Tests/Visual/Menus/TestSceneMainMenu.cs index 7053a9d544..3c78edb8a5 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMainMenu.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMainMenu.cs @@ -13,30 +13,48 @@ namespace osu.Game.Tests.Visual.Menus { public partial class TestSceneMainMenu : OsuGameTestScene { - private SystemTitle systemTitle => Game.ChildrenOfType().Single(); + private OnlineMenuBanner onlineMenuBanner => Game.ChildrenOfType().Single(); [Test] - public void TestSystemTitle() + public void TestOnlineMenuBanner() { - AddStep("set system title", () => systemTitle.Current.Value = new APISystemTitle + AddStep("set online content", () => onlineMenuBanner.Current.Value = new APIMenuContent { - Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png", - Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023", + Images = new[] + { + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png", + Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023", + } + } }); - AddAssert("system title not visible", () => systemTitle.State.Value, () => Is.EqualTo(Visibility.Hidden)); + AddAssert("system title not visible", () => onlineMenuBanner.State.Value, () => Is.EqualTo(Visibility.Hidden)); AddStep("enter menu", () => InputManager.Key(Key.Enter)); - AddUntilStep("system title visible", () => systemTitle.State.Value, () => Is.EqualTo(Visibility.Visible)); - AddStep("set another title", () => systemTitle.Current.Value = new APISystemTitle + AddUntilStep("system title visible", () => onlineMenuBanner.State.Value, () => Is.EqualTo(Visibility.Visible)); + AddStep("set another title", () => onlineMenuBanner.Current.Value = new APIMenuContent { - Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png", - Url = @"https://osu.ppy.sh/community/contests/189", + Images = new[] + { + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png", + Url = @"https://osu.ppy.sh/community/contests/189", + } + } }); - AddStep("set title with nonexistent image", () => systemTitle.Current.Value = new APISystemTitle + AddStep("set title with nonexistent image", () => onlineMenuBanner.Current.Value = new APIMenuContent { - Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2 - Url = @"https://osu.ppy.sh/community/contests/189", + Images = new[] + { + new APIMenuImage + { + Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2 + Url = @"https://osu.ppy.sh/community/contests/189", + } + } }); - AddStep("unset system title", () => systemTitle.Current.Value = null); + AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent()); } } } diff --git a/osu.Game/Online/API/Requests/GetSystemTitleRequest.cs b/osu.Game/Online/API/Requests/GetMenuContentRequest.cs similarity index 74% rename from osu.Game/Online/API/Requests/GetSystemTitleRequest.cs rename to osu.Game/Online/API/Requests/GetMenuContentRequest.cs index 52ca0c11eb..ad2bac6696 100644 --- a/osu.Game/Online/API/Requests/GetSystemTitleRequest.cs +++ b/osu.Game/Online/API/Requests/GetMenuContentRequest.cs @@ -5,9 +5,9 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class GetSystemTitleRequest : OsuJsonWebRequest + public class GetMenuContentRequest : OsuJsonWebRequest { - public GetSystemTitleRequest() + public GetMenuContentRequest() : base(@"https://assets.ppy.sh/lazer-status.json") { } diff --git a/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs b/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs new file mode 100644 index 0000000000..acee6c99ba --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs @@ -0,0 +1,42 @@ +// 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.Online.API.Requests.Responses +{ + public class APIMenuContent : IEquatable + { + /// + /// Images which should be displayed in rotation. + /// + [JsonProperty(@"images")] + public APIMenuImage[] Images { get; init; } = Array.Empty(); + + public DateTimeOffset LastUpdated { get; init; } + + public bool Equals(APIMenuContent? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return LastUpdated.Equals(other.LastUpdated); + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + + if (obj.GetType() != GetType()) return false; + + return Equals((APIMenuContent)obj); + } + + public override int GetHashCode() + { + return LastUpdated.GetHashCode(); + } + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs b/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs new file mode 100644 index 0000000000..4824e23d4b --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs @@ -0,0 +1,57 @@ +// 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.Online.API.Requests.Responses +{ + public class APIMenuImage : IEquatable + { + /// + /// A URL pointing to the image which should be displayed. Generally should be an @2x image filename. + /// + [JsonProperty(@"image")] + public string Image { get; init; } = string.Empty; + + /// + /// A URL that should be opened on clicking the image. + /// + [JsonProperty(@"url")] + public string Url { get; init; } = string.Empty; + + /// + /// The time at which this item should begin displaying. If null, will display immediately. + /// + [JsonProperty(@"begins")] + public DateTimeOffset? Begins { get; set; } + + /// + /// The time at which this item should stop displaying. If null, will display indefinitely. + /// + [JsonProperty(@"expires")] + public DateTimeOffset? Expires { get; set; } + + public bool Equals(APIMenuImage? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return Image == other.Image && Url == other.Url; + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + + return Equals((APIMenuImage)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(Image, Url); + } + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APISystemTitle.cs b/osu.Game/Online/API/Requests/Responses/APISystemTitle.cs deleted file mode 100644 index bfa5c1043b..0000000000 --- a/osu.Game/Online/API/Requests/Responses/APISystemTitle.cs +++ /dev/null @@ -1,30 +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.Online.API.Requests.Responses -{ - public class APISystemTitle : IEquatable - { - [JsonProperty(@"image")] - public string Image { get; set; } = string.Empty; - - [JsonProperty(@"url")] - public string Url { get; set; } = string.Empty; - - public bool Equals(APISystemTitle? other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - - return Image == other.Image && Url == other.Url; - } - - public override bool Equals(object? obj) => obj is APISystemTitle other && Equals(other); - - // ReSharper disable NonReadonlyMemberInGetHashCode - public override int GetHashCode() => HashCode.Combine(Image, Url); - } -} diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index decb901c32..235c5d5c56 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -98,7 +98,7 @@ namespace osu.Game.Screens.Menu private ParallaxContainer buttonsContainer; private SongTicker songTicker; private Container logoTarget; - private SystemTitle systemTitle; + private OnlineMenuBanner onlineMenuBanner; private MenuTip menuTip; private FillFlowContainer bottomElementsFlow; private SupporterDisplay supporterDisplay; @@ -178,7 +178,7 @@ namespace osu.Game.Screens.Menu Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, - systemTitle = new SystemTitle + onlineMenuBanner = new OnlineMenuBanner { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -201,12 +201,12 @@ namespace osu.Game.Screens.Menu case ButtonSystemState.Initial: case ButtonSystemState.Exit: ApplyToBackground(b => b.FadeColour(Color4.White, 500, Easing.OutSine)); - systemTitle.State.Value = Visibility.Hidden; + onlineMenuBanner.State.Value = Visibility.Hidden; break; default: ApplyToBackground(b => b.FadeColour(OsuColour.Gray(0.8f), 500, Easing.OutSine)); - systemTitle.State.Value = Visibility.Visible; + onlineMenuBanner.State.Value = Visibility.Visible; break; } }; diff --git a/osu.Game/Screens/Menu/SystemTitle.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs similarity index 79% rename from osu.Game/Screens/Menu/SystemTitle.cs rename to osu.Game/Screens/Menu/OnlineMenuBanner.cs index 813a470ed6..cf20196f85 100644 --- a/osu.Game/Screens/Menu/SystemTitle.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; @@ -18,42 +19,28 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Screens.Menu { - public partial class SystemTitle : VisibilityContainer + public partial class OnlineMenuBanner : VisibilityContainer { - internal Bindable Current { get; } = new Bindable(); + internal Bindable Current { get; } = new Bindable(new APIMenuContent()); private const float transition_duration = 500; private Container content = null!; private CancellationTokenSource? cancellationTokenSource; - private SystemTitleImage? currentImage; - - private ScheduledDelegate? openUrlAction; + private MenuImage? currentImage; [BackgroundDependencyLoader] - private void load(OsuGame? game) + private void load() { AutoSizeAxes = Axes.Both; AutoSizeDuration = transition_duration; AutoSizeEasing = Easing.OutQuint; - InternalChild = content = new OsuClickableContainer + InternalChild = content = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, - Action = () => - { - currentImage?.Flash(); - - // Delay slightly to allow animation to play out. - openUrlAction?.Cancel(); - openUrlAction = Scheduler.AddDelayed(() => - { - if (!string.IsNullOrEmpty(Current.Value?.Url)) - game?.HandleLink(Current.Value.Url); - }, 250); - } }; } @@ -98,7 +85,7 @@ namespace osu.Game.Screens.Menu private void checkForUpdates() { - var request = new GetSystemTitleRequest(); + var request = new GetMenuContentRequest(); Task.Run(() => request.Perform()) .ContinueWith(r => { @@ -121,12 +108,12 @@ namespace osu.Game.Screens.Menu cancellationTokenSource = null; currentImage?.FadeOut(500, Easing.OutQuint).Expire(); - if (string.IsNullOrEmpty(Current.Value?.Image)) + if (Current.Value.Images.Length == 0) return; - LoadComponentAsync(new SystemTitleImage(Current.Value), loaded => + LoadComponentAsync(new MenuImage(Current.Value.Images.First()), loaded => { - if (!loaded.SystemTitle.Equals(Current.Value)) + if (!loaded.Image.Equals(Current.Value.Images.First())) loaded.Dispose(); content.Add(currentImage = loaded); @@ -134,22 +121,24 @@ namespace osu.Game.Screens.Menu } [LongRunningLoad] - private partial class SystemTitleImage : CompositeDrawable + private partial class MenuImage : OsuClickableContainer { - public readonly APISystemTitle SystemTitle; + public readonly APIMenuImage Image; private Sprite flash = null!; - public SystemTitleImage(APISystemTitle systemTitle) + private ScheduledDelegate? openUrlAction; + + public MenuImage(APIMenuImage image) { - SystemTitle = systemTitle; + Image = image; } [BackgroundDependencyLoader] - private void load(LargeTextureStore textureStore) + private void load(LargeTextureStore textureStore, OsuGame game) { - Texture? texture = textureStore.Get(SystemTitle.Image); - if (texture != null && SystemTitle.Image.Contains(@"@2x")) + Texture? texture = textureStore.Get(Image.Image); + if (texture != null && Image.Image.Contains(@"@2x")) texture.ScaleAdjust *= 2; AutoSizeAxes = Axes.Both; @@ -163,6 +152,19 @@ namespace osu.Game.Screens.Menu Blending = BlendingParameters.Additive, }, }; + + Action = () => + { + Flash(); + + // Delay slightly to allow animation to play out. + openUrlAction?.Cancel(); + openUrlAction = Scheduler.AddDelayed(() => + { + if (!string.IsNullOrEmpty(Image.Url)) + game?.HandleLink(Image.Url); + }, 250); + }; } protected override void LoadComplete() From 4c82e44291fdf23bf324d1d8f4a3092ede9437da Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Mar 2024 20:07:17 +0800 Subject: [PATCH 868/915] Add isolated test coverage of online menu banner --- .../Visual/Menus/TestSceneMainMenu.cs | 23 ------ .../Visual/Menus/TestSceneOnlineMenuBanner.cs | 71 +++++++++++++++++++ 2 files changed, 71 insertions(+), 23 deletions(-) create mode 100644 osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMainMenu.cs b/osu.Game.Tests/Visual/Menus/TestSceneMainMenu.cs index 3c78edb8a5..e2a841d79a 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMainMenu.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMainMenu.cs @@ -32,29 +32,6 @@ namespace osu.Game.Tests.Visual.Menus AddAssert("system title not visible", () => onlineMenuBanner.State.Value, () => Is.EqualTo(Visibility.Hidden)); AddStep("enter menu", () => InputManager.Key(Key.Enter)); AddUntilStep("system title visible", () => onlineMenuBanner.State.Value, () => Is.EqualTo(Visibility.Visible)); - AddStep("set another title", () => onlineMenuBanner.Current.Value = new APIMenuContent - { - Images = new[] - { - new APIMenuImage - { - Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png", - Url = @"https://osu.ppy.sh/community/contests/189", - } - } - }); - AddStep("set title with nonexistent image", () => onlineMenuBanner.Current.Value = new APIMenuContent - { - Images = new[] - { - new APIMenuImage - { - Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2 - Url = @"https://osu.ppy.sh/community/contests/189", - } - } - }); - AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent()); } } } diff --git a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs new file mode 100644 index 0000000000..a80212e0a1 --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs @@ -0,0 +1,71 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Screens.Menu; + +namespace osu.Game.Tests.Visual.Menus +{ + public partial class TestSceneOnlineMenuBanner : OsuTestScene + { + private OnlineMenuBanner onlineMenuBanner = null!; + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("Create banner", () => + { + Child = onlineMenuBanner = new OnlineMenuBanner + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + State = { Value = Visibility.Visible } + }; + }); + } + + [Test] + public void TestBasic() + { + AddAssert("system title not visible", () => onlineMenuBanner.State.Value, () => Is.EqualTo(Visibility.Hidden)); + AddStep("set online content", () => onlineMenuBanner.Current.Value = new APIMenuContent + { + Images = new[] + { + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png", + Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023", + } + }, + }); + AddStep("set another title", () => onlineMenuBanner.Current.Value = new APIMenuContent + { + Images = new[] + { + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png", + Url = @"https://osu.ppy.sh/community/contests/189", + } + } + }); + AddStep("set title with nonexistent image", () => onlineMenuBanner.Current.Value = new APIMenuContent + { + Images = new[] + { + new APIMenuImage + { + Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2 + Url = @"https://osu.ppy.sh/community/contests/189", + } + } + }); + AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent()); + } + } +} From ec4a9a5fdd4ffa1df41b2e26227d27d1277ae8d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Mar 2024 23:07:31 +0800 Subject: [PATCH 869/915] Make work again for simple case --- .../API/Requests/Responses/APIMenuContent.cs | 12 ++++++--- osu.Game/Screens/Menu/OnlineMenuBanner.cs | 25 +++++++------------ 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs b/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs index acee6c99ba..7b53488030 100644 --- a/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs +++ b/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses @@ -14,14 +15,12 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"images")] public APIMenuImage[] Images { get; init; } = Array.Empty(); - public DateTimeOffset LastUpdated { get; init; } - public bool Equals(APIMenuContent? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return LastUpdated.Equals(other.LastUpdated); + return Images.SequenceEqual(other.Images); } public override bool Equals(object? obj) @@ -36,7 +35,12 @@ namespace osu.Game.Online.API.Requests.Responses public override int GetHashCode() { - return LastUpdated.GetHashCode(); + var hash = new HashCode(); + + foreach (var image in Images) + hash.Add(image.GetHashCode()); + + return hash.ToHashCode(); } } } diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index cf20196f85..613a6eed4c 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Menu { base.LoadComplete(); - Current.BindValueChanged(_ => loadNewImage(), true); + Current.BindValueChanged(_ => loadNewImages(), true); checkForUpdates(); } @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Menu }); } - private void loadNewImage() + private void loadNewImages() { cancellationTokenSource?.Cancel(); cancellationTokenSource = null; @@ -131,19 +131,19 @@ namespace osu.Game.Screens.Menu public MenuImage(APIMenuImage image) { + AutoSizeAxes = Axes.Both; + Image = image; } [BackgroundDependencyLoader] - private void load(LargeTextureStore textureStore, OsuGame game) + private void load(LargeTextureStore textureStore, OsuGame? game) { Texture? texture = textureStore.Get(Image.Image); if (texture != null && Image.Image.Contains(@"@2x")) texture.ScaleAdjust *= 2; - AutoSizeAxes = Axes.Both; - - InternalChildren = new Drawable[] + Children = new Drawable[] { new Sprite { Texture = texture }, flash = new Sprite @@ -155,7 +155,9 @@ namespace osu.Game.Screens.Menu Action = () => { - Flash(); + flash.FadeInFromZero(50) + .Then() + .FadeOut(500, Easing.OutQuint); // Delay slightly to allow animation to play out. openUrlAction?.Cancel(); @@ -174,15 +176,6 @@ namespace osu.Game.Screens.Menu this.FadeInFromZero(500, Easing.OutQuint); flash.FadeOutFromOne(4000, Easing.OutQuint); } - - public Drawable Flash() - { - flash.FadeInFromZero(50) - .Then() - .FadeOut(500, Easing.OutQuint); - - return this; - } } } } From a4c619ea97c190a9a4929d89268677af7b72a985 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Mar 2024 15:14:56 +0800 Subject: [PATCH 870/915] Add basic support for loading multiple images --- .../Visual/Menus/TestSceneOnlineMenuBanner.cs | 21 ++++- osu.Game/Screens/Menu/OnlineMenuBanner.cs | 80 ++++++++++--------- 2 files changed, 64 insertions(+), 37 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs index a80212e0a1..4cc379a18b 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs @@ -31,7 +31,6 @@ namespace osu.Game.Tests.Visual.Menus [Test] public void TestBasic() { - AddAssert("system title not visible", () => onlineMenuBanner.State.Value, () => Is.EqualTo(Visibility.Hidden)); AddStep("set online content", () => onlineMenuBanner.Current.Value = new APIMenuContent { Images = new[] @@ -43,6 +42,7 @@ namespace osu.Game.Tests.Visual.Menus } }, }); + AddStep("set another title", () => onlineMenuBanner.Current.Value = new APIMenuContent { Images = new[] @@ -54,6 +54,24 @@ namespace osu.Game.Tests.Visual.Menus } } }); + + AddStep("set multiple images", () => onlineMenuBanner.Current.Value = new APIMenuContent + { + Images = new[] + { + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png", + Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023", + }, + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png", + Url = @"https://osu.ppy.sh/community/contests/189", + } + }, + }); + AddStep("set title with nonexistent image", () => onlineMenuBanner.Current.Value = new APIMenuContent { Images = new[] @@ -65,6 +83,7 @@ namespace osu.Game.Tests.Visual.Menus } } }); + AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent()); } } diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index 613a6eed4c..587a93fb67 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -27,7 +27,6 @@ namespace osu.Game.Screens.Menu private Container content = null!; private CancellationTokenSource? cancellationTokenSource; - private MenuImage? currentImage; [BackgroundDependencyLoader] private void load() @@ -48,32 +47,6 @@ namespace osu.Game.Screens.Menu protected override void PopOut() => content.FadeOut(transition_duration, Easing.OutQuint); - protected override bool OnHover(HoverEvent e) - { - content.ScaleTo(1.05f, 2000, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - content.ScaleTo(1f, 500, Easing.OutQuint); - base.OnHoverLost(e); - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - content.ScaleTo(0.95f, 500, Easing.OutQuint); - return base.OnMouseDown(e); - } - - protected override void OnMouseUp(MouseUpEvent e) - { - content - .ScaleTo(0.95f) - .ScaleTo(1, 500, Easing.OutElastic); - base.OnMouseUp(e); - } - protected override void LoadComplete() { base.LoadComplete(); @@ -106,17 +79,26 @@ namespace osu.Game.Screens.Menu { cancellationTokenSource?.Cancel(); cancellationTokenSource = null; - currentImage?.FadeOut(500, Easing.OutQuint).Expire(); - if (Current.Value.Images.Length == 0) + var newContent = Current.Value; + + foreach (var i in content) + { + i.FadeOutFromOne(100, Easing.OutQuint) + .Expire(); + } + + if (newContent.Images.Length == 0) return; - LoadComponentAsync(new MenuImage(Current.Value.Images.First()), loaded => + LoadComponentsAsync(newContent.Images.Select(i => new MenuImage(i)), loaded => { - if (!loaded.Image.Equals(Current.Value.Images.First())) - loaded.Dispose(); + if (!newContent.Equals(Current.Value)) + return; - content.Add(currentImage = loaded); + content.AddRange(loaded); + + loaded.First().Show(); }, (cancellationTokenSource ??= new CancellationTokenSource()).Token); } @@ -132,6 +114,8 @@ namespace osu.Game.Screens.Menu public MenuImage(APIMenuImage image) { AutoSizeAxes = Axes.Both; + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; Image = image; } @@ -169,13 +153,37 @@ namespace osu.Game.Screens.Menu }; } - protected override void LoadComplete() + public override void Show() { - base.LoadComplete(); - this.FadeInFromZero(500, Easing.OutQuint); flash.FadeOutFromOne(4000, Easing.OutQuint); } + + protected override bool OnHover(HoverEvent e) + { + this.ScaleTo(1.05f, 2000, Easing.OutQuint); + return true; + } + + protected override void OnHoverLost(HoverLostEvent e) + { + this.ScaleTo(1f, 500, Easing.OutQuint); + base.OnHoverLost(e); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + this.ScaleTo(0.95f, 500, Easing.OutQuint); + return true; + } + + protected override void OnMouseUp(MouseUpEvent e) + { + this + .ScaleTo(0.95f) + .ScaleTo(1, 500, Easing.OutElastic); + base.OnMouseUp(e); + } } } } From d0b164b44f6d986f965c469cd838bfacbe0a3de6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Mar 2024 23:37:30 +0800 Subject: [PATCH 871/915] Add automatic rotation support --- osu.Game/Screens/Menu/OnlineMenuBanner.cs | 38 +++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index 587a93fb67..a4648265ae 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -28,6 +28,10 @@ namespace osu.Game.Screens.Menu private Container content = null!; private CancellationTokenSource? cancellationTokenSource; + private int displayIndex = -1; + + private ScheduledDelegate? nextDisplay; + [BackgroundDependencyLoader] private void load() { @@ -77,16 +81,16 @@ namespace osu.Game.Screens.Menu private void loadNewImages() { + nextDisplay?.Cancel(); + cancellationTokenSource?.Cancel(); cancellationTokenSource = null; var newContent = Current.Value; - foreach (var i in content) - { - i.FadeOutFromOne(100, Easing.OutQuint) - .Expire(); - } + // A better fade out would be nice, but the menu content changes *very* rarely + // so let's keep things simple for now. + content.Clear(true); if (newContent.Images.Length == 0) return; @@ -96,12 +100,34 @@ namespace osu.Game.Screens.Menu if (!newContent.Equals(Current.Value)) return; + // start hidden + foreach (var image in loaded) + image.Hide(); + content.AddRange(loaded); - loaded.First().Show(); + displayIndex = -1; + showNext(); }, (cancellationTokenSource ??= new CancellationTokenSource()).Token); } + private void showNext() + { + nextDisplay?.Cancel(); + + bool previousShowing = displayIndex >= 0; + if (previousShowing) + content[displayIndex % content.Count].FadeOut(400, Easing.OutQuint); + + displayIndex++; + + using (BeginDelayedSequence(previousShowing ? 300 : 0)) + content[displayIndex % content.Count].Show(); + + if (content.Count > 1) + nextDisplay = Scheduler.AddDelayed(showNext, 12000); + } + [LongRunningLoad] private partial class MenuImage : OsuClickableContainer { From 3847aae57d88ea2156c7599c53a0e994fffd4760 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2024 12:14:40 +0800 Subject: [PATCH 872/915] Don't rotate when hovering --- osu.Game/Screens/Menu/OnlineMenuBanner.cs | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index a4648265ae..74062d5b9f 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -21,6 +21,8 @@ namespace osu.Game.Screens.Menu { public partial class OnlineMenuBanner : VisibilityContainer { + public double DelayBetweenRotation = 7500; + internal Bindable Current { get; } = new Bindable(new APIMenuContent()); private const float transition_duration = 500; @@ -115,21 +117,29 @@ namespace osu.Game.Screens.Menu { nextDisplay?.Cancel(); - bool previousShowing = displayIndex >= 0; - if (previousShowing) - content[displayIndex % content.Count].FadeOut(400, Easing.OutQuint); + // If the user is hovering a banner, don't rotate yet. + bool anyHovered = content.Any(i => i.IsHovered); - displayIndex++; + if (!anyHovered) + { + bool previousShowing = displayIndex >= 0; + if (previousShowing) + content[displayIndex % content.Count].FadeOut(400, Easing.OutQuint); - using (BeginDelayedSequence(previousShowing ? 300 : 0)) - content[displayIndex % content.Count].Show(); + displayIndex++; + + using (BeginDelayedSequence(previousShowing ? 300 : 0)) + content[displayIndex % content.Count].Show(); + } if (content.Count > 1) - nextDisplay = Scheduler.AddDelayed(showNext, 12000); + { + nextDisplay = Scheduler.AddDelayed(showNext, DelayBetweenRotation); + } } [LongRunningLoad] - private partial class MenuImage : OsuClickableContainer + public partial class MenuImage : OsuClickableContainer { public readonly APIMenuImage Image; From e9f15534ed7ea64b7cfe77360f488b3a63e703db Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2024 12:14:47 +0800 Subject: [PATCH 873/915] Improve test coverage --- .../Visual/Menus/TestSceneOnlineMenuBanner.cs | 75 ++++++++++++++++--- osu.Game/Screens/Menu/OnlineMenuBanner.cs | 7 +- 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs index 4cc379a18b..6be5b80983 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.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.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,6 +22,8 @@ namespace osu.Game.Tests.Visual.Menus { Child = onlineMenuBanner = new OnlineMenuBanner { + FetchOnlineContent = false, + DelayBetweenRotation = 500, Anchor = Anchor.Centre, Origin = Anchor.Centre, State = { Value = Visibility.Visible } @@ -43,6 +46,18 @@ namespace osu.Game.Tests.Visual.Menus }, }); + AddUntilStep("wait for one image shown", () => + { + var images = onlineMenuBanner.ChildrenOfType(); + + if (images.Count() != 1) + return false; + + var image = images.Single(); + + return image.IsPresent && image.Image.Url == "https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023"; + }); + AddStep("set another title", () => onlineMenuBanner.Current.Value = new APIMenuContent { Images = new[] @@ -55,6 +70,40 @@ namespace osu.Game.Tests.Visual.Menus } }); + AddUntilStep("wait for new image shown", () => + { + var images = onlineMenuBanner.ChildrenOfType(); + + if (images.Count() != 1) + return false; + + var image = images.Single(); + + return image.IsPresent && image.Image.Url == "https://osu.ppy.sh/community/contests/189"; + }); + + AddStep("set title with nonexistent image", () => onlineMenuBanner.Current.Value = new APIMenuContent + { + Images = new[] + { + new APIMenuImage + { + Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2 + Url = @"https://osu.ppy.sh/community/contests/189", + } + } + }); + + AddUntilStep("wait for no image shown", () => !onlineMenuBanner.ChildrenOfType().Any()); + + AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent()); + + AddUntilStep("wait for no image shown", () => !onlineMenuBanner.ChildrenOfType().Any()); + } + + [Test] + public void TestMultipleImages() + { AddStep("set multiple images", () => onlineMenuBanner.Current.Value = new APIMenuContent { Images = new[] @@ -72,19 +121,25 @@ namespace osu.Game.Tests.Visual.Menus }, }); - AddStep("set title with nonexistent image", () => onlineMenuBanner.Current.Value = new APIMenuContent + AddUntilStep("wait for first image shown", () => { - Images = new[] - { - new APIMenuImage - { - Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2 - Url = @"https://osu.ppy.sh/community/contests/189", - } - } + var images = onlineMenuBanner.ChildrenOfType(); + + if (images.Count() != 2) + return false; + + return images.First().IsPresent && !images.Last().IsPresent; }); - AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent()); + AddUntilStep("wait for second image shown", () => + { + var images = onlineMenuBanner.ChildrenOfType(); + + if (images.Count() != 2) + return false; + + return !images.First().IsPresent && images.Last().IsPresent; + }); } } } diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index 74062d5b9f..2ab6417370 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -21,7 +21,9 @@ namespace osu.Game.Screens.Menu { public partial class OnlineMenuBanner : VisibilityContainer { - public double DelayBetweenRotation = 7500; + public double DelayBetweenRotation { get; set; } = 7500; + + public bool FetchOnlineContent { get; set; } = true; internal Bindable Current { get; } = new Bindable(new APIMenuContent()); @@ -64,6 +66,9 @@ namespace osu.Game.Screens.Menu private void checkForUpdates() { + if (!FetchOnlineContent) + return; + var request = new GetMenuContentRequest(); Task.Run(() => request.Perform()) .ContinueWith(r => From f0614928b182bf2d575c5e298e29d2254fd28ecb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2024 13:19:12 +0800 Subject: [PATCH 874/915] Read from new location --- osu.Game/Online/API/Requests/GetMenuContentRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/GetMenuContentRequest.cs b/osu.Game/Online/API/Requests/GetMenuContentRequest.cs index ad2bac6696..26747489d6 100644 --- a/osu.Game/Online/API/Requests/GetMenuContentRequest.cs +++ b/osu.Game/Online/API/Requests/GetMenuContentRequest.cs @@ -8,7 +8,7 @@ namespace osu.Game.Online.API.Requests public class GetMenuContentRequest : OsuJsonWebRequest { public GetMenuContentRequest() - : base(@"https://assets.ppy.sh/lazer-status.json") + : base(@"https://assets.ppy.sh/menu-content.json") { } } From 057f86dd145dd5d0ba573737ca61aceb27dcc70a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2024 14:28:23 +0800 Subject: [PATCH 875/915] Add handling of expiration --- .../Visual/Menus/TestSceneOnlineMenuBanner.cs | 60 +++++++++++++++++++ .../API/Requests/Responses/APIMenuImage.cs | 4 ++ osu.Game/Screens/Menu/OnlineMenuBanner.cs | 60 ++++++++++++------- 3 files changed, 102 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs index 6be5b80983..2dd08ce306 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.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.Linq; using NUnit.Framework; using osu.Framework.Graphics; @@ -141,5 +142,64 @@ namespace osu.Game.Tests.Visual.Menus return !images.First().IsPresent && images.Last().IsPresent; }); } + + [Test] + public void TestExpiry() + { + AddStep("set multiple images, second expiring soon", () => onlineMenuBanner.Current.Value = new APIMenuContent + { + Images = new[] + { + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png", + Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023", + }, + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png", + Url = @"https://osu.ppy.sh/community/contests/189", + Expires = DateTimeOffset.Now.AddSeconds(2), + } + }, + }); + + AddUntilStep("wait for first image shown", () => + { + var images = onlineMenuBanner.ChildrenOfType(); + + if (images.Count() != 2) + return false; + + return images.First().IsPresent && !images.Last().IsPresent; + }); + + AddUntilStep("wait for second image shown", () => + { + var images = onlineMenuBanner.ChildrenOfType(); + + if (images.Count() != 2) + return false; + + return !images.First().IsPresent && images.Last().IsPresent; + }); + + AddUntilStep("wait for expiry", () => + { + return onlineMenuBanner + .ChildrenOfType() + .Any(i => !i.Image.IsCurrent); + }); + + AddUntilStep("wait for first image shown", () => + { + var images = onlineMenuBanner.ChildrenOfType(); + + if (images.Count() != 2) + return false; + + return images.First().IsPresent && !images.Last().IsPresent; + }); + } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs b/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs index 4824e23d4b..42129ca96e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs +++ b/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs @@ -20,6 +20,10 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"url")] public string Url { get; init; } = string.Empty; + public bool IsCurrent => + (Begins == null || Begins < DateTimeOffset.UtcNow) && + (Expires == null || Expires > DateTimeOffset.UtcNow); + /// /// The time at which this item should begin displaying. If null, will display immediately. /// diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index 2ab6417370..55ceb84d7b 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Menu private const float transition_duration = 500; - private Container content = null!; + private Container content = null!; private CancellationTokenSource? cancellationTokenSource; private int displayIndex = -1; @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Menu AutoSizeDuration = transition_duration; AutoSizeEasing = Easing.OutQuint; - InternalChild = content = new Container + InternalChild = content = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -59,8 +59,7 @@ namespace osu.Game.Screens.Menu { base.LoadComplete(); - Current.BindValueChanged(_ => loadNewImages(), true); - + Current.BindValueChanged(loadNewImages, true); checkForUpdates(); } @@ -86,25 +85,24 @@ namespace osu.Game.Screens.Menu }); } - private void loadNewImages() + /// + /// Takes and materialises and displays drawables for all valid images to be displayed. + /// + /// + private void loadNewImages(ValueChangedEvent images) { nextDisplay?.Cancel(); cancellationTokenSource?.Cancel(); cancellationTokenSource = null; - var newContent = Current.Value; - // A better fade out would be nice, but the menu content changes *very* rarely // so let's keep things simple for now. content.Clear(true); - if (newContent.Images.Length == 0) - return; - - LoadComponentsAsync(newContent.Images.Select(i => new MenuImage(i)), loaded => + LoadComponentsAsync(images.NewValue.Images.Select(i => new MenuImage(i)), loaded => { - if (!newContent.Equals(Current.Value)) + if (!images.NewValue.Equals(Current.Value)) return; // start hidden @@ -127,20 +125,38 @@ namespace osu.Game.Screens.Menu if (!anyHovered) { - bool previousShowing = displayIndex >= 0; - if (previousShowing) - content[displayIndex % content.Count].FadeOut(400, Easing.OutQuint); + int previousIndex = displayIndex; - displayIndex++; + if (displayIndex == -1) + displayIndex = 0; - using (BeginDelayedSequence(previousShowing ? 300 : 0)) - content[displayIndex % content.Count].Show(); + // To handle expiration simply, arrange all images in best-next order. + // Fade in the first valid one, then handle fading out the last if required. + var currentRotation = content + .Skip(displayIndex + 1) + .Concat(content.Take(displayIndex + 1)); + + foreach (var image in currentRotation) + { + if (!image.Image.IsCurrent) continue; + + using (BeginDelayedSequence(previousIndex >= 0 ? 300 : 0)) + { + displayIndex = content.IndexOf(image); + + if (displayIndex != previousIndex) + image.Show(); + + break; + } + } + + if (previousIndex >= 0 && previousIndex != displayIndex) + content[previousIndex].FadeOut(400, Easing.OutQuint); } - if (content.Count > 1) - { - nextDisplay = Scheduler.AddDelayed(showNext, DelayBetweenRotation); - } + // Re-scheduling this method will both handle rotation and re-checking for expiration dates. + nextDisplay = Scheduler.AddDelayed(showNext, DelayBetweenRotation); } [LongRunningLoad] From bb9fa52fda51f46e4e0fe39e2be8196ab0dc0fba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2024 14:53:05 +0800 Subject: [PATCH 876/915] Fix `displayIndex` not being correctly set to `-1` after last expiry date --- .../Visual/Menus/TestSceneOnlineMenuBanner.cs | 36 ++++++++++++++++++- osu.Game/Screens/Menu/OnlineMenuBanner.cs | 11 +++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs index 2dd08ce306..380085ce04 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs @@ -144,7 +144,41 @@ namespace osu.Game.Tests.Visual.Menus } [Test] - public void TestExpiry() + public void TestFutureSingle() + { + AddStep("set image with time constraints", () => onlineMenuBanner.Current.Value = new APIMenuContent + { + Images = new[] + { + new APIMenuImage + { + Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png", + Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023", + Begins = DateTimeOffset.Now.AddSeconds(2), + Expires = DateTimeOffset.Now.AddSeconds(5), + }, + }, + }); + + AddUntilStep("wait for no image shown", () => !onlineMenuBanner.ChildrenOfType().Any(i => i.IsPresent)); + + AddUntilStep("wait for one image shown", () => + { + var images = onlineMenuBanner.ChildrenOfType(); + + if (images.Count() != 1) + return false; + + var image = images.Single(); + + return image.IsPresent && image.Image.Url == "https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023"; + }); + + AddUntilStep("wait for no image shown", () => !onlineMenuBanner.ChildrenOfType().Any(i => i.IsPresent)); + } + + [Test] + public void TestExpiryMultiple() { AddStep("set multiple images, second expiring soon", () => onlineMenuBanner.Current.Value = new APIMenuContent { diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index 55ceb84d7b..37bec7aa63 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -127,14 +127,15 @@ namespace osu.Game.Screens.Menu { int previousIndex = displayIndex; - if (displayIndex == -1) - displayIndex = 0; - // To handle expiration simply, arrange all images in best-next order. // Fade in the first valid one, then handle fading out the last if required. var currentRotation = content - .Skip(displayIndex + 1) - .Concat(content.Take(displayIndex + 1)); + .Skip(Math.Max(0, previousIndex) + 1) + .Concat(content.Take(Math.Max(0, previousIndex) + 1)); + + // After the loop, displayIndex will be the new valid index or -1 if + // none valid. + displayIndex = -1; foreach (var image in currentRotation) { From 78037fa4773dfc8f8063d45e104bd84131515bcc Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Mon, 25 Mar 2024 04:19:14 -0300 Subject: [PATCH 877/915] Handle new combo on `HandleReverse` --- .../Edit/CatchSelectionHandler.cs | 33 ++++++++++++++++--- .../Edit/OsuSelectionHandler.cs | 20 +++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs index 418351e2f3..e3d82cc517 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs @@ -76,21 +76,44 @@ namespace osu.Game.Rulesets.Catch.Edit public override bool HandleReverse() { + var hitObjects = EditorBeatmap.SelectedHitObjects; + double selectionStartTime = SelectedItems.Min(h => h.StartTime); double selectionEndTime = SelectedItems.Max(h => h.GetEndTime()); - EditorBeatmap.PerformOnSelection(hitObject => - { - hitObject.StartTime = selectionEndTime - (hitObject.GetEndTime() - selectionStartTime); + var newComboPlaces = hitObjects + .OfType() + .Where(h => h.NewCombo) + .Select(obj => obj.StartTime) + .ToList(); - if (hitObject is JuiceStream juiceStream) + foreach (var h in hitObjects) + { + h.StartTime = selectionEndTime - (h.GetEndTime() - selectionStartTime); + + if (h is JuiceStream juiceStream) { juiceStream.Path.Reverse(out Vector2 positionalOffset); juiceStream.OriginalX += positionalOffset.X; juiceStream.LegacyConvertedY += positionalOffset.Y; EditorBeatmap.Update(juiceStream); } - }); + } + + foreach (var h in hitObjects) + { + if (h is CatchHitObject obj) obj.NewCombo = false; + } + + foreach (double place in newComboPlaces) + { + hitObjects + .OfType() + .Where(obj => obj.StartTime == place) + .ToList() + .ForEach(obj => obj.NewCombo = true); + } + return true; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index cea2adc6e2..b4980b55d4 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -85,6 +85,12 @@ namespace osu.Game.Rulesets.Osu.Edit bool moreThanOneObject = hitObjects.Count > 1; + var newComboPlaces = hitObjects + .OfType() + .Where(h => h.NewCombo) + .Select(obj => obj.StartTime) + .ToList(); + foreach (var h in hitObjects) { if (moreThanOneObject) @@ -97,6 +103,20 @@ namespace osu.Game.Rulesets.Osu.Edit } } + foreach (var h in hitObjects) + { + if (h is OsuHitObject obj) obj.NewCombo = false; + } + + foreach (double place in newComboPlaces) + { + hitObjects + .OfType() + .Where(obj => obj.StartTime == place) + .ToList() + .ForEach(obj => obj.NewCombo = true); + } + return true; } From 3db88fbcea288f5c4136739bd26e0bdab9e0b05a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Mar 2024 17:54:20 +0100 Subject: [PATCH 878/915] Use less confusing message format when logging discord errors The "code" is a number, so it looked weird when put in the middle without any nearby punctuation. Example: An error occurred with Discord RPC Client: 5005 secrets cannot currently be sent with buttons --- osu.Desktop/DiscordRichPresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index d78459ff28..eaa9a90f27 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -75,7 +75,7 @@ namespace osu.Desktop }; client.OnReady += onReady; - client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network, LogLevel.Error); + client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Message} ({e.Code})", LoggingTarget.Network, LogLevel.Error); // A URI scheme is required to support game invitations, as well as informing Discord of the game executable path to support launching the game when a user clicks on join/spectate. client.RegisterUriScheme(); From e95f29cf4ba8840e0305bbae7637d01ddc03f285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Mar 2024 17:57:13 +0100 Subject: [PATCH 879/915] Rename `updatePresence() => schedulePresenceUpdate()` The method doesn't actually update anything by itself, and I want to free up the `updatePresence()` name for the actual update. --- osu.Desktop/DiscordRichPresence.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index eaa9a90f27..811f2f3548 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -94,10 +94,10 @@ namespace osu.Desktop activity.BindTo(u.NewValue.Activity); }, true); - ruleset.BindValueChanged(_ => updatePresence()); - status.BindValueChanged(_ => updatePresence()); - activity.BindValueChanged(_ => updatePresence()); - privacyMode.BindValueChanged(_ => updatePresence()); + ruleset.BindValueChanged(_ => schedulePresenceUpdate()); + status.BindValueChanged(_ => schedulePresenceUpdate()); + activity.BindValueChanged(_ => schedulePresenceUpdate()); + privacyMode.BindValueChanged(_ => schedulePresenceUpdate()); multiplayerClient.RoomUpdated += onRoomUpdated; client.Initialize(); @@ -111,14 +111,14 @@ namespace osu.Desktop if (client.CurrentPresence != null) client.SetPresence(null); - updatePresence(); + schedulePresenceUpdate(); } - private void onRoomUpdated() => updatePresence(); + private void onRoomUpdated() => schedulePresenceUpdate(); private ScheduledDelegate? presenceUpdateDelegate; - private void updatePresence() + private void schedulePresenceUpdate() { presenceUpdateDelegate?.Cancel(); presenceUpdateDelegate = Scheduler.AddDelayed(() => From a398754a27ac26a1f6e57790b2c609226ad805fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Mar 2024 18:00:42 +0100 Subject: [PATCH 880/915] Merge all presence methods into one I'm about to make them interdependent (and it's discord's fault), so it doesn't really make sense to make them separate at this point I don't think. And it felt weird anyway. --- osu.Desktop/DiscordRichPresence.cs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 811f2f3548..d67437ba62 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -134,16 +134,14 @@ namespace osu.Desktop bool hideIdentifiableInformation = privacyMode.Value == DiscordRichPresenceMode.Limited || status.Value == UserStatus.DoNotDisturb; - updatePresenceStatus(hideIdentifiableInformation); - updatePresenceParty(hideIdentifiableInformation); - updatePresenceAssets(); - + updatePresence(hideIdentifiableInformation); client.SetPresence(presence); }, 200); } - private void updatePresenceStatus(bool hideIdentifiableInformation) + private void updatePresence(bool hideIdentifiableInformation) { + // user activity if (activity.Value != null) { presence.State = truncate(activity.Value.GetStatus(hideIdentifiableInformation)); @@ -170,10 +168,8 @@ namespace osu.Desktop presence.State = "Idle"; presence.Details = string.Empty; } - } - private void updatePresenceParty(bool hideIdentifiableInformation) - { + // user party if (!hideIdentifiableInformation && multiplayerClient.Room != null) { MultiplayerRoom room = multiplayerClient.Room; @@ -201,11 +197,9 @@ namespace osu.Desktop presence.Party = null; presence.Secrets.JoinSecret = null; } - } - private void updatePresenceAssets() - { - // update user information + // game images: + // large image tooltip if (privacyMode.Value == DiscordRichPresenceMode.Limited) presence.Assets.LargeImageText = string.Empty; else @@ -216,7 +210,7 @@ namespace osu.Desktop presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.GlobalRank > 0 ? $" (rank #{user.Value.Statistics.GlobalRank:N0})" : string.Empty); } - // update ruleset + // small image presence.Assets.SmallImageKey = ruleset.Value.IsLegacyRuleset() ? $"mode_{ruleset.Value.OnlineID}" : "mode_custom"; presence.Assets.SmallImageText = ruleset.Value.Name; } From 53c3aec3c364a2541180e1bc34b4c40ee688f2b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Mar 2024 18:02:54 +0100 Subject: [PATCH 881/915] Fix discord RPC errors in multiplayer Reproduction steps: 1. Go to multiplayer 2. Create a room 3. Play a map to completion 4. Wait for "secrets cannot currently be sent with buttons" error messages The fix is to clear the buttons since they're the less important ones. --- osu.Desktop/DiscordRichPresence.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index d67437ba62..6e8554d617 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -191,6 +191,9 @@ namespace osu.Desktop }; presence.Secrets.JoinSecret = JsonConvert.SerializeObject(roomSecret); + // discord cannot handle both secrets and buttons at the same time, so we need to choose something. + // the multiplayer room seems more important. + presence.Buttons = null; } else { From 6266af8a5696edb32da2f57b877f84dbcab66e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Mar 2024 18:57:58 +0100 Subject: [PATCH 882/915] Fix taiko legacy score simulator not including swell tick score gain into bonus portion Reported in https://discord.com/channels/188630481301012481/1097318920991559880/1221836384038551613. Example score: https://osu.ppy.sh/scores/1855965185 The cause of the overestimation was an error in taiko's score simulator. In lazer taiko, swell ticks don't give any score anymore, while they did in stable. For all intents and purposes, swell ticks can be considered "bonus" objects that "don't give any actual bonus score". Which is to say, during simulation of a legacy score swell ticks hit should be treated as bonus, because if they aren't, then otherwise they will be treated essentially as *normal hits*, meaning that they will be included in the *accuracy* portion of score, which breaks all sorts of follow-up assumptions: - The accuracy portion of the best possible total score becomes overinflated in comparison to reality, while the combo portion of that maximum score becomes underestimated. - Because the affected score has low accuracy, the estimated accuracy portion of the score (as given by maximmum accuracy portion of score times the actual numerical accuracy of the score) is also low. - However, the next step is estimating the combo portion, which is done by taking legacy total score, subtracting the aforementioned estimation for accuracy total score from that, and then dividing the result by the maximum achievable combo score on the map. Because most of actual "combo" score from swell ticks was "moved" into the accuracy portion due to the aforementioned error, the maximum achievable combo score becomes so small that the estimated combo portion exceeds 1. Instead, this change makes it so that gains from swell ticks are treated as "bonus", which means that they are excluded from the accuracy portion of score and instead count into the bonus portion of score, bringing the scores concerned more in line with expectations - although due to pessimistic assumptions in the simulation of the swell itself, the conversion will still overestimate total score for affected scores, just not by *that* much. --- osu.Game.Rulesets.Taiko/Difficulty/TaikoLegacyScoreSimulator.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoLegacyScoreSimulator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoLegacyScoreSimulator.cs index 66ff0fc3d9..9839d94277 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoLegacyScoreSimulator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoLegacyScoreSimulator.cs @@ -95,6 +95,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty case SwellTick: scoreIncrease = 300; increaseCombo = false; + isBonus = true; + bonusResult = HitResult.IgnoreHit; break; case DrumRollTick: From 73926592b91e1cf6348b3e7ae3c68142dbbd8d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Mar 2024 19:27:38 +0100 Subject: [PATCH 883/915] Bump legacy score version to recalculate all scores --- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 93f51ee74d..0f00cce080 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -46,9 +46,10 @@ namespace osu.Game.Scoring.Legacy /// 30000013: All local scores will use lazer definitions of ranks for consistency. Recalculates the rank of all scores. /// 30000014: Fix edge cases in conversion for osu! scores on selected beatmaps. Reconvert all scores. /// 30000015: Fix osu! standardised score estimation algorithm violating basic invariants. Reconvert all scores. + /// 30000016: Fix taiko standardised score estimation algorithm not including swell tick score gain into bonus portion. Reconvert all scores. /// /// - public const int LATEST_VERSION = 30000015; + public const int LATEST_VERSION = 30000016; /// /// The first stable-compatible YYYYMMDD format version given to lazer usage of replays. From 10683de578590d9a17c690df4ef9fc89515599a5 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Tue, 26 Mar 2024 04:59:47 -0300 Subject: [PATCH 884/915] Use order of new combo flags instead of `StartTime` --- .../Edit/CatchSelectionHandler.cs | 22 +++++++------------ .../Edit/OsuSelectionHandler.cs | 22 +++++++------------ 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs index e3d82cc517..e3d2347c4d 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs @@ -81,12 +81,13 @@ namespace osu.Game.Rulesets.Catch.Edit double selectionStartTime = SelectedItems.Min(h => h.StartTime); double selectionEndTime = SelectedItems.Max(h => h.GetEndTime()); - var newComboPlaces = hitObjects + var newComboOrder = hitObjects .OfType() - .Where(h => h.NewCombo) - .Select(obj => obj.StartTime) + .Select(obj => obj.NewCombo) .ToList(); + newComboOrder.Reverse(); + foreach (var h in hitObjects) { h.StartTime = selectionEndTime - (h.GetEndTime() - selectionStartTime); @@ -100,18 +101,11 @@ namespace osu.Game.Rulesets.Catch.Edit } } - foreach (var h in hitObjects) + int i = 0; + foreach (bool newCombo in newComboOrder) { - if (h is CatchHitObject obj) obj.NewCombo = false; - } - - foreach (double place in newComboPlaces) - { - hitObjects - .OfType() - .Where(obj => obj.StartTime == place) - .ToList() - .ForEach(obj => obj.NewCombo = true); + hitObjects.OfType().ToList()[i].NewCombo = newCombo; + i++; } return true; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index b4980b55d4..df39ab8fce 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -85,12 +85,13 @@ namespace osu.Game.Rulesets.Osu.Edit bool moreThanOneObject = hitObjects.Count > 1; - var newComboPlaces = hitObjects + var newComboOrder = hitObjects .OfType() - .Where(h => h.NewCombo) - .Select(obj => obj.StartTime) + .Select(obj => obj.NewCombo) .ToList(); + newComboOrder.Reverse(); + foreach (var h in hitObjects) { if (moreThanOneObject) @@ -103,18 +104,11 @@ namespace osu.Game.Rulesets.Osu.Edit } } - foreach (var h in hitObjects) + int i = 0; + foreach (bool newCombo in newComboOrder) { - if (h is OsuHitObject obj) obj.NewCombo = false; - } - - foreach (double place in newComboPlaces) - { - hitObjects - .OfType() - .Where(obj => obj.StartTime == place) - .ToList() - .ForEach(obj => obj.NewCombo = true); + hitObjects.OfType().ToList()[i].NewCombo = newCombo; + i++; } return true; From 9b923b19094bbcdf3f130d005085de70368cb8c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Mar 2024 10:55:49 +0100 Subject: [PATCH 885/915] Fix code quality issues --- .../Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs | 4 ++-- .../Editor/Checks/CheckKeyCountTest.cs | 2 +- .../Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs | 4 ++-- .../Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs | 4 ++-- .../Edit/Checks/CheckOsuAbnormalDifficultySettings.cs | 1 + .../Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs | 4 ++-- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Catch.Tests/Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs index 2ae2e20215..33aa4cba5d 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/Checks/CheckCatchAbnormalDifficultySettingsTest.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor.Checks { private CheckCatchAbnormalDifficultySettings check = null!; - private IBeatmap beatmap = new Beatmap(); + private readonly IBeatmap beatmap = new Beatmap(); [SetUp] public void Setup() @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor.Checks check = new CheckCatchAbnormalDifficultySettings(); beatmap.BeatmapInfo.Ruleset = new CatchRuleset().RulesetInfo; - beatmap.Difficulty = new BeatmapDifficulty() + beatmap.Difficulty = new BeatmapDifficulty { ApproachRate = 5, CircleSize = 5, diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs index 564c611548..b40a62176c 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckKeyCountTest.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor.Checks { check = new CheckKeyCount(); - beatmap = new Beatmap() + beatmap = new Beatmap { BeatmapInfo = new BeatmapInfo { diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs index 6c585aace3..da5ab037e5 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/Checks/CheckManiaAbnormalDifficultySettingsTest.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor.Checks { private CheckManiaAbnormalDifficultySettings check = null!; - private IBeatmap beatmap = new Beatmap(); + private readonly IBeatmap beatmap = new Beatmap(); [SetUp] public void Setup() @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor.Checks check = new CheckManiaAbnormalDifficultySettings(); beatmap.BeatmapInfo.Ruleset = new ManiaRuleset().RulesetInfo; - beatmap.Difficulty = new BeatmapDifficulty() + beatmap.Difficulty = new BeatmapDifficulty { OverallDifficulty = 5, DrainRate = 5, diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs index 53ccd3c7a7..5f49714d93 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOsuAbnormalDifficultySettingsTest.cs @@ -17,14 +17,14 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks { private CheckOsuAbnormalDifficultySettings check = null!; - private IBeatmap beatmap = new Beatmap(); + private readonly IBeatmap beatmap = new Beatmap(); [SetUp] public void Setup() { check = new CheckOsuAbnormalDifficultySettings(); - beatmap.Difficulty = new BeatmapDifficulty() + beatmap.Difficulty = new BeatmapDifficulty { ApproachRate = 5, CircleSize = 5, diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs index c1eca7fff7..7ad861f317 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs @@ -11,6 +11,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks public class CheckOsuAbnormalDifficultySettings : CheckAbnormalDifficultySettings { public override CheckMetadata Metadata => new CheckMetadata(CheckCategory.Settings, "Checks osu relevant settings"); + public override IEnumerable Run(BeatmapVerifierContext context) { var diff = context.Beatmap.Difficulty; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs index f10e62f3bf..4a6cf0313a 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor.Checks { private CheckTaikoAbnormalDifficultySettings check = null!; - private IBeatmap beatmap = new Beatmap(); + private readonly IBeatmap beatmap = new Beatmap(); [SetUp] public void Setup() @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor.Checks check = new CheckTaikoAbnormalDifficultySettings(); beatmap.BeatmapInfo.Ruleset = new TaikoRuleset().RulesetInfo; - beatmap.Difficulty = new BeatmapDifficulty() + beatmap.Difficulty = new BeatmapDifficulty { OverallDifficulty = 5, }; From 8fb308c1925e1cdbda3eba6e58b7ef5c8fb1fe89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Mar 2024 10:57:20 +0100 Subject: [PATCH 886/915] Add failing test coverage for checking taiko HP too I was wrong, taiko uses HP (to calculate miss penalty). --- ...heckTaikoAbnormalDifficultySettingsTest.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs index 4a6cf0313a..6a50fd0956 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/Checks/CheckTaikoAbnormalDifficultySettingsTest.cs @@ -52,6 +52,18 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor.Checks Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); } + [Test] + public void TestDrainRateTwoDecimals() + { + beatmap.Difficulty.DrainRate = 5.55f; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateMoreThanOneDecimal); + } + [Test] public void TestOverallDifficultyUnder() { @@ -76,6 +88,30 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor.Checks Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); } + [Test] + public void TestDrainRateUnder() + { + beatmap.Difficulty.DrainRate = -10; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + + [Test] + public void TestDrainRateOver() + { + beatmap.Difficulty.DrainRate = 20; + + var context = getContext(); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckAbnormalDifficultySettings.IssueTemplateOutOfRange); + } + private BeatmapVerifierContext getContext() { return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); From e7cf1ab4df36879306ef6e4c38b535ba370a0e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Mar 2024 10:58:39 +0100 Subject: [PATCH 887/915] Add checks for taiko drain rate --- .../Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs index ce35f21853..10e2867ca0 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs @@ -21,6 +21,12 @@ namespace osu.Game.Rulesets.Taiko.Edit.Checks if (OutOfRange(diff.OverallDifficulty)) yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); + + if (HasMoreThanOneDecimalPlace(diff.DrainRate)) + yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + + if (OutOfRange(diff.DrainRate)) + yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); } } } From 1866b4b6b10d1990db311eb96ae02c5c5609e918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Mar 2024 11:13:03 +0100 Subject: [PATCH 888/915] Refactor abstract check to reduce duplication --- .../CheckCatchAbnormalDifficultySettings.cs | 25 +++++++------- .../CheckManiaAbnormalDifficultySettings.cs | 17 +++++----- .../CheckOsuAbnormalDifficultySettings.cs | 33 ++++++++++--------- .../CheckTaikoAbnormalDifficultySettings.cs | 17 +++++----- .../Checks/CheckAbnormalDifficultySettings.cs | 13 +++++--- 5 files changed, 57 insertions(+), 48 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/Checks/CheckCatchAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Catch/Edit/Checks/CheckCatchAbnormalDifficultySettings.cs index 8295795f00..d2c3df0872 100644 --- a/osu.Game.Rulesets.Catch/Edit/Checks/CheckCatchAbnormalDifficultySettings.cs +++ b/osu.Game.Rulesets.Catch/Edit/Checks/CheckCatchAbnormalDifficultySettings.cs @@ -15,24 +15,25 @@ namespace osu.Game.Rulesets.Catch.Edit.Checks public override IEnumerable Run(BeatmapVerifierContext context) { var diff = context.Beatmap.Difficulty; + Issue? issue; - if (HasMoreThanOneDecimalPlace(diff.ApproachRate)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Approach rate", diff.ApproachRate); + if (HasMoreThanOneDecimalPlace("Approach rate", diff.ApproachRate, out issue)) + yield return issue; - if (OutOfRange(diff.ApproachRate)) - yield return new IssueTemplateOutOfRange(this).Create("Approach rate", diff.ApproachRate); + if (OutOfRange("Approach rate", diff.ApproachRate, out issue)) + yield return issue; - if (HasMoreThanOneDecimalPlace(diff.CircleSize)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Circle size", diff.CircleSize); + if (HasMoreThanOneDecimalPlace("Circle size", diff.CircleSize, out issue)) + yield return issue; - if (OutOfRange(diff.CircleSize)) - yield return new IssueTemplateOutOfRange(this).Create("Circle size", diff.CircleSize); + if (OutOfRange("Circle size", diff.CircleSize, out issue)) + yield return issue; - if (HasMoreThanOneDecimalPlace(diff.DrainRate)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + if (HasMoreThanOneDecimalPlace("Drain rate", diff.DrainRate, out issue)) + yield return issue; - if (OutOfRange(diff.DrainRate)) - yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); + if (OutOfRange("Drain rate", diff.DrainRate, out issue)) + yield return issue; } } } diff --git a/osu.Game.Rulesets.Mania/Edit/Checks/CheckManiaAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Mania/Edit/Checks/CheckManiaAbnormalDifficultySettings.cs index ae0cc3aa4c..233c602c21 100644 --- a/osu.Game.Rulesets.Mania/Edit/Checks/CheckManiaAbnormalDifficultySettings.cs +++ b/osu.Game.Rulesets.Mania/Edit/Checks/CheckManiaAbnormalDifficultySettings.cs @@ -15,18 +15,19 @@ namespace osu.Game.Rulesets.Mania.Edit.Checks public override IEnumerable Run(BeatmapVerifierContext context) { var diff = context.Beatmap.Difficulty; + Issue? issue; - if (HasMoreThanOneDecimalPlace(diff.OverallDifficulty)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); + if (HasMoreThanOneDecimalPlace("Overall difficulty", diff.OverallDifficulty, out issue)) + yield return issue; - if (OutOfRange(diff.OverallDifficulty)) - yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); + if (OutOfRange("Overall difficulty", diff.OverallDifficulty, out issue)) + yield return issue; - if (HasMoreThanOneDecimalPlace(diff.DrainRate)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + if (HasMoreThanOneDecimalPlace("Drain rate", diff.DrainRate, out issue)) + yield return issue; - if (OutOfRange(diff.DrainRate)) - yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); + if (OutOfRange("Drain rate", diff.DrainRate, out issue)) + yield return issue; } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs index 7ad861f317..1c44d54633 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOsuAbnormalDifficultySettings.cs @@ -15,30 +15,31 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks public override IEnumerable Run(BeatmapVerifierContext context) { var diff = context.Beatmap.Difficulty; + Issue? issue; - if (HasMoreThanOneDecimalPlace(diff.ApproachRate)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Approach rate", diff.ApproachRate); + if (HasMoreThanOneDecimalPlace("Approach rate", diff.ApproachRate, out issue)) + yield return issue; - if (OutOfRange(diff.ApproachRate)) - yield return new IssueTemplateOutOfRange(this).Create("Approach rate", diff.ApproachRate); + if (OutOfRange("Approach rate", diff.ApproachRate, out issue)) + yield return issue; - if (HasMoreThanOneDecimalPlace(diff.OverallDifficulty)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); + if (HasMoreThanOneDecimalPlace("Overall difficulty", diff.OverallDifficulty, out issue)) + yield return issue; - if (OutOfRange(diff.OverallDifficulty)) - yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); + if (OutOfRange("Overall difficulty", diff.OverallDifficulty, out issue)) + yield return issue; - if (HasMoreThanOneDecimalPlace(diff.CircleSize)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Circle size", diff.CircleSize); + if (HasMoreThanOneDecimalPlace("Circle size", diff.CircleSize, out issue)) + yield return issue; - if (OutOfRange(diff.CircleSize)) - yield return new IssueTemplateOutOfRange(this).Create("Circle size", diff.CircleSize); + if (OutOfRange("Circle size", diff.CircleSize, out issue)) + yield return issue; - if (HasMoreThanOneDecimalPlace(diff.DrainRate)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + if (HasMoreThanOneDecimalPlace("Drain rate", diff.DrainRate, out issue)) + yield return issue; - if (OutOfRange(diff.DrainRate)) - yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); + if (OutOfRange("Drain rate", diff.DrainRate, out issue)) + yield return issue; } } } diff --git a/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs b/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs index 10e2867ca0..38ba7b1b01 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Checks/CheckTaikoAbnormalDifficultySettings.cs @@ -15,18 +15,19 @@ namespace osu.Game.Rulesets.Taiko.Edit.Checks public override IEnumerable Run(BeatmapVerifierContext context) { var diff = context.Beatmap.Difficulty; + Issue? issue; - if (HasMoreThanOneDecimalPlace(diff.OverallDifficulty)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Overall difficulty", diff.OverallDifficulty); + if (HasMoreThanOneDecimalPlace("Overall difficulty", diff.OverallDifficulty, out issue)) + yield return issue; - if (OutOfRange(diff.OverallDifficulty)) - yield return new IssueTemplateOutOfRange(this).Create("Overall difficulty", diff.OverallDifficulty); + if (OutOfRange("Overall difficulty", diff.OverallDifficulty, out issue)) + yield return issue; - if (HasMoreThanOneDecimalPlace(diff.DrainRate)) - yield return new IssueTemplateMoreThanOneDecimal(this).Create("Drain rate", diff.DrainRate); + if (HasMoreThanOneDecimalPlace("Drain rate", diff.DrainRate, out issue)) + yield return issue; - if (OutOfRange(diff.DrainRate)) - yield return new IssueTemplateOutOfRange(this).Create("Drain rate", diff.DrainRate); + if (OutOfRange("Drain rate", diff.DrainRate, out issue)) + yield return issue; } } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs index 93592a866b..638f0cfd53 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAbnormalDifficultySettings.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using osu.Game.Rulesets.Edit.Checks.Components; namespace osu.Game.Rulesets.Edit.Checks @@ -21,14 +22,18 @@ namespace osu.Game.Rulesets.Edit.Checks /// /// If the setting is out of the boundaries set by the editor (0 - 10) /// - protected bool OutOfRange(float setting) + protected bool OutOfRange(string setting, float value, [NotNullWhen(true)] out Issue? issue) { - return setting < 0f || setting > 10f; + bool hasIssue = value < 0f || value > 10f; + issue = hasIssue ? new IssueTemplateOutOfRange(this).Create(setting, value) : null; + return hasIssue; } - protected bool HasMoreThanOneDecimalPlace(float setting) + protected bool HasMoreThanOneDecimalPlace(string setting, float value, [NotNullWhen(true)] out Issue? issue) { - return float.Round(setting, 1) != setting; + bool hasIssue = float.Round(value, 1) != value; + issue = hasIssue ? new IssueTemplateMoreThanOneDecimal(this).Create(setting, value) : null; + return hasIssue; } public class IssueTemplateMoreThanOneDecimal : IssueTemplate From c24eb066dc4927580ffecfe79460819bc5486f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Mar 2024 12:03:24 +0100 Subject: [PATCH 889/915] Update tests to match new expected behaviour Co-authored-by: Vlad Frangu --- .../Filtering/FilterQueryParserTest.cs | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index bd706b5b4c..ea14412f55 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -273,12 +273,21 @@ namespace osu.Game.Tests.NonVisual.Filtering } [Test] - public void TestApplyStatusMatches() + public void TestApplyMultipleEqualityStatusQueries() { const string query = "status=ranked status=loved"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); - Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); + Assert.That(filterCriteria.OnlineStatus.Values, Is.Empty); + } + + [Test] + public void TestApplyEqualStatusQueryWithMultipleValues() + { + const string query = "status=ranked,loved"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.That(filterCriteria.OnlineStatus.Values, Is.Not.Empty); Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Ranked)); Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Loved)); } @@ -289,13 +298,43 @@ namespace osu.Game.Tests.NonVisual.Filtering const string query = "status>=r"; var filterCriteria = new FilterCriteria(); FilterQueryParser.ApplyQueries(filterCriteria, query); - Assert.IsNotEmpty(filterCriteria.OnlineStatus.Values); + Assert.That(filterCriteria.OnlineStatus.Values, Has.Count.EqualTo(4)); Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Ranked)); Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Approved)); Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Qualified)); Assert.That(filterCriteria.OnlineStatus.Values, Contains.Item(BeatmapOnlineStatus.Loved)); } + [Test] + public void TestApplyRangeStatusWithMultipleMatchesQuery() + { + const string query = "status>=r,l"; + var filterCriteria = new FilterCriteria(); + FilterQueryParser.ApplyQueries(filterCriteria, query); + Assert.That(filterCriteria.OnlineStatus.Values, Is.EquivalentTo(Enum.GetValues())); + } + + [Test] + public void TestApplyTwoRangeStatusQuery() + { + const string query = "status>r status Date: Tue, 26 Mar 2024 12:20:38 +0100 Subject: [PATCH 890/915] Update `OptionalSet` implementation to intersect across multiple filters rather than union --- osu.Game/Screens/Select/FilterCriteria.cs | 9 +- osu.Game/Screens/Select/FilterQueryParser.cs | 86 ++++++++++++-------- 2 files changed, 56 insertions(+), 39 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 6750b07aba..01b0e9b7d9 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -114,17 +114,18 @@ namespace osu.Game.Screens.Select public IRulesetFilterCriteria? RulesetCriteria { get; set; } - public struct OptionalSet : IEquatable> - where T : struct + public readonly struct OptionalSet : IEquatable> + where T : struct, Enum { - public bool HasFilter => Values.Count > 0; + public bool HasFilter => true; public bool IsInRange(T value) => Values.Contains(value); - public HashSet Values = new HashSet(); + public HashSet Values { get; } public OptionalSet() { + Values = Enum.GetValues().ToHashSet(); } public bool Equals(OptionalSet other) => Values.SetEquals(other.Values); diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 32b533e18d..4e49495f47 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Select return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt); case "status": - return TryUpdateCriteriaSet(ref criteria.OnlineStatus, op, value, tryParseEnum); + return TryUpdateCriteriaSet(ref criteria.OnlineStatus, op, value); case "creator": case "author": @@ -302,54 +302,70 @@ namespace osu.Game.Screens.Select /// /// Attempts to parse a keyword filter of type , - /// from the specified and . - /// If can be parsed into using , the function returns true + /// from the specified and . + /// If can be parsed successfully, the function returns true /// and the resulting range constraint is stored into the 's expected values. /// /// The to store the parsed data into, if successful. /// The operator for the keyword filter. - /// The value of the keyword filter. - /// Function used to determine if can be converted to type . - public static bool TryUpdateCriteriaSet(ref FilterCriteria.OptionalSet range, Operator op, string val, TryParseFunction parseFunction) - where T : struct, Enum - => parseFunction.Invoke(val, out var converted) && tryUpdateCriteriaSet(ref range, op, converted); - - private static bool tryUpdateCriteriaSet(ref FilterCriteria.OptionalSet range, Operator op, T pivotValue) + /// The value of the keyword filter. + public static bool TryUpdateCriteriaSet(ref FilterCriteria.OptionalSet range, Operator op, string filterValue) where T : struct, Enum { - var allDefinedValues = Enum.GetValues(); + var matchingValues = new HashSet(); - foreach (var val in allDefinedValues) + if (op == Operator.Equal && filterValue.Contains(',')) { - int compareResult = Comparer.Default.Compare(val, pivotValue); + string[] splitValues = filterValue.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - switch (op) + foreach (string splitValue in splitValues) { - case Operator.Less: - if (compareResult < 0) range.Values.Add(val); - break; - - case Operator.LessOrEqual: - if (compareResult <= 0) range.Values.Add(val); - break; - - case Operator.Equal: - if (compareResult == 0) range.Values.Add(val); - break; - - case Operator.GreaterOrEqual: - if (compareResult >= 0) range.Values.Add(val); - break; - - case Operator.Greater: - if (compareResult > 0) range.Values.Add(val); - break; - - default: + if (!tryParseEnum(splitValue, out var parsedValue)) return false; + + matchingValues.Add(parsedValue); + } + } + else + { + if (!tryParseEnum(filterValue, out var pivotValue)) + return false; + + var allDefinedValues = Enum.GetValues(); + + foreach (var val in allDefinedValues) + { + int compareResult = Comparer.Default.Compare(val, pivotValue); + + switch (op) + { + case Operator.Less: + if (compareResult < 0) matchingValues.Add(val); + break; + + case Operator.LessOrEqual: + if (compareResult <= 0) matchingValues.Add(val); + break; + + case Operator.Equal: + if (compareResult == 0) matchingValues.Add(val); + break; + + case Operator.GreaterOrEqual: + if (compareResult >= 0) matchingValues.Add(val); + break; + + case Operator.Greater: + if (compareResult > 0) matchingValues.Add(val); + break; + + default: + return false; + } } } + range.Values.IntersectWith(matchingValues); return true; } From 9474156df4bb33bda65c0bd2d68d565825f1b3d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2024 20:21:12 +0800 Subject: [PATCH 891/915] Improve equality implementations --- .../API/Requests/Responses/APIMenuContent.cs | 10 +--------- .../API/Requests/Responses/APIMenuImage.cs | 17 +++++------------ 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs b/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs index 7b53488030..6aad0f6c87 100644 --- a/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs +++ b/osu.Game/Online/API/Requests/Responses/APIMenuContent.cs @@ -23,15 +23,7 @@ namespace osu.Game.Online.API.Requests.Responses return Images.SequenceEqual(other.Images); } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - - if (obj.GetType() != GetType()) return false; - - return Equals((APIMenuContent)obj); - } + public override bool Equals(object? other) => other is APIMenuContent content && Equals(content); public override int GetHashCode() { diff --git a/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs b/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs index 42129ca96e..8aff08099a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs +++ b/osu.Game/Online/API/Requests/Responses/APIMenuImage.cs @@ -28,34 +28,27 @@ namespace osu.Game.Online.API.Requests.Responses /// The time at which this item should begin displaying. If null, will display immediately. /// [JsonProperty(@"begins")] - public DateTimeOffset? Begins { get; set; } + public DateTimeOffset? Begins { get; init; } /// /// The time at which this item should stop displaying. If null, will display indefinitely. /// [JsonProperty(@"expires")] - public DateTimeOffset? Expires { get; set; } + public DateTimeOffset? Expires { get; init; } public bool Equals(APIMenuImage? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return Image == other.Image && Url == other.Url; + return Image == other.Image && Url == other.Url && Begins == other.Begins && Expires == other.Expires; } - public override bool Equals(object? obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - - return Equals((APIMenuImage)obj); - } + public override bool Equals(object? other) => other is APIMenuImage content && Equals(content); public override int GetHashCode() { - return HashCode.Combine(Image, Url); + return HashCode.Combine(Image, Url, Begins, Expires); } } } From fd649edabae36603cccfc8a847a81de05b32f257 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2024 20:21:48 +0800 Subject: [PATCH 892/915] Also don't rotate images during a drag operation --- osu.Game/Screens/Menu/OnlineMenuBanner.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index 37bec7aa63..260c021719 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -120,8 +120,8 @@ namespace osu.Game.Screens.Menu { nextDisplay?.Cancel(); - // If the user is hovering a banner, don't rotate yet. - bool anyHovered = content.Any(i => i.IsHovered); + // If the user is interacting with a banner, don't rotate yet. + bool anyHovered = content.Any(i => i.IsHovered || i.IsDragged); if (!anyHovered) { @@ -242,6 +242,8 @@ namespace osu.Game.Screens.Menu .ScaleTo(1, 500, Easing.OutElastic); base.OnMouseUp(e); } + + protected override bool OnDragStart(DragStartEvent e) => true; } } } From e77d4c8cfaf66e1e717b0094632a3704b77e73f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2024 20:28:03 +0800 Subject: [PATCH 893/915] Remove unnecessary `Math.Max` --- osu.Game/Screens/Menu/OnlineMenuBanner.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/OnlineMenuBanner.cs b/osu.Game/Screens/Menu/OnlineMenuBanner.cs index 260c021719..6f98b73939 100644 --- a/osu.Game/Screens/Menu/OnlineMenuBanner.cs +++ b/osu.Game/Screens/Menu/OnlineMenuBanner.cs @@ -130,8 +130,8 @@ namespace osu.Game.Screens.Menu // To handle expiration simply, arrange all images in best-next order. // Fade in the first valid one, then handle fading out the last if required. var currentRotation = content - .Skip(Math.Max(0, previousIndex) + 1) - .Concat(content.Take(Math.Max(0, previousIndex) + 1)); + .Skip(previousIndex + 1) + .Concat(content.Take(previousIndex + 1)); // After the loop, displayIndex will be the new valid index or -1 if // none valid. From dee88573a756f9652628d13f2033cd4b78244870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Mar 2024 13:44:12 +0100 Subject: [PATCH 894/915] Fix test failure in visual browser I'm not sure why it's failing headless and I'm not particularly interested in finding that out right now. --- osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs index 380085ce04..60e42838d8 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Menu; +using osuTK; namespace osu.Game.Tests.Visual.Menus { @@ -95,7 +96,7 @@ namespace osu.Game.Tests.Visual.Menus } }); - AddUntilStep("wait for no image shown", () => !onlineMenuBanner.ChildrenOfType().Any()); + AddUntilStep("wait for no image shown", () => onlineMenuBanner.ChildrenOfType().Single().Size, () => Is.EqualTo(Vector2.Zero)); AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent()); From b4ccbc68e447f0dba68470d70510195bfad009f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2024 21:20:22 +0800 Subject: [PATCH 895/915] Fix failing test --- osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs index 60e42838d8..0b90fd13c3 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneOnlineMenuBanner.cs @@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual.Menus } }); - AddUntilStep("wait for no image shown", () => onlineMenuBanner.ChildrenOfType().Single().Size, () => Is.EqualTo(Vector2.Zero)); + AddUntilStep("wait for no image shown", () => onlineMenuBanner.ChildrenOfType().SingleOrDefault()?.Size, () => Is.EqualTo(Vector2.Zero)); AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent()); From a5f15a119e325f954e8f5358227269a99dec4e5e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2024 22:51:54 +0800 Subject: [PATCH 896/915] Apply rate adjust fix in all cases rather than specifically for `Clock.Rate == 1` --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index a14dfd4d64..de9a5aff3a 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -96,10 +96,8 @@ namespace osu.Game.Graphics.Containers // In the case of gameplay, we are usually within a hierarchy with the correct rate applied to our `Drawable.Clock`. // This means that the amount of early adjustment is adjusted in line with audio track rate changes. // But other cases like the osu! logo at the main menu won't correctly have this rate information. - // - // So for cases where the rate of the source isn't in sync with our hierarchy, let's assume we need to account for it locally. - if (Clock.Rate == 1 && BeatSyncSource.Clock.Rate != Clock.Rate) - early *= BeatSyncSource.Clock.Rate; + // We can adjust here to ensure the applied early activation always matches expectations. + early *= BeatSyncSource.Clock.Rate / Clock.Rate; currentTrackTime = BeatSyncSource.Clock.CurrentTime + early; From 4c1a1b54be7ffab08eb6e2713dbeca953f15044c Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 27 Mar 2024 00:07:51 +0900 Subject: [PATCH 897/915] Fix NVAPI startup exception on non-Windows platforms --- osu.Desktop/NVAPI.cs | 2 ++ osu.Desktop/Program.cs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/NVAPI.cs b/osu.Desktop/NVAPI.cs index 78a814c585..554f89a847 100644 --- a/osu.Desktop/NVAPI.cs +++ b/osu.Desktop/NVAPI.cs @@ -8,11 +8,13 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using osu.Framework.Logging; namespace osu.Desktop { [SuppressMessage("ReSharper", "InconsistentNaming")] + [SupportedOSPlatform("windows")] internal static class NVAPI { private const string osu_filename = "osu!.exe"; diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 73670adc49..2d7ec5aa5f 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -70,7 +70,8 @@ namespace osu.Desktop // NVIDIA profiles are based on the executable name of a process. // Lazer and stable share the same executable name. // Stable sets this setting to "Off", which may not be what we want, so let's force it back to the default "Auto" on startup. - NVAPI.ThreadedOptimisations = NvThreadControlSetting.OGL_THREAD_CONTROL_DEFAULT; + if (OperatingSystem.IsWindows()) + NVAPI.ThreadedOptimisations = NvThreadControlSetting.OGL_THREAD_CONTROL_DEFAULT; // Back up the cwd before DesktopGameHost changes it string cwd = Environment.CurrentDirectory; From 01a72d5afaa788e707308bea0764565ad1b044e6 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Tue, 26 Mar 2024 12:10:40 -0300 Subject: [PATCH 898/915] Fix combo not reversing properly depending on the order of selection --- .../Edit/CatchSelectionHandler.cs | 17 +++++++++-------- .../Edit/OsuSelectionHandler.cs | 17 +++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs index e3d2347c4d..f8fe9805e6 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs @@ -76,17 +76,15 @@ namespace osu.Game.Rulesets.Catch.Edit public override bool HandleReverse() { - var hitObjects = EditorBeatmap.SelectedHitObjects; + var hitObjects = EditorBeatmap.SelectedHitObjects + .OfType() + .OrderBy(obj => obj.StartTime) + .ToList(); double selectionStartTime = SelectedItems.Min(h => h.StartTime); double selectionEndTime = SelectedItems.Max(h => h.GetEndTime()); - var newComboOrder = hitObjects - .OfType() - .Select(obj => obj.NewCombo) - .ToList(); - - newComboOrder.Reverse(); + var newComboOrder = hitObjects.Select(obj => obj.NewCombo).ToList(); foreach (var h in hitObjects) { @@ -101,10 +99,13 @@ namespace osu.Game.Rulesets.Catch.Edit } } + // re-order objects again after flipping their times + hitObjects = [.. hitObjects.OrderBy(obj => obj.StartTime)]; + int i = 0; foreach (bool newCombo in newComboOrder) { - hitObjects.OfType().ToList()[i].NewCombo = newCombo; + hitObjects[i].NewCombo = newCombo; i++; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index df39ab8fce..0e889cab81 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -78,19 +78,17 @@ namespace osu.Game.Rulesets.Osu.Edit public override bool HandleReverse() { - var hitObjects = EditorBeatmap.SelectedHitObjects; + var hitObjects = EditorBeatmap.SelectedHitObjects + .OfType() + .OrderBy(obj => obj.StartTime) + .ToList(); double endTime = hitObjects.Max(h => h.GetEndTime()); double startTime = hitObjects.Min(h => h.StartTime); bool moreThanOneObject = hitObjects.Count > 1; - var newComboOrder = hitObjects - .OfType() - .Select(obj => obj.NewCombo) - .ToList(); - - newComboOrder.Reverse(); + var newComboOrder = hitObjects.Select(obj => obj.NewCombo).ToList(); foreach (var h in hitObjects) { @@ -104,10 +102,13 @@ namespace osu.Game.Rulesets.Osu.Edit } } + // re-order objects again after flipping their times + hitObjects = [.. hitObjects.OrderBy(obj => obj.StartTime)]; + int i = 0; foreach (bool newCombo in newComboOrder) { - hitObjects.OfType().ToList()[i].NewCombo = newCombo; + hitObjects[i].NewCombo = newCombo; i++; } From e02ad6cf94d3a9bba0cbcac6ecee5a0125f9da89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2024 23:38:34 +0800 Subject: [PATCH 899/915] Fix test regression --- osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModTouchDevice.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModTouchDevice.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModTouchDevice.cs index fdb1cac3e5..8c81431770 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModTouchDevice.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModTouchDevice.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods private SessionStatics statics { get; set; } = null!; private ScoreAccessibleSoloPlayer currentPlayer = null!; - private readonly ManualClock manualClock = new ManualClock { Rate = 0 }; + private readonly ManualClock manualClock = new ManualClock { Rate = 1 }; protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null) => new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(manualClock), Audio); From 0b29a762b8aa712d1a0b697f367ae809a0896f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 26 Mar 2024 17:36:00 +0100 Subject: [PATCH 900/915] Add precautionary guard to avoid potential div-by-zero Probably wouldn't happen outside of tests, but I'd rather not find out next release. --- osu.Game/Graphics/Containers/BeatSyncedContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index de9a5aff3a..7210371ebf 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -97,7 +97,8 @@ namespace osu.Game.Graphics.Containers // This means that the amount of early adjustment is adjusted in line with audio track rate changes. // But other cases like the osu! logo at the main menu won't correctly have this rate information. // We can adjust here to ensure the applied early activation always matches expectations. - early *= BeatSyncSource.Clock.Rate / Clock.Rate; + if (Clock.Rate > 0) + early *= BeatSyncSource.Clock.Rate / Clock.Rate; currentTrackTime = BeatSyncSource.Clock.CurrentTime + early; From 4490dbf8960214dcc9d3f67dbfc88ab5255c6e94 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 27 Mar 2024 13:37:47 +0900 Subject: [PATCH 901/915] Update diffcalc workflow --- .github/workflows/diffcalc.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml index 7a2dcecb9c..2ed176fe8d 100644 --- a/.github/workflows/diffcalc.yml +++ b/.github/workflows/diffcalc.yml @@ -110,10 +110,14 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' || contains(github.event.comment.body, '!diffcalc') }} steps: - name: Check permissions - if: ${{ github.event_name != 'workflow_dispatch' }} - uses: actions-cool/check-user-permission@a0668c9aec87f3875fc56170b6452a453e9dd819 # v2.2.0 - with: - require: 'write' + run: | + ALLOWED_USERS=(smoogipoo peppy bdach) + for i in "${ALLOWED_USERS[@]}"; do + if [[ "${{ github.actor }}" == "$i" ]]; then + exit 0 + fi + done + exit 1 create-comment: name: Create PR comment From 60c93d2c6de6690913ba6f9552615116c2470a29 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Wed, 27 Mar 2024 08:22:51 -0300 Subject: [PATCH 902/915] Add reverse pattern visual tests --- .../Editor/TestSceneCatchReverseSelection.cs | 313 ++++++++++++++++ .../Editor/TestSceneOsuReverseSelection.cs | 347 ++++++++++++++++++ 2 files changed, 660 insertions(+) create mode 100644 osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchReverseSelection.cs create mode 100644 osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuReverseSelection.cs diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchReverseSelection.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchReverseSelection.cs new file mode 100644 index 0000000000..c8a48f76eb --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchReverseSelection.cs @@ -0,0 +1,313 @@ +// 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.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Objects; +using osu.Game.Tests.Beatmaps; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Rulesets.Catch.Tests.Editor +{ + [TestFixture] + public partial class TestSceneCatchReverseSelection : TestSceneEditor + { + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); + + [Test] + public void TestReverseSelectionTwoFruits() + { + float fruit1OldX = default; + float fruit2OldX = default; + + addObjects([ + new Fruit + { + StartTime = 200, + X = fruit1OldX = 0, + }, + new Fruit + { + StartTime = 400, + X = fruit2OldX = 20, + } + ]); + + selectEverything(); + reverseSelection(); + + AddAssert("fruit1 is at fruit2's X", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).EffectiveX, + () => Is.EqualTo(fruit2OldX) + ); + + AddAssert("fruit2 is at fruit1's X", + () => EditorBeatmap.HitObjects.OfType().ElementAt(1).EffectiveX, + () => Is.EqualTo(fruit1OldX) + ); + + AddAssert("fruit2 is not a new combo", + () => EditorBeatmap.HitObjects.OfType().ElementAt(1).NewCombo, + () => Is.EqualTo(false) + ); + } + + [Test] + public void TestReverseSelectionThreeFruits() + { + float fruit1OldX = default; + float fruit2OldX = default; + float fruit3OldX = default; + + addObjects([ + new Fruit + { + StartTime = 200, + X = fruit1OldX = 0, + }, + new Fruit + { + StartTime = 400, + X = fruit2OldX = 20, + }, + new Fruit + { + StartTime = 600, + X = fruit3OldX = 40, + } + ]); + + selectEverything(); + reverseSelection(); + + AddAssert("fruit1 is at fruit3's X", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).EffectiveX, + () => Is.EqualTo(fruit3OldX) + ); + + AddAssert("fruit2's X is unchanged", + () => EditorBeatmap.HitObjects.OfType().ElementAt(1).EffectiveX, + () => Is.EqualTo(fruit2OldX) + ); + + AddAssert("fruit3's is at fruit1's X", + () => EditorBeatmap.HitObjects.OfType().ElementAt(2).EffectiveX, + () => Is.EqualTo(fruit1OldX) + ); + + AddAssert("fruit3 is not a new combo", + () => EditorBeatmap.HitObjects.OfType().ElementAt(2).NewCombo, + () => Is.EqualTo(false) + ); + } + + [Test] + public void TestReverseSelectionFruitAndJuiceStream() + { + addObjects([ + new Fruit + { + StartTime = 200, + X = 0, + }, + new JuiceStream + { + StartTime = 400, + X = 20, + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(50)) + } + } + } + ]); + + selectEverything(); + reverseSelection(); + + AddAssert("First element is juice stream", + () => EditorBeatmap.HitObjects.First().GetType(), + () => Is.EqualTo(typeof(JuiceStream)) + ); + + AddAssert("Last element is fruit", + () => EditorBeatmap.HitObjects.Last().GetType(), + () => Is.EqualTo(typeof(Fruit)) + ); + + AddAssert("Fruit is not new combo", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).NewCombo, + () => Is.EqualTo(false) + ); + } + + [Test] + public void TestReverseSelectionTwoFruitsAndJuiceStream() + { + addObjects([ + new Fruit + { + StartTime = 200, + X = 0, + }, + new Fruit + { + StartTime = 400, + X = 20, + }, + new JuiceStream + { + StartTime = 600, + X = 40, + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(50)) + } + } + } + ]); + + selectEverything(); + reverseSelection(); + + AddAssert("First element is juice stream", + () => EditorBeatmap.HitObjects.First().GetType(), + () => Is.EqualTo(typeof(JuiceStream)) + ); + + AddAssert("Middle element is Fruit", + () => EditorBeatmap.HitObjects.ElementAt(1).GetType(), + () => Is.EqualTo(typeof(Fruit)) + ); + + AddAssert("Last element is Fruit", + () => EditorBeatmap.HitObjects.Last().GetType(), + () => Is.EqualTo(typeof(Fruit)) + ); + + AddAssert("Last fruit is not new combo", + () => EditorBeatmap.HitObjects.OfType().Last().NewCombo, + () => Is.EqualTo(false) + ); + } + + [Test] + public void TestReverseSelectionTwoCombos() + { + float fruit1OldX = default; + float fruit2OldX = default; + float fruit3OldX = default; + + float fruit4OldX = default; + float fruit5OldX = default; + float fruit6OldX = default; + + addObjects([ + new Fruit + { + StartTime = 200, + X = fruit1OldX = 0, + }, + new Fruit + { + StartTime = 400, + X = fruit2OldX = 20, + }, + new Fruit + { + StartTime = 600, + X = fruit3OldX = 40, + }, + + new Fruit + { + StartTime = 800, + NewCombo = true, + X = fruit4OldX = 60, + }, + new Fruit + { + StartTime = 1000, + X = fruit5OldX = 80, + }, + new Fruit + { + StartTime = 1200, + X = fruit6OldX = 100, + } + ]); + + selectEverything(); + reverseSelection(); + + AddAssert("fruit1 is at fruit6 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).EffectiveX, + () => Is.EqualTo(fruit6OldX) + ); + + AddAssert("fruit2 is at fruit5 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(1).EffectiveX, + () => Is.EqualTo(fruit5OldX) + ); + + AddAssert("fruit3 is at fruit4 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(2).EffectiveX, + () => Is.EqualTo(fruit4OldX) + ); + + AddAssert("fruit4 is at fruit3 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(3).EffectiveX, + () => Is.EqualTo(fruit3OldX) + ); + + AddAssert("fruit5 is at fruit2 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(4).EffectiveX, + () => Is.EqualTo(fruit2OldX) + ); + + AddAssert("fruit6 is at fruit1 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(5).EffectiveX, + () => Is.EqualTo(fruit1OldX) + ); + + AddAssert("fruit1 is new combo", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).NewCombo, + () => Is.EqualTo(true) + ); + + AddAssert("fruit4 is new combo", + () => EditorBeatmap.HitObjects.OfType().ElementAt(3).NewCombo, + () => Is.EqualTo(true) + ); + } + + private void addObjects(CatchHitObject[] hitObjects) => AddStep("Add objects", () => EditorBeatmap.AddRange(hitObjects)); + + private void selectEverything() + { + AddStep("Select everything", () => + { + EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + }); + } + + private void reverseSelection() + { + AddStep("Reverse selection", () => + { + InputManager.PressKey(Key.LControl); + InputManager.Key(Key.G); + InputManager.ReleaseKey(Key.LControl); + }); + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuReverseSelection.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuReverseSelection.cs new file mode 100644 index 0000000000..33104288ab --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuReverseSelection.cs @@ -0,0 +1,347 @@ +// 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.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Tests.Beatmaps; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Rulesets.Osu.Tests.Editor +{ + [TestFixture] + public partial class TestSceneOsuReverseSelection : TestSceneOsuEditor + { + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); + + [Test] + public void TestReverseSelectionTwoCircles() + { + Vector2 circle1OldPosition = default; + Vector2 circle2OldPosition = default; + + AddStep("Add circles", () => + { + var circle1 = new HitCircle + { + StartTime = 0, + Position = circle1OldPosition = new Vector2(208, 240) + }; + var circle2 = new HitCircle + { + StartTime = 200, + Position = circle2OldPosition = new Vector2(256, 144) + }; + + EditorBeatmap.AddRange([circle1, circle2]); + }); + + AddStep("Select circles", () => + { + EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + }); + + AddStep("Reverse selection", () => + { + InputManager.PressKey(Key.LControl); + InputManager.Key(Key.G); + InputManager.ReleaseKey(Key.LControl); + }); + + AddAssert("circle1 is at circle2 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, + () => Is.EqualTo(circle2OldPosition) + ); + + AddAssert("circle2 is at circle1 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(1).Position, + () => Is.EqualTo(circle1OldPosition) + ); + + AddAssert("circle2 is not a new combo", + () => EditorBeatmap.HitObjects.OfType().ElementAt(1).NewCombo, + () => Is.EqualTo(false) + ); + } + + [Test] + public void TestReverseSelectionThreeCircles() + { + Vector2 circle1OldPosition = default; + Vector2 circle2OldPosition = default; + Vector2 circle3OldPosition = default; + + AddStep("Add circles", () => + { + var circle1 = new HitCircle + { + StartTime = 0, + Position = circle1OldPosition = new Vector2(208, 240) + }; + var circle2 = new HitCircle + { + StartTime = 200, + Position = circle2OldPosition = new Vector2(256, 144) + }; + var circle3 = new HitCircle + { + StartTime = 400, + Position = circle3OldPosition = new Vector2(304, 240) + }; + + EditorBeatmap.AddRange([circle1, circle2, circle3]); + }); + + AddStep("Select circles", () => + { + EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + }); + + AddStep("Reverse selection", () => + { + InputManager.PressKey(Key.LControl); + InputManager.Key(Key.G); + InputManager.ReleaseKey(Key.LControl); + }); + + AddAssert("circle1 is at circle3 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, + () => Is.EqualTo(circle3OldPosition) + ); + + AddAssert("circle3 is at circle1 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(2).Position, + () => Is.EqualTo(circle1OldPosition) + ); + + AddAssert("circle3 is not a new combo", + () => EditorBeatmap.HitObjects.OfType().ElementAt(2).NewCombo, + () => Is.EqualTo(false) + ); + } + + [Test] + public void TestReverseSelectionCircleAndSlider() + { + Vector2 circleOldPosition = default; + Vector2 sliderHeadOldPosition = default; + Vector2 sliderTailOldPosition = default; + + AddStep("Add objects", () => + { + var circle = new HitCircle + { + StartTime = 0, + Position = circleOldPosition = new Vector2(208, 240) + }; + var slider = new Slider + { + StartTime = 200, + Position = sliderHeadOldPosition = new Vector2(257, 144), + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(100)) + } + } + }; + + sliderTailOldPosition = slider.EndPosition; + + EditorBeatmap.AddRange([circle, slider]); + }); + + AddStep("Select objects", () => + { + var circle = (HitCircle)EditorBeatmap.HitObjects[0]; + var slider = (Slider)EditorBeatmap.HitObjects[1]; + + EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + }); + + AddStep("Reverse selection", () => + { + InputManager.PressKey(Key.LControl); + InputManager.Key(Key.G); + InputManager.ReleaseKey(Key.LControl); + }); + + AddAssert("circle is at the same position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, + () => Is.EqualTo(circleOldPosition) + ); + + AddAssert("Slider head is at slider tail", () => + Vector2.Distance(EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, sliderTailOldPosition) < 1); + + AddAssert("Slider tail is at slider head", () => + Vector2.Distance(EditorBeatmap.HitObjects.OfType().ElementAt(0).EndPosition, sliderHeadOldPosition) < 1); + } + + [Test] + public void TestReverseSelectionTwoCirclesAndSlider() + { + Vector2 circle1OldPosition = default; + Vector2 circle2OldPosition = default; + + Vector2 sliderHeadOldPosition = default; + Vector2 sliderTailOldPosition = default; + + AddStep("Add objects", () => + { + var circle1 = new HitCircle + { + StartTime = 0, + Position = circle1OldPosition = new Vector2(208, 240) + }; + var circle2 = new HitCircle + { + StartTime = 200, + Position = circle2OldPosition = new Vector2(256, 144) + }; + var slider = new Slider + { + StartTime = 200, + Position = sliderHeadOldPosition = new Vector2(304, 240), + Path = new SliderPath + { + ControlPoints = + { + new PathControlPoint(), + new PathControlPoint(new Vector2(100)) + } + } + }; + + sliderTailOldPosition = slider.EndPosition; + + EditorBeatmap.AddRange([circle1, circle2, slider]); + }); + + AddStep("Select objects", () => + { + EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + }); + + AddStep("Reverse selection", () => + { + InputManager.PressKey(Key.LControl); + InputManager.Key(Key.G); + InputManager.ReleaseKey(Key.LControl); + }); + + AddAssert("circle1 is at circle2 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, + () => Is.EqualTo(circle2OldPosition) + ); + + AddAssert("circle2 is at circle1 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(1).Position, + () => Is.EqualTo(circle1OldPosition) + ); + + AddAssert("Slider head is at slider tail", () => + Vector2.Distance(EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, sliderTailOldPosition) < 1); + + AddAssert("Slider tail is at slider head", () => + Vector2.Distance(EditorBeatmap.HitObjects.OfType().ElementAt(0).EndPosition, sliderHeadOldPosition) < 1); + } + + [Test] + public void TestReverseSelectionTwoCombos() + { + Vector2 circle1OldPosition = default; + Vector2 circle2OldPosition = default; + Vector2 circle3OldPosition = default; + + Vector2 circle4OldPosition = default; + Vector2 circle5OldPosition = default; + Vector2 circle6OldPosition = default; + + AddStep("Add circles", () => + { + var circle1 = new HitCircle + { + StartTime = 0, + Position = circle1OldPosition = new Vector2(216, 240) + }; + var circle2 = new HitCircle + { + StartTime = 200, + Position = circle2OldPosition = new Vector2(120, 192) + }; + var circle3 = new HitCircle + { + StartTime = 400, + Position = circle3OldPosition = new Vector2(216, 144) + }; + + var circle4 = new HitCircle + { + StartTime = 646, + NewCombo = true, + Position = circle4OldPosition = new Vector2(296, 240) + }; + var circle5 = new HitCircle + { + StartTime = 846, + Position = circle5OldPosition = new Vector2(392, 162) + }; + var circle6 = new HitCircle + { + StartTime = 1046, + Position = circle6OldPosition = new Vector2(296, 144) + }; + + EditorBeatmap.AddRange([circle1, circle2, circle3, circle4, circle5, circle6]); + }); + + AddStep("Select circles", () => + { + EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + }); + + AddStep("Reverse selection", () => + { + InputManager.PressKey(Key.LControl); + InputManager.Key(Key.G); + InputManager.ReleaseKey(Key.LControl); + }); + + AddAssert("circle1 is at circle6 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, + () => Is.EqualTo(circle6OldPosition) + ); + + AddAssert("circle2 is at circle5 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(1).Position, + () => Is.EqualTo(circle5OldPosition) + ); + + AddAssert("circle3 is at circle4 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(2).Position, + () => Is.EqualTo(circle4OldPosition) + ); + + AddAssert("circle4 is at circle3 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(3).Position, + () => Is.EqualTo(circle3OldPosition) + ); + + AddAssert("circle5 is at circle2 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(4).Position, + () => Is.EqualTo(circle2OldPosition) + ); + + AddAssert("circle6 is at circle1 position", + () => EditorBeatmap.HitObjects.OfType().ElementAt(5).Position, + () => Is.EqualTo(circle1OldPosition) + ); + } + } +} From 53900d5472ac14a41003f5353bd704e42e245a7b Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 27 Mar 2024 18:56:26 +0100 Subject: [PATCH 903/915] Fix tests failing locally due to not using invariant culture --- osu.Game/Skinning/SkinImporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinImporter.cs b/osu.Game/Skinning/SkinImporter.cs index 3e948a8afb..59c7f0ba26 100644 --- a/osu.Game/Skinning/SkinImporter.cs +++ b/osu.Game/Skinning/SkinImporter.cs @@ -132,7 +132,7 @@ namespace osu.Game.Skinning { // skins without a skin.ini are supposed to import using the "latest version" spec. // see https://github.com/peppy/osu-stable-reference/blob/1531237b63392e82c003c712faa028406073aa8f/osu!/Graphics/Skinning/SkinManager.cs#L297-L298 - newLines.Add($"Version: {SkinConfiguration.LATEST_VERSION}"); + newLines.Add(FormattableString.Invariant($"Version: {SkinConfiguration.LATEST_VERSION}")); // In the case a skin doesn't have a skin.ini yet, let's create one. writeNewSkinIni(); From a9cbabf71135ff97c587a1c01079b56850ef27f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 28 Mar 2024 10:05:26 +0100 Subject: [PATCH 904/915] Simplify tests --- .../Editor/TestSceneCatchReverseSelection.cs | 196 ++++++------------ .../Editor/TestSceneOsuReverseSelection.cs | 177 ++++++---------- 2 files changed, 133 insertions(+), 240 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchReverseSelection.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchReverseSelection.cs index c8a48f76eb..36a0e3388e 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchReverseSelection.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchReverseSelection.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.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; @@ -20,93 +21,78 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor [Test] public void TestReverseSelectionTwoFruits() { - float fruit1OldX = default; - float fruit2OldX = default; + CatchHitObject[] objects = null!; + bool[] newCombos = null!; addObjects([ new Fruit { StartTime = 200, - X = fruit1OldX = 0, + X = 0, }, new Fruit { StartTime = 400, - X = fruit2OldX = 20, + X = 20, } ]); + AddStep("store objects & new combo data", () => + { + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); + }); + selectEverything(); reverseSelection(); - AddAssert("fruit1 is at fruit2's X", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).EffectiveX, - () => Is.EqualTo(fruit2OldX) - ); - - AddAssert("fruit2 is at fruit1's X", - () => EditorBeatmap.HitObjects.OfType().ElementAt(1).EffectiveX, - () => Is.EqualTo(fruit1OldX) - ); - - AddAssert("fruit2 is not a new combo", - () => EditorBeatmap.HitObjects.OfType().ElementAt(1).NewCombo, - () => Is.EqualTo(false) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); } [Test] public void TestReverseSelectionThreeFruits() { - float fruit1OldX = default; - float fruit2OldX = default; - float fruit3OldX = default; + CatchHitObject[] objects = null!; + bool[] newCombos = null!; addObjects([ new Fruit { StartTime = 200, - X = fruit1OldX = 0, + X = 0, }, new Fruit { StartTime = 400, - X = fruit2OldX = 20, + X = 20, }, new Fruit { StartTime = 600, - X = fruit3OldX = 40, + X = 40, } ]); + AddStep("store objects & new combo data", () => + { + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); + }); + selectEverything(); reverseSelection(); - AddAssert("fruit1 is at fruit3's X", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).EffectiveX, - () => Is.EqualTo(fruit3OldX) - ); - - AddAssert("fruit2's X is unchanged", - () => EditorBeatmap.HitObjects.OfType().ElementAt(1).EffectiveX, - () => Is.EqualTo(fruit2OldX) - ); - - AddAssert("fruit3's is at fruit1's X", - () => EditorBeatmap.HitObjects.OfType().ElementAt(2).EffectiveX, - () => Is.EqualTo(fruit1OldX) - ); - - AddAssert("fruit3 is not a new combo", - () => EditorBeatmap.HitObjects.OfType().ElementAt(2).NewCombo, - () => Is.EqualTo(false) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); } [Test] public void TestReverseSelectionFruitAndJuiceStream() { + CatchHitObject[] objects = null!; + bool[] newCombos = null!; + addObjects([ new Fruit { @@ -128,28 +114,25 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor } ]); + AddStep("store objects & new combo data", () => + { + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); + }); + selectEverything(); reverseSelection(); - AddAssert("First element is juice stream", - () => EditorBeatmap.HitObjects.First().GetType(), - () => Is.EqualTo(typeof(JuiceStream)) - ); - - AddAssert("Last element is fruit", - () => EditorBeatmap.HitObjects.Last().GetType(), - () => Is.EqualTo(typeof(Fruit)) - ); - - AddAssert("Fruit is not new combo", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).NewCombo, - () => Is.EqualTo(false) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); } [Test] public void TestReverseSelectionTwoFruitsAndJuiceStream() { + CatchHitObject[] objects = null!; + bool[] newCombos = null!; + addObjects([ new Fruit { @@ -176,122 +159,79 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor } ]); + AddStep("store objects & new combo data", () => + { + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); + }); + selectEverything(); reverseSelection(); - AddAssert("First element is juice stream", - () => EditorBeatmap.HitObjects.First().GetType(), - () => Is.EqualTo(typeof(JuiceStream)) - ); - - AddAssert("Middle element is Fruit", - () => EditorBeatmap.HitObjects.ElementAt(1).GetType(), - () => Is.EqualTo(typeof(Fruit)) - ); - - AddAssert("Last element is Fruit", - () => EditorBeatmap.HitObjects.Last().GetType(), - () => Is.EqualTo(typeof(Fruit)) - ); - - AddAssert("Last fruit is not new combo", - () => EditorBeatmap.HitObjects.OfType().Last().NewCombo, - () => Is.EqualTo(false) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); } [Test] public void TestReverseSelectionTwoCombos() { - float fruit1OldX = default; - float fruit2OldX = default; - float fruit3OldX = default; - - float fruit4OldX = default; - float fruit5OldX = default; - float fruit6OldX = default; + CatchHitObject[] objects = null!; + bool[] newCombos = null!; addObjects([ new Fruit { StartTime = 200, - X = fruit1OldX = 0, + X = 0, }, new Fruit { StartTime = 400, - X = fruit2OldX = 20, + X = 20, }, new Fruit { StartTime = 600, - X = fruit3OldX = 40, + X = 40, }, new Fruit { StartTime = 800, NewCombo = true, - X = fruit4OldX = 60, + X = 60, }, new Fruit { StartTime = 1000, - X = fruit5OldX = 80, + X = 80, }, new Fruit { StartTime = 1200, - X = fruit6OldX = 100, + X = 100, } ]); + AddStep("store objects & new combo data", () => + { + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); + }); + selectEverything(); reverseSelection(); - AddAssert("fruit1 is at fruit6 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).EffectiveX, - () => Is.EqualTo(fruit6OldX) - ); - - AddAssert("fruit2 is at fruit5 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(1).EffectiveX, - () => Is.EqualTo(fruit5OldX) - ); - - AddAssert("fruit3 is at fruit4 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(2).EffectiveX, - () => Is.EqualTo(fruit4OldX) - ); - - AddAssert("fruit4 is at fruit3 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(3).EffectiveX, - () => Is.EqualTo(fruit3OldX) - ); - - AddAssert("fruit5 is at fruit2 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(4).EffectiveX, - () => Is.EqualTo(fruit2OldX) - ); - - AddAssert("fruit6 is at fruit1 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(5).EffectiveX, - () => Is.EqualTo(fruit1OldX) - ); - - AddAssert("fruit1 is new combo", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).NewCombo, - () => Is.EqualTo(true) - ); - - AddAssert("fruit4 is new combo", - () => EditorBeatmap.HitObjects.OfType().ElementAt(3).NewCombo, - () => Is.EqualTo(true) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); } private void addObjects(CatchHitObject[] hitObjects) => AddStep("Add objects", () => EditorBeatmap.AddRange(hitObjects)); + private IEnumerable getObjects() => EditorBeatmap.HitObjects.OfType(); + + private IEnumerable getObjectNewCombos() => getObjects().Select(ho => ho.NewCombo); + private void selectEverything() { AddStep("Select everything", () => diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuReverseSelection.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuReverseSelection.cs index 33104288ab..28c1577fcb 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuReverseSelection.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuReverseSelection.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.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; @@ -20,30 +21,33 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [Test] public void TestReverseSelectionTwoCircles() { - Vector2 circle1OldPosition = default; - Vector2 circle2OldPosition = default; + OsuHitObject[] objects = null!; + bool[] newCombos = null!; AddStep("Add circles", () => { var circle1 = new HitCircle { StartTime = 0, - Position = circle1OldPosition = new Vector2(208, 240) + Position = new Vector2(208, 240) }; var circle2 = new HitCircle { StartTime = 200, - Position = circle2OldPosition = new Vector2(256, 144) + Position = new Vector2(256, 144) }; EditorBeatmap.AddRange([circle1, circle2]); }); - AddStep("Select circles", () => + AddStep("store objects & new combo data", () => { - EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); }); + AddStep("Select circles", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("Reverse selection", () => { InputManager.PressKey(Key.LControl); @@ -51,55 +55,45 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor InputManager.ReleaseKey(Key.LControl); }); - AddAssert("circle1 is at circle2 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, - () => Is.EqualTo(circle2OldPosition) - ); - - AddAssert("circle2 is at circle1 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(1).Position, - () => Is.EqualTo(circle1OldPosition) - ); - - AddAssert("circle2 is not a new combo", - () => EditorBeatmap.HitObjects.OfType().ElementAt(1).NewCombo, - () => Is.EqualTo(false) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); } [Test] public void TestReverseSelectionThreeCircles() { - Vector2 circle1OldPosition = default; - Vector2 circle2OldPosition = default; - Vector2 circle3OldPosition = default; + OsuHitObject[] objects = null!; + bool[] newCombos = null!; AddStep("Add circles", () => { var circle1 = new HitCircle { StartTime = 0, - Position = circle1OldPosition = new Vector2(208, 240) + Position = new Vector2(208, 240) }; var circle2 = new HitCircle { StartTime = 200, - Position = circle2OldPosition = new Vector2(256, 144) + Position = new Vector2(256, 144) }; var circle3 = new HitCircle { StartTime = 400, - Position = circle3OldPosition = new Vector2(304, 240) + Position = new Vector2(304, 240) }; EditorBeatmap.AddRange([circle1, circle2, circle3]); }); - AddStep("Select circles", () => + AddStep("store objects & new combo data", () => { - EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); }); + AddStep("Select circles", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("Reverse selection", () => { InputManager.PressKey(Key.LControl); @@ -107,26 +101,16 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor InputManager.ReleaseKey(Key.LControl); }); - AddAssert("circle1 is at circle3 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, - () => Is.EqualTo(circle3OldPosition) - ); - - AddAssert("circle3 is at circle1 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(2).Position, - () => Is.EqualTo(circle1OldPosition) - ); - - AddAssert("circle3 is not a new combo", - () => EditorBeatmap.HitObjects.OfType().ElementAt(2).NewCombo, - () => Is.EqualTo(false) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); } [Test] public void TestReverseSelectionCircleAndSlider() { - Vector2 circleOldPosition = default; + OsuHitObject[] objects = null!; + bool[] newCombos = null!; + Vector2 sliderHeadOldPosition = default; Vector2 sliderTailOldPosition = default; @@ -135,7 +119,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor var circle = new HitCircle { StartTime = 0, - Position = circleOldPosition = new Vector2(208, 240) + Position = new Vector2(208, 240) }; var slider = new Slider { @@ -156,14 +140,14 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor EditorBeatmap.AddRange([circle, slider]); }); - AddStep("Select objects", () => + AddStep("store objects & new combo data", () => { - var circle = (HitCircle)EditorBeatmap.HitObjects[0]; - var slider = (Slider)EditorBeatmap.HitObjects[1]; - - EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); }); + AddStep("Select objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("Reverse selection", () => { InputManager.PressKey(Key.LControl); @@ -171,10 +155,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor InputManager.ReleaseKey(Key.LControl); }); - AddAssert("circle is at the same position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, - () => Is.EqualTo(circleOldPosition) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); AddAssert("Slider head is at slider tail", () => Vector2.Distance(EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, sliderTailOldPosition) < 1); @@ -186,8 +168,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [Test] public void TestReverseSelectionTwoCirclesAndSlider() { - Vector2 circle1OldPosition = default; - Vector2 circle2OldPosition = default; + OsuHitObject[] objects = null!; + bool[] newCombos = null!; Vector2 sliderHeadOldPosition = default; Vector2 sliderTailOldPosition = default; @@ -197,12 +179,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor var circle1 = new HitCircle { StartTime = 0, - Position = circle1OldPosition = new Vector2(208, 240) + Position = new Vector2(208, 240) }; var circle2 = new HitCircle { StartTime = 200, - Position = circle2OldPosition = new Vector2(256, 144) + Position = new Vector2(256, 144) }; var slider = new Slider { @@ -223,11 +205,14 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor EditorBeatmap.AddRange([circle1, circle2, slider]); }); - AddStep("Select objects", () => + AddStep("store objects & new combo data", () => { - EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); }); + AddStep("Select objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("Reverse selection", () => { InputManager.PressKey(Key.LControl); @@ -235,15 +220,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor InputManager.ReleaseKey(Key.LControl); }); - AddAssert("circle1 is at circle2 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, - () => Is.EqualTo(circle2OldPosition) - ); - - AddAssert("circle2 is at circle1 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(1).Position, - () => Is.EqualTo(circle1OldPosition) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); AddAssert("Slider head is at slider tail", () => Vector2.Distance(EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, sliderTailOldPosition) < 1); @@ -255,57 +233,55 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [Test] public void TestReverseSelectionTwoCombos() { - Vector2 circle1OldPosition = default; - Vector2 circle2OldPosition = default; - Vector2 circle3OldPosition = default; - - Vector2 circle4OldPosition = default; - Vector2 circle5OldPosition = default; - Vector2 circle6OldPosition = default; + OsuHitObject[] objects = null!; + bool[] newCombos = null!; AddStep("Add circles", () => { var circle1 = new HitCircle { StartTime = 0, - Position = circle1OldPosition = new Vector2(216, 240) + Position = new Vector2(216, 240) }; var circle2 = new HitCircle { StartTime = 200, - Position = circle2OldPosition = new Vector2(120, 192) + Position = new Vector2(120, 192) }; var circle3 = new HitCircle { StartTime = 400, - Position = circle3OldPosition = new Vector2(216, 144) + Position = new Vector2(216, 144) }; var circle4 = new HitCircle { StartTime = 646, NewCombo = true, - Position = circle4OldPosition = new Vector2(296, 240) + Position = new Vector2(296, 240) }; var circle5 = new HitCircle { StartTime = 846, - Position = circle5OldPosition = new Vector2(392, 162) + Position = new Vector2(392, 162) }; var circle6 = new HitCircle { StartTime = 1046, - Position = circle6OldPosition = new Vector2(296, 144) + Position = new Vector2(296, 144) }; EditorBeatmap.AddRange([circle1, circle2, circle3, circle4, circle5, circle6]); }); - AddStep("Select circles", () => + AddStep("store objects & new combo data", () => { - EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects); + objects = getObjects().ToArray(); + newCombos = getObjectNewCombos().ToArray(); }); + AddStep("Select circles", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + AddStep("Reverse selection", () => { InputManager.PressKey(Key.LControl); @@ -313,35 +289,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor InputManager.ReleaseKey(Key.LControl); }); - AddAssert("circle1 is at circle6 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(0).Position, - () => Is.EqualTo(circle6OldPosition) - ); - - AddAssert("circle2 is at circle5 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(1).Position, - () => Is.EqualTo(circle5OldPosition) - ); - - AddAssert("circle3 is at circle4 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(2).Position, - () => Is.EqualTo(circle4OldPosition) - ); - - AddAssert("circle4 is at circle3 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(3).Position, - () => Is.EqualTo(circle3OldPosition) - ); - - AddAssert("circle5 is at circle2 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(4).Position, - () => Is.EqualTo(circle2OldPosition) - ); - - AddAssert("circle6 is at circle1 position", - () => EditorBeatmap.HitObjects.OfType().ElementAt(5).Position, - () => Is.EqualTo(circle1OldPosition) - ); + AddAssert("objects reversed", getObjects, () => Is.EqualTo(objects.Reverse())); + AddAssert("new combo positions preserved", getObjectNewCombos, () => Is.EqualTo(newCombos)); } + + private IEnumerable getObjects() => EditorBeatmap.HitObjects.OfType(); + + private IEnumerable getObjectNewCombos() => getObjects().Select(ho => ho.NewCombo); } } From 2f786ffc32d925d15d3417f696ac3a046dc2af80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 28 Mar 2024 10:12:27 +0100 Subject: [PATCH 905/915] Simplify implementation --- .../Edit/CatchSelectionHandler.cs | 21 +++++++++---------- .../Edit/OsuSelectionHandler.cs | 21 +++++++++---------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs index f8fe9805e6..a2784126eb 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs @@ -77,13 +77,16 @@ namespace osu.Game.Rulesets.Catch.Edit public override bool HandleReverse() { var hitObjects = EditorBeatmap.SelectedHitObjects - .OfType() - .OrderBy(obj => obj.StartTime) - .ToList(); + .OfType() + .OrderBy(obj => obj.StartTime) + .ToList(); double selectionStartTime = SelectedItems.Min(h => h.StartTime); double selectionEndTime = SelectedItems.Max(h => h.GetEndTime()); + // the expectation is that even if the objects themselves are reversed temporally, + // the position of new combos in the selection should remain the same. + // preserve it for later before doing the reversal. var newComboOrder = hitObjects.Select(obj => obj.NewCombo).ToList(); foreach (var h in hitObjects) @@ -99,15 +102,11 @@ namespace osu.Game.Rulesets.Catch.Edit } } - // re-order objects again after flipping their times - hitObjects = [.. hitObjects.OrderBy(obj => obj.StartTime)]; + // re-order objects by start time again after reversing, and restore new combo flag positioning + hitObjects = hitObjects.OrderBy(obj => obj.StartTime).ToList(); - int i = 0; - foreach (bool newCombo in newComboOrder) - { - hitObjects[i].NewCombo = newCombo; - i++; - } + for (int i = 0; i < hitObjects.Count; ++i) + hitObjects[i].NewCombo = newComboOrder[i]; return true; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 0e889cab81..b33272968b 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -79,15 +79,18 @@ namespace osu.Game.Rulesets.Osu.Edit public override bool HandleReverse() { var hitObjects = EditorBeatmap.SelectedHitObjects - .OfType() - .OrderBy(obj => obj.StartTime) - .ToList(); + .OfType() + .OrderBy(obj => obj.StartTime) + .ToList(); double endTime = hitObjects.Max(h => h.GetEndTime()); double startTime = hitObjects.Min(h => h.StartTime); bool moreThanOneObject = hitObjects.Count > 1; + // the expectation is that even if the objects themselves are reversed temporally, + // the position of new combos in the selection should remain the same. + // preserve it for later before doing the reversal. var newComboOrder = hitObjects.Select(obj => obj.NewCombo).ToList(); foreach (var h in hitObjects) @@ -102,15 +105,11 @@ namespace osu.Game.Rulesets.Osu.Edit } } - // re-order objects again after flipping their times - hitObjects = [.. hitObjects.OrderBy(obj => obj.StartTime)]; + // re-order objects by start time again after reversing, and restore new combo flag positioning + hitObjects = hitObjects.OrderBy(obj => obj.StartTime).ToList(); - int i = 0; - foreach (bool newCombo in newComboOrder) - { - hitObjects[i].NewCombo = newCombo; - i++; - } + for (int i = 0; i < hitObjects.Count; ++i) + hitObjects[i].NewCombo = newComboOrder[i]; return true; } From cbbb46cad87d40b3416e23c60f8dc5bf391004c9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 29 Mar 2024 00:25:03 +0900 Subject: [PATCH 906/915] Update action versions in diffcalc workflow --- .github/workflows/diffcalc.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml index 2ed176fe8d..7fd0f798cd 100644 --- a/.github/workflows/diffcalc.yml +++ b/.github/workflows/diffcalc.yml @@ -126,7 +126,7 @@ jobs: if: ${{ github.event_name == 'issue_comment' && github.event.issue.pull_request }} steps: - name: Create comment - uses: thollander/actions-comment-pull-request@363c6f6eae92cc5c3a66e95ba016fc771bb38943 # v2.4.2 + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 with: comment_tag: ${{ env.EXECUTION_ID }} message: | @@ -253,7 +253,7 @@ jobs: - name: Restore cache id: restore-cache - uses: maxnowack/local-cache@038cc090b52e4f205fbc468bf5b0756df6f68775 # v1 + uses: maxnowack/local-cache@720e69c948191660a90aa1cf6a42fc4d2dacdf30 # v2 with: path: ${{ steps.query.outputs.DATA_NAME }}.tar.bz2 key: ${{ steps.query.outputs.DATA_NAME }} @@ -284,7 +284,7 @@ jobs: - name: Restore cache id: restore-cache - uses: maxnowack/local-cache@038cc090b52e4f205fbc468bf5b0756df6f68775 # v1 + uses: maxnowack/local-cache@720e69c948191660a90aa1cf6a42fc4d2dacdf30 # v2 with: path: ${{ steps.query.outputs.DATA_NAME }}.tar.bz2 key: ${{ steps.query.outputs.DATA_NAME }} @@ -358,7 +358,7 @@ jobs: steps: - name: Update comment on success if: ${{ needs.generator.result == 'success' }} - uses: thollander/actions-comment-pull-request@363c6f6eae92cc5c3a66e95ba016fc771bb38943 # v2.4.2 + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 with: comment_tag: ${{ env.EXECUTION_ID }} mode: upsert @@ -369,7 +369,7 @@ jobs: - name: Update comment on failure if: ${{ needs.generator.result == 'failure' }} - uses: thollander/actions-comment-pull-request@363c6f6eae92cc5c3a66e95ba016fc771bb38943 # v2.4.2 + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 with: comment_tag: ${{ env.EXECUTION_ID }} mode: upsert @@ -379,7 +379,7 @@ jobs: - name: Update comment on cancellation if: ${{ needs.generator.result == 'cancelled' }} - uses: thollander/actions-comment-pull-request@363c6f6eae92cc5c3a66e95ba016fc771bb38943 # v2.4.2 + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 with: comment_tag: ${{ env.EXECUTION_ID }} mode: delete From c51a2e169d374b1cb820e2975def1cb2bbd902f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2024 12:19:06 +0800 Subject: [PATCH 907/915] Add test coverage of crash scenario --- osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index e603f72bb8..24c9d1294f 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -74,6 +74,10 @@ namespace osu.Game.Tests.Visual.Menus }); AddStep("enter code", () => loginOverlay.ChildrenOfType().First().Text = "88800088"); assertAPIState(APIState.Online); + + AddStep("set failing", () => { dummyAPI.SetState(APIState.Failing); }); + AddStep("return to online", () => { dummyAPI.SetState(APIState.Online); }); + AddStep("clear handler", () => dummyAPI.HandleRequest = null); } From fef8afb833b7ddfd42b97260faff7593da514868 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2024 12:03:05 +0800 Subject: [PATCH 908/915] Fix double binding causing game crash after API enters failing state See https://sentry.ppy.sh/organizations/ppy/issues/33406/?alert_rule_id=4&alert_timestamp=1711655107332&alert_type=email&environment=production&project=2&referrer=alert_email --- osu.Game/Overlays/Login/LoginPanel.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 25bf612bc3..d5c7ed29b8 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Login [Resolved] private OsuColour colours { get; set; } = null!; - private UserDropdown dropdown = null!; + private UserDropdown? dropdown; /// /// Called to request a hide of a parent displaying this container. @@ -68,6 +68,14 @@ namespace osu.Game.Overlays.Login apiState.BindValueChanged(onlineStateChanged, true); } + protected override void LoadComplete() + { + base.LoadComplete(); + + userStatus.BindTo(api.LocalUser.Value.Status); + userStatus.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true); + } + private void onlineStateChanged(ValueChangedEvent state) => Schedule(() => { form = null; @@ -144,9 +152,6 @@ namespace osu.Game.Overlays.Login }, }; - userStatus.BindTo(api.LocalUser.Value.Status); - userStatus.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true); - dropdown.Current.BindValueChanged(action => { switch (action.NewValue) @@ -171,6 +176,7 @@ namespace osu.Game.Overlays.Login break; } }, true); + break; } @@ -180,6 +186,9 @@ namespace osu.Game.Overlays.Login private void updateDropdownCurrent(UserStatus? status) { + if (dropdown == null) + return; + switch (status) { case UserStatus.Online: From d9cf5b5440ff3146e94d1c5da5c3c7c11bd53dd8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2024 15:44:01 +0800 Subject: [PATCH 909/915] Fix bindable not being correctly re-bound across local user changes --- .../Visual/Menus/TestSceneLoginOverlay.cs | 12 +++++++++ osu.Game/Overlays/Login/LoginPanel.cs | 25 +++++++++++-------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index 24c9d1294f..460d7814e0 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -15,6 +15,7 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays; using osu.Game.Overlays.Login; using osu.Game.Overlays.Settings; +using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK.Input; @@ -72,13 +73,24 @@ namespace osu.Game.Tests.Visual.Menus return false; }); + AddStep("enter code", () => loginOverlay.ChildrenOfType().First().Text = "88800088"); assertAPIState(APIState.Online); + assertDropdownState(UserAction.Online); AddStep("set failing", () => { dummyAPI.SetState(APIState.Failing); }); AddStep("return to online", () => { dummyAPI.SetState(APIState.Online); }); AddStep("clear handler", () => dummyAPI.HandleRequest = null); + + assertDropdownState(UserAction.Online); + AddStep("change user state", () => dummyAPI.LocalUser.Value.Status.Value = UserStatus.DoNotDisturb); + assertDropdownState(UserAction.DoNotDisturb); + } + + private void assertDropdownState(UserAction state) + { + AddAssert($"dropdown state is {state}", () => loginOverlay.ChildrenOfType().First().Current.Value, () => Is.EqualTo(state)); } private void assertAPIState(APIState expected) => diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index d5c7ed29b8..a8adf4ce8c 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -15,6 +15,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Settings; using osu.Game.Users; using osuTK; @@ -37,8 +38,10 @@ namespace osu.Game.Overlays.Login /// public Action? RequestHide; + private IBindable user = null!; + private readonly Bindable status = new Bindable(); + private readonly IBindable apiState = new Bindable(); - private readonly Bindable userStatus = new Bindable(); [Resolved] private IAPIProvider api { get; set; } = null!; @@ -61,19 +64,21 @@ namespace osu.Game.Overlays.Login AutoSizeAxes = Axes.Y; } - [BackgroundDependencyLoader] - private void load() - { - apiState.BindTo(api.State); - apiState.BindValueChanged(onlineStateChanged, true); - } - protected override void LoadComplete() { base.LoadComplete(); - userStatus.BindTo(api.LocalUser.Value.Status); - userStatus.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true); + apiState.BindTo(api.State); + apiState.BindValueChanged(onlineStateChanged, true); + + user = api.LocalUser.GetBoundCopy(); + user.BindValueChanged(u => + { + status.UnbindBindings(); + status.BindTo(u.NewValue.Status); + }, true); + + status.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true); } private void onlineStateChanged(ValueChangedEvent state) => Schedule(() => From 233b9eb1723fb44a26c1a65c1d583e3e6f87f7b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2024 17:11:55 +0800 Subject: [PATCH 910/915] Avoid reporting an import as successful when all beatmaps failed to import --- osu.Game/Beatmaps/BeatmapImporter.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 5ff3ab64b2..9ca0aafddd 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -434,6 +434,9 @@ namespace osu.Game.Beatmaps } } + if (!beatmaps.Any()) + throw new ArgumentException($"No valid beatmap files found in the beatmap archive."); + return beatmaps; } } From df4a28db915653f79603ef78ea44af48d781391e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2024 17:32:20 +0800 Subject: [PATCH 911/915] Fix failing test due to missing ruleset store --- osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs b/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs index 5f722e381c..016928c6d6 100644 --- a/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs +++ b/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs @@ -12,6 +12,7 @@ using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.IO; +using osu.Game.Rulesets; using osu.Game.Tests.Resources; namespace osu.Game.Tests.Database @@ -77,6 +78,7 @@ namespace osu.Game.Tests.Database { using (HeadlessGameHost host = new CleanRunHeadlessGameHost()) using (var tmpStorage = new TemporaryNativeStorage("stable-songs-folder")) + using (new RealmRulesetStore(realm, storage)) { var stableStorage = new StableStorage(tmpStorage.GetFullPath(""), host); var songsStorage = stableStorage.GetStorageForDirectory(StableStorage.STABLE_DEFAULT_SONGS_PATH); From 2d3b273974de4cb85dea652f3915a37f7ee0451e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 29 Mar 2024 10:36:17 +0100 Subject: [PATCH 912/915] Remove redundant string interpolation --- osu.Game/Beatmaps/BeatmapImporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 9ca0aafddd..2137f33e77 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -435,7 +435,7 @@ namespace osu.Game.Beatmaps } if (!beatmaps.Any()) - throw new ArgumentException($"No valid beatmap files found in the beatmap archive."); + throw new ArgumentException("No valid beatmap files found in the beatmap archive."); return beatmaps; } From e06df34a1c7f57ffec818be87264c4e82b61e508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 29 Mar 2024 11:16:31 +0100 Subject: [PATCH 913/915] Apply partial fade on pp display on results screen when score will not give pp --- .../TestSceneExpandedPanelMiddleContent.cs | 37 +++++++++++++++++++ osu.Game/Localisation/ResultsScreenStrings.cs | 24 ++++++++++++ .../Statistics/PerformanceStatistic.cs | 32 ++++++++++++++-- 3 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Localisation/ResultsScreenStrings.cs diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs index d97946a1d5..9f7726313a 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs @@ -14,13 +14,16 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; +using osu.Game.Localisation; using osu.Game.Models; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking.Expanded; +using osu.Game.Screens.Ranking.Expanded.Statistics; using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Resources; using osuTK; @@ -67,6 +70,40 @@ namespace osu.Game.Tests.Visual.Ranking AddAssert("play time displayed", () => this.ChildrenOfType().Any()); } + [Test] + public void TestPPShownAsProvisionalWhenBeatmapHasNoLeaderboard() + { + AddStep("show example score", () => + { + var beatmap = createTestBeatmap(new RealmUser()); + beatmap.Status = BeatmapOnlineStatus.Graveyard; + showPanel(TestResources.CreateTestScoreInfo(beatmap)); + }); + + AddAssert("pp display faded out", () => + { + var ppDisplay = this.ChildrenOfType().Single(); + return ppDisplay.Alpha == 0.5 && ppDisplay.TooltipText == ResultsScreenStrings.NoPPForUnrankedBeatmaps; + }); + } + + [Test] + public void TestPPShownAsProvisionalWhenUnrankedModsArePresent() + { + AddStep("show example score", () => + { + var score = TestResources.CreateTestScoreInfo(createTestBeatmap(new RealmUser())); + score.Mods = score.Mods.Append(new OsuModDifficultyAdjust()).ToArray(); + showPanel(score); + }); + + AddAssert("pp display faded out", () => + { + var ppDisplay = this.ChildrenOfType().Single(); + return ppDisplay.Alpha == 0.5 && ppDisplay.TooltipText == ResultsScreenStrings.NoPPForUnrankedMods; + }); + } + [Test] public void TestWithDefaultDate() { diff --git a/osu.Game/Localisation/ResultsScreenStrings.cs b/osu.Game/Localisation/ResultsScreenStrings.cs new file mode 100644 index 0000000000..54e7717af9 --- /dev/null +++ b/osu.Game/Localisation/ResultsScreenStrings.cs @@ -0,0 +1,24 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class ResultsScreenStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.ResultsScreen"; + + /// + /// "Performance points are not granted for this score because the beatmap is not ranked." + /// + public static LocalisableString NoPPForUnrankedBeatmaps => new TranslatableString(getKey(@"no_pp_for_unranked_beatmaps"), @"Performance points are not granted for this score because the beatmap is not ranked."); + + /// + /// "Performance points are not granted for this score because of unranked mods." + /// + public static LocalisableString NoPPForUnrankedMods => new TranslatableString(getKey(@"no_pp_for_unranked_mods"), @"Performance points are not granted for this score because of unranked mods."); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs index 22c1e26d43..0a9c68eafc 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs @@ -4,20 +4,26 @@ #nullable disable using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Resources.Localisation.Web; using osu.Game.Scoring; +using osu.Game.Localisation; namespace osu.Game.Screens.Ranking.Expanded.Statistics { - public partial class PerformanceStatistic : StatisticDisplay + public partial class PerformanceStatistic : StatisticDisplay, IHasTooltip { + public LocalisableString TooltipText { get; private set; } + private readonly ScoreInfo score; private readonly Bindable performance = new Bindable(); @@ -37,7 +43,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics { if (score.PP.HasValue) { - setPerformanceValue(score.PP.Value); + setPerformanceValue(score, score.PP.Value); } else { @@ -52,15 +58,33 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics var result = await performanceCalculator.CalculateAsync(score, attributes.Value.Attributes, cancellationToken ?? default).ConfigureAwait(false); - Schedule(() => setPerformanceValue(result.Total)); + Schedule(() => setPerformanceValue(score, result.Total)); }, cancellationToken ?? default); } } - private void setPerformanceValue(double? pp) + private void setPerformanceValue(ScoreInfo scoreInfo, double? pp) { if (pp.HasValue) + { performance.Value = (int)Math.Round(pp.Value, MidpointRounding.AwayFromZero); + + if (!scoreInfo.BeatmapInfo!.Status.GrantsPerformancePoints()) + { + Alpha = 0.5f; + TooltipText = ResultsScreenStrings.NoPPForUnrankedBeatmaps; + } + else if (scoreInfo.Mods.Any(m => !m.Ranked)) + { + Alpha = 0.5f; + TooltipText = ResultsScreenStrings.NoPPForUnrankedMods; + } + else + { + Alpha = 1f; + TooltipText = default; + } + } } public override void Appear() From c21805589eb2014bd07e6386b9398734e9a99dcb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 29 Mar 2024 22:40:04 +0800 Subject: [PATCH 914/915] Fix taiko mascot size not matching stable --- osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs index 7b1e31112e..e863c4c2e4 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs @@ -27,7 +27,8 @@ namespace osu.Game.Rulesets.Taiko.UI InternalChild = textureAnimation = createTextureAnimation(state).With(animation => { animation.Origin = animation.Anchor = Anchor.BottomLeft; - animation.Scale = new Vector2(0.51f); // close enough to stable + // matches stable (https://github.com/peppy/osu-stable-reference/blob/054d0380c19aa5972be176d9d242ceb0e1630ae6/osu!/GameModes/Play/Rulesets/Taiko/TaikoMascot.cs#L34) + animation.Scale = new Vector2(0.6f); }); RelativeSizeAxes = Axes.Both; From 51f79c33e1c93ecb4cbf71e5de820941a0fa622e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 29 Mar 2024 23:33:04 +0300 Subject: [PATCH 915/915] Fix URL pointing to non-existent commit --- osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs index e863c4c2e4..90f7782aba 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.UI InternalChild = textureAnimation = createTextureAnimation(state).With(animation => { animation.Origin = animation.Anchor = Anchor.BottomLeft; - // matches stable (https://github.com/peppy/osu-stable-reference/blob/054d0380c19aa5972be176d9d242ceb0e1630ae6/osu!/GameModes/Play/Rulesets/Taiko/TaikoMascot.cs#L34) + // matches stable (https://github.com/peppy/osu-stable-reference/blob/e53980dd76857ee899f66ce519ba1597e7874f28/osu!/GameModes/Play/Rulesets/Taiko/TaikoMascot.cs#L34) animation.Scale = new Vector2(0.6f); });

EM!on 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