diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d75f09f184..d8645d728e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,7 +114,10 @@ jobs: dotnet-version: "8.0.x" - name: Install .NET workloads - run: dotnet workload install android + # since windows image 20241113.3.0, not specifying a version here + # installs the .NET 7 version of android workload for very unknown reasons. + # revisit once we upgrade to .NET 9, it's probably fixed there. + run: dotnet workload install android --version (dotnet --version) - name: Compile run: dotnet build -c Debug osu.Android.slnf diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml index 4297a88e89..8461208a2e 100644 --- a/.github/workflows/diffcalc.yml +++ b/.github/workflows/diffcalc.yml @@ -115,7 +115,7 @@ jobs: steps: - name: Check permissions run: | - ALLOWED_USERS=(smoogipoo peppy bdach frenzibyte) + ALLOWED_USERS=(smoogipoo peppy bdach frenzibyte tsunyoku stanriders) for i in "${ALLOWED_USERS[@]}"; do if [[ "${{ github.actor }}" == "$i" ]]; then exit 0 diff --git a/.globalconfig b/.globalconfig deleted file mode 100644 index a4d4707f9b..0000000000 --- a/.globalconfig +++ /dev/null @@ -1,57 +0,0 @@ -# .NET Code Style -# IDE styles reference: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ - -# IDE0001: Simplify names -dotnet_diagnostic.IDE0001.severity = warning - -# IDE0002: Simplify member access -dotnet_diagnostic.IDE0002.severity = warning - -# IDE0003: Remove qualification -dotnet_diagnostic.IDE0003.severity = warning - -# IDE0004: Remove unnecessary cast -dotnet_diagnostic.IDE0004.severity = warning - -# IDE0005: Remove unnecessary imports -dotnet_diagnostic.IDE0005.severity = warning - -# IDE0034: Simplify default literal -dotnet_diagnostic.IDE0034.severity = warning - -# IDE0036: Sort modifiers -dotnet_diagnostic.IDE0036.severity = warning - -# IDE0040: Add accessibility modifier -dotnet_diagnostic.IDE0040.severity = warning - -# IDE0049: Use keyword for type name -dotnet_diagnostic.IDE0040.severity = warning - -# IDE0055: Fix formatting -dotnet_diagnostic.IDE0055.severity = warning - -# IDE0051: Private method is unused -dotnet_diagnostic.IDE0051.severity = silent - -# IDE0052: Private member is unused -dotnet_diagnostic.IDE0052.severity = silent - -# IDE0073: File header -dotnet_diagnostic.IDE0073.severity = warning - -# IDE0130: Namespace mismatch with folder -dotnet_diagnostic.IDE0130.severity = warning - -# IDE1006: Naming style -dotnet_diagnostic.IDE1006.severity = warning - -#Disable operator overloads requiring alternate named methods -dotnet_diagnostic.CA2225.severity = none - -# Banned APIs -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 diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index 3c60b28765..550f7c8e11 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -14,10 +14,6 @@ M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Gen M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks. P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks. M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever. -M:System.Char.ToLower(System.Char);char.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture. -M:System.Char.ToUpper(System.Char);char.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture. -M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString. -M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString. M:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead. M:Humanizer.InflectorExtensions.Camelize(System.String);Humanizer's .Camelize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToCamelCase() instead. M:Humanizer.InflectorExtensions.Underscore(System.String);Humanizer's .Underscore() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToSnakeCase() instead. diff --git a/CodeAnalysis/osu.globalconfig b/CodeAnalysis/osu.globalconfig new file mode 100644 index 0000000000..247a825033 --- /dev/null +++ b/CodeAnalysis/osu.globalconfig @@ -0,0 +1,109 @@ +# .NET Code Style +# IDE styles reference: https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ +is_global = true + +# IDE0001: Simplify names +dotnet_diagnostic.IDE0001.severity = warning + +# IDE0002: Simplify member access +dotnet_diagnostic.IDE0002.severity = warning + +# IDE0003: Remove qualification +dotnet_diagnostic.IDE0003.severity = warning + +# IDE0004: Remove unnecessary cast +dotnet_diagnostic.IDE0004.severity = warning + +# IDE0005: Remove unnecessary imports +dotnet_diagnostic.IDE0005.severity = warning + +# IDE0034: Simplify default literal +dotnet_diagnostic.IDE0034.severity = warning + +# IDE0036: Sort modifiers +dotnet_diagnostic.IDE0036.severity = warning + +# IDE0040: Add accessibility modifier +dotnet_diagnostic.IDE0040.severity = warning + +# IDE0049: Use keyword for type name +dotnet_diagnostic.IDE0040.severity = warning + +# IDE0055: Fix formatting +dotnet_diagnostic.IDE0055.severity = warning + +# IDE0051: Private method is unused +dotnet_diagnostic.IDE0051.severity = silent + +# IDE0052: Private member is unused +dotnet_diagnostic.IDE0052.severity = silent + +# IDE0073: File header +dotnet_diagnostic.IDE0073.severity = warning + +# IDE0130: Namespace mismatch with folder +dotnet_diagnostic.IDE0130.severity = warning + +# IDE1006: Naming style +dotnet_diagnostic.IDE1006.severity = warning + +# CA1305: Specify IFormatProvider +# Too many noisy warnings for parsing/formatting numbers +dotnet_diagnostic.CA1305.severity = none + +# CA1507: Use nameof to express symbol names +# Flaggs serialization name attributes +dotnet_diagnostic.CA1507.severity = suggestion + +# CA1806: Do not ignore method results +# The usages for numeric parsing are explicitly optional +dotnet_diagnostic.CA1806.severity = suggestion + +# CA1822: Mark members as static +# Potential false positive around reflection/too much noise +dotnet_diagnostic.CA1822.severity = none + +# CA1826: Do not use Enumerable method on indexable collections +dotnet_diagnostic.CA1826.severity = suggestion + +# CA1859: Use concrete types when possible for improved performance +# Involves design considerations +dotnet_diagnostic.CA1859.severity = suggestion + +# CA1860: Avoid using 'Enumerable.Any()' extension method +dotnet_diagnostic.CA1860.severity = suggestion + +# CA1861: Avoid constant arrays as arguments +# Outdated with collection expressions +dotnet_diagnostic.CA1861.severity = suggestion + +# CA2007: Consider calling ConfigureAwait on the awaited task +dotnet_diagnostic.CA2007.severity = warning + +# CA2016: Forward the 'CancellationToken' parameter to methods +# Some overloads are having special handling for debugger +dotnet_diagnostic.CA2016.severity = suggestion + +# CA2021: Do not call Enumerable.Cast or Enumerable.OfType with incompatible types +# Causing a lot of false positives with generics +dotnet_diagnostic.CA2021.severity = none + +# CA2101: Specify marshaling for P/Invoke string arguments +# Reports warning for all non-UTF16 usages on DllImport; consider migrating to LibraryImport +dotnet_diagnostic.CA2101.severity = none + +# CA2201: Do not raise reserved exception types +dotnet_diagnostic.CA2201.severity = warning + +# CA2208: Instantiate argument exceptions correctly +dotnet_diagnostic.CA2208.severity = suggestion + +# CA2242: Test for NaN correctly +dotnet_diagnostic.CA2242.severity = warning + +# Banned APIs +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 diff --git a/CodeAnalysis/osu.ruleset b/CodeAnalysis/osu.ruleset deleted file mode 100644 index 6a99e230d1..0000000000 --- a/CodeAnalysis/osu.ruleset +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 5ba12b845b..3acb86ee0c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,9 +18,21 @@ + + - $(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset + Default + Default + Recommended + Recommended + Recommended + Recommended + Default + Minimum + Recommended + Default + Default true diff --git a/osu.Android.props b/osu.Android.props index 4699beeac0..84827ce76b 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 ccae4a15ee..349d6fa1d7 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -17,6 +17,6 @@ -all - + diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs new file mode 100644 index 0000000000..e88b39f710 --- /dev/null +++ b/osu.iOS/AppDelegate.cs @@ -0,0 +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 Foundation; +using osu.Framework.iOS; + +namespace osu.iOS +{ + [Register("AppDelegate")] + public class AppDelegate : GameApplicationDelegate + { + protected override Framework.Game CreateGame() => new OsuGameIOS(); + } +} diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 1330e29bc1..29410938a3 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -34,9 +34,11 @@ CADisableMinimumFrameDurationOnPhone NSCameraUsageDescription - We don't really use the camera. + We don't use the camera. NSMicrophoneUsageDescription - We don't really use the microphone. + We don't use the microphone. + NSBluetoothAlwaysUsageDescription + We don't use Bluetooth. UISupportedInterfaceOrientations UIInterfaceOrientationLandscapeRight @@ -68,6 +70,8 @@ sh.ppy.osu.items + UTTypeDescription + osu! replay UTTypeIdentifier sh.ppy.osu.osr UTTypeTagSpecification @@ -81,6 +85,8 @@ sh.ppy.osu.items + UTTypeDescription + osu! skin UTTypeIdentifier sh.ppy.osu.osk UTTypeTagSpecification @@ -94,6 +100,8 @@ sh.ppy.osu.items + UTTypeDescription + osu! beatmap UTTypeIdentifier sh.ppy.osu.osz UTTypeTagSpecification @@ -107,6 +115,8 @@ sh.ppy.osu.items + UTTypeDescription + osu! beatmap UTTypeIdentifier sh.ppy.osu.olz UTTypeTagSpecification @@ -145,5 +155,7 @@ LSApplicationCategoryType public.app-category.music-games + LSSupportsOpeningDocumentsInPlace + diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index 2a4f9b87ac..a9ca1778a0 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -5,6 +5,8 @@ using System; using Foundation; using Microsoft.Maui.Devices; using osu.Framework.Graphics; +using osu.Framework.iOS; +using osu.Framework.Platform; using osu.Game; using osu.Game.Updater; using osu.Game.Utils; @@ -15,10 +17,14 @@ namespace osu.iOS { public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString()); + public override bool HideUnlicensedContent => true; + protected override UpdateManager CreateUpdateManager() => new MobileUpdateNotifier(); protected override BatteryInfo CreateBatteryInfo() => new IOSBatteryInfo(); + protected override Storage CreateStorage(GameHost host, Storage defaultStorage) => new OsuStorageIOS((IOSGameHost)host, defaultStorage); + protected override Edges SafeAreaOverrideEdges => // iOS shows a home indicator at the bottom, and adds a safe area to account for this. // Because we have the home indicator (mostly) hidden we don't really care about drawing in this region. diff --git a/osu.iOS/OsuStorageIOS.cs b/osu.iOS/OsuStorageIOS.cs new file mode 100644 index 0000000000..f3a5eec737 --- /dev/null +++ b/osu.iOS/OsuStorageIOS.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using osu.Framework.iOS; +using osu.Framework.Platform; +using osu.Game.IO; + +namespace osu.iOS +{ + public class OsuStorageIOS : OsuStorage + { + private readonly IOSGameHost host; + + public OsuStorageIOS(IOSGameHost host, Storage defaultStorage) + : base(host, defaultStorage) + { + this.host = host; + } + + public override Storage GetExportStorage() => new IOSStorage(Path.GetTempPath(), host); + } +} diff --git a/osu.iOS/Application.cs b/osu.iOS/Program.cs similarity index 69% rename from osu.iOS/Application.cs rename to osu.iOS/Program.cs index 74bd58acb8..fd24ecf419 100644 --- a/osu.iOS/Application.cs +++ b/osu.iOS/Program.cs @@ -1,15 +1,15 @@ // 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.iOS; +using UIKit; namespace osu.iOS { - public static class Application + public static class Program { public static void Main(string[] args) { - GameApplication.Main(new OsuGameIOS()); + UIApplication.Main(args, null, typeof(AppDelegate)); } } } diff --git a/osu.sln b/osu.sln index 829e43fc65..63da18c23e 100644 --- a/osu.sln +++ b/osu.sln @@ -56,11 +56,10 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{10DF8F12-50FD-45D8-8A38-17BA764BF54D}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig - .globalconfig = .globalconfig Directory.Build.props = Directory.Build.props osu.Android.props = osu.Android.props osu.iOS.props = osu.iOS.props - CodeAnalysis\osu.ruleset = CodeAnalysis\osu.ruleset + global.json = global.json osu.sln.DotSettings = osu.sln.DotSettings osu.TestProject.props = osu.TestProject.props EndProjectSection @@ -95,6 +94,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Pippidon" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Pippidon.Tests", "Templates\Rulesets\ruleset-scrolling-example\osu.Game.Rulesets.Pippidon.Tests\osu.Game.Rulesets.Pippidon.Tests.csproj", "{1743BF7C-E6AE-4A06-BAD9-166D62894303}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CodeAnalysis", "CodeAnalysis", "{FB156649-D457-4D1A-969C-D3A23FD31513}" + ProjectSection(SolutionItems) = preProject + CodeAnalysis\BannedSymbols.txt = CodeAnalysis\BannedSymbols.txt + CodeAnalysis\osu.globalconfig = CodeAnalysis\osu.globalconfig + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU