diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 56b3ebe87b..213c5082ab 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,7 +31,7 @@ jobs:
run: dotnet tool restore
- name: Restore Packages
- run: dotnet restore
+ run: dotnet restore osu.Desktop.slnf
- name: Restore inspectcode cache
uses: actions/cache@v3
@@ -113,27 +113,36 @@ jobs:
with:
dotnet-version: "6.0.x"
- - name: Setup MSBuild
- uses: microsoft/setup-msbuild@v1
+ - name: Install .NET workloads
+ run: dotnet workload install maui-android
- - name: Build
- run: msbuild osu.Android/osu.Android.csproj /restore /p:Configuration=Debug
+ - name: Compile
+ run: dotnet build -c Debug osu.Android.slnf
build-only-ios:
name: Build only (iOS)
- runs-on: macos-latest
+ # change to macos-latest once GitHub finishes migrating all repositories to macOS 12.
+ runs-on: macos-12
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v2
+ # see https://github.com/actions/runner-images/issues/6771#issuecomment-1354713617
+ # remove once all workflow VMs use Xcode 14.1
+ - name: Set Xcode Version
+ shell: bash
+ run: |
+ sudo xcode-select -s "/Applications/Xcode_14.1.app"
+ echo "MD_APPLE_SDK_ROOT=/Applications/Xcode_14.1.app" >> $GITHUB_ENV
+
- name: Install .NET 6.0.x
uses: actions/setup-dotnet@v1
with:
dotnet-version: "6.0.x"
- # Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
- # cannot accept .sln(f) files as arguments.
- # Build just the main game for now.
+ - name: Install .NET Workloads
+ run: dotnet workload install maui-ios
+
- name: Build
- run: msbuild osu.iOS/osu.iOS.csproj /restore /p:Configuration=Debug
+ run: dotnet build -c Debug osu.iOS
diff --git a/README.md b/README.md
index 75d61dad4d..0de82eba75 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@ If you are looking to install or test osu! without setting up a development envi
**Latest build:**
-| [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 10+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) |
+| [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) |
| ------------- | ------------- | ------------- | ------------- | ------------- |
- The iOS testflight link may fill up (Apple has a hard limit of 10,000 users). We reset it occasionally when this happens. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements of link resets.
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 092a013614..d09e7647e0 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 @@
- netstandard2.1
+ net6.0
osu.Game.Rulesets.EmptyFreeform
Library
AnyCPU
@@ -12,4 +12,4 @@
-
\ No newline at end of file
+
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 a3607343c9..9c8867f4ef 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 @@
- netstandard2.1
+ net6.0
osu.Game.Rulesets.Pippidon
Library
AnyCPU
@@ -12,4 +12,4 @@
-
\ No newline at end of file
+
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 2ea52429ab..5bf3884f53 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 @@
- netstandard2.1
+ net6.0
osu.Game.Rulesets.EmptyScrolling
Library
AnyCPU
@@ -12,4 +12,4 @@
-
\ No newline at end of file
+
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 a3607343c9..9c8867f4ef 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 @@
- netstandard2.1
+ net6.0
osu.Game.Rulesets.Pippidon
Library
AnyCPU
@@ -12,4 +12,4 @@
-
\ No newline at end of file
+
diff --git a/appveyor.yml b/appveyor.yml
index 5be73f9875..ed48a997e8 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,6 +1,6 @@
clone_depth: 1
version: '{branch}-{build}'
-image: Visual Studio 2019
+image: Visual Studio 2022
cache:
- '%LOCALAPPDATA%\NuGet\v3-cache -> appveyor.yml'
@@ -11,6 +11,8 @@ dotnet_csproj:
before_build:
- cmd: dotnet --info # Useful when version mismatch between CI and local
+ - cmd: dotnet workload install maui-android # Change to `dotnet workload restore` once there's no old projects
+ - cmd: dotnet workload install maui-ios # Change to `dotnet workload restore` once there's no old projects
- cmd: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects
build:
diff --git a/global.json b/global.json
new file mode 100644
index 0000000000..f20ff84190
--- /dev/null
+++ b/global.json
@@ -0,0 +1,6 @@
+{
+ "sdk": {
+ "version": "6.0.300",
+ "rollForward": "major"
+ }
+}
diff --git a/osu.Android.props b/osu.Android.props
index 147d236d98..5da7eae380 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -1,58 +1,16 @@
- 8.0
- bin\$(Configuration)
- 4
- 2.0
- false
- false
- Library
- 512
- Off
- True
- Xamarin.Android.Net.AndroidClientHandler
- v10.0
- false
- true
- armeabi-v7a;x86;arm64-v8a
- true
- cjk,mideast,other,rare,west
- SdkOnly
- prompt
-
-
- True
- portable
- False
- DEBUG;TRACE
- false
- true
- false
-
-
- false
- None
- True
- false
- False
+ 21.0
+ android-x86;android-arm;android-arm64
+ apk
+ CJK;Mideast;Rare;West;Other;
+ Xamarin.Android.Net.AndroidMessageHandler
+
+ true
true
-
- osu.licenseheader
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -61,4 +19,9 @@
+
+
+ true
+
diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/AndroidManifest.xml
similarity index 98%
rename from osu.Android/Properties/AndroidManifest.xml
rename to osu.Android/AndroidManifest.xml
index 165a64a424..be326be5eb 100644
--- a/osu.Android/Properties/AndroidManifest.xml
+++ b/osu.Android/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs
index be40db7508..ca3d628447 100644
--- a/osu.Android/OsuGameActivity.cs
+++ b/osu.Android/OsuGameActivity.cs
@@ -7,6 +7,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
@@ -74,11 +75,23 @@ namespace osu.Android
Debug.Assert(Resources?.DisplayMetrics != null);
Point displaySize = new Point();
+#pragma warning disable 618 // GetSize is deprecated
WindowManager.DefaultDisplay.GetSize(displaySize);
+#pragma warning restore 618
float smallestWidthDp = Math.Min(displaySize.X, displaySize.Y) / Resources.DisplayMetrics.Density;
bool isTablet = smallestWidthDp >= 600f;
RequestedOrientation = DefaultOrientation = isTablet ? ScreenOrientation.FullUser : ScreenOrientation.SensorLandscape;
+
+ // Currently (SDK 6.0.200), BundleAssemblies is not runnable for net6-android.
+ // The assembly files are not available as files either after native AOT.
+ // Manually load them so that they can be loaded by RulesetStore.loadFromAppDomain.
+ // REMEMBER to fully uninstall previous version every time when investigating this!
+ // Don't forget osu.Game.Tests.Android too.
+ Assembly.Load("osu.Game.Rulesets.Osu");
+ Assembly.Load("osu.Game.Rulesets.Taiko");
+ Assembly.Load("osu.Game.Rulesets.Catch");
+ Assembly.Load("osu.Game.Rulesets.Mania");
}
protected override void OnNewIntent(Intent intent) => handleIntent(intent);
@@ -127,7 +140,7 @@ namespace osu.Android
cursor.MoveToFirst();
- int filenameColumn = cursor.GetColumnIndex(OpenableColumns.DisplayName);
+ int filenameColumn = cursor.GetColumnIndex(IOpenableColumns.DisplayName);
string filename = cursor.GetString(filenameColumn);
// SharpCompress requires archive streams to be seekable, which the stream opened by
diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs
index 1c6f41a7ec..0227d2aec2 100644
--- a/osu.Android/OsuGameAndroid.cs
+++ b/osu.Android/OsuGameAndroid.cs
@@ -5,7 +5,7 @@
using System;
using Android.App;
-using Android.OS;
+using Microsoft.Maui.Devices;
using osu.Framework.Allocation;
using osu.Framework.Android.Input;
using osu.Framework.Input.Handlers;
@@ -14,7 +14,6 @@ using osu.Game;
using osu.Game.Overlays.Settings;
using osu.Game.Updater;
using osu.Game.Utils;
-using Xamarin.Essentials;
namespace osu.Android
{
@@ -48,7 +47,7 @@ namespace osu.Android
// https://stackoverflow.com/questions/52977079/android-sdk-28-versioncode-in-packageinfo-has-been-deprecated
string versionName = string.Empty;
- if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
+ if (OperatingSystem.IsAndroidVersionAtLeast(28))
{
versionName = packageInfo.LongVersionCode.ToString();
// ensure we only read the trailing portion of long (the part we are interested in).
diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj
index 004cc8c39c..de53e5dd59 100644
--- a/osu.Android/osu.Android.csproj
+++ b/osu.Android/osu.Android.csproj
@@ -1,73 +1,19 @@
-
-
+
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- {122416d6-6b49-4ee2-a1e8-b825f31c79fe}
+ net6.0-android
+ Exe
osu.Android
osu.Android
- Properties\AndroidManifest.xml
- armeabi-v7a;x86;arm64-v8a
- false
-
-
- cjk;mideast;other;rare;west
- d8
- r8
-
-
- None
- cjk;mideast;other;rare;west
- true
+ true
+
+ false
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
- {58f6c80c-1253-4a0e-a465-b8c85ebeadf3}
- osu.Game.Rulesets.Catch
-
-
- {48f4582b-7687-4621-9cbe-5c24197cb536}
- osu.Game.Rulesets.Mania
-
-
- {c92a607b-1fdd-4954-9f92-03ff547d9080}
- osu.Game.Rulesets.Osu
-
-
- {f167e17a-7de6-4af5-b920-a5112296c695}
- osu.Game.Rulesets.Taiko
-
-
- {2a66dd92-adb1-4994-89e2-c94e04acda0d}
- osu.Game
-
-
-
-
-
-
-
- 5.0.0
-
-
-
-
-
-
-
\ No newline at end of file
+
diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml
similarity index 98%
rename from osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml
rename to osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml
index f8c3fcd894..bf7c0bfeca 100644
--- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml
+++ b/osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
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 94fdba4a3e..4ee3219442 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,49 +1,24 @@
-
-
+
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- {122416d6-6b49-4ee2-a1e8-b825f31c79fe}
+ net6.0-android
+ Exe
osu.Game.Rulesets.Catch.Tests
osu.Game.Rulesets.Catch.Tests.Android
- Properties\AndroidManifest.xml
- armeabi-v7a;x86;arm64-v8a
-
-
- None
- cjk;mideast;other;rare;west
- true
-
-
-
-
-
-
-
+
%(RecursiveDir)%(Filename)%(Extension)
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ Android\%(RecursiveDir)%(Filename)%(Extension)
+
-
- {58f6c80c-1253-4a0e-a465-b8c85ebeadf3}
- osu.Game.Rulesets.Catch
-
-
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}
- osu.Game
-
+
+
-
-
- 5.0.0
-
-
-
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs
index 71d943ece1..1fcb0aa427 100644
--- a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs
+++ b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs
@@ -3,7 +3,6 @@
#nullable disable
-using osu.Framework.iOS;
using UIKit;
namespace osu.Game.Rulesets.Catch.Tests.iOS
@@ -12,7 +11,7 @@ namespace osu.Game.Rulesets.Catch.Tests.iOS
{
public static void Main(string[] args)
{
- UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate));
+ UIApplication.Main(args, null, typeof(AppDelegate));
}
}
}
diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist b/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist
index 16a2b99997..5ace6c07f5 100644
--- a/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist
+++ b/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist
@@ -13,7 +13,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 10.0
+ 13.4
UIDeviceFamily
1
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 be6044bbd0..acf12bb0ac 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,35 +1,19 @@
-
-
+
- Debug
- iPhoneSimulator
- {4004C7B7-1A62-43F1-9DF2-52450FA67E70}
Exe
+ net6.0-ios
+ 13.4
osu.Game.Rulesets.Catch.Tests
osu.Game.Rulesets.Catch.Tests.iOS
-
-
-
- Linker.xml
-
-
-
%(RecursiveDir)%(Filename)%(Extension)
-
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}
- osu.Game
-
-
- {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}
- osu.Game.Rulesets.Catch
-
+
+
-
-
\ No newline at end of file
+
diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs
index e5cdcf706c..43918bda57 100644
--- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs
+++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs
@@ -121,9 +121,7 @@ namespace osu.Game.Rulesets.Catch.Edit
return new SnapResult(originPosition, StartTime);
}
- return enumerateSnappingCandidates(time)
- .OrderBy(pos => Vector2.DistanceSquared(screenSpacePosition, pos.ScreenSpacePosition))
- .FirstOrDefault();
+ return enumerateSnappingCandidates(time).MinBy(pos => Vector2.DistanceSquared(screenSpacePosition, pos.ScreenSpacePosition));
}
private IEnumerable enumerateSnappingCandidates(double time)
diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
index e2f95ca177..ecce7c1b3f 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 @@
- netstandard2.1
+ net6.0
Library
true
catch the fruit. to the beat.
@@ -15,4 +15,4 @@
-
\ No newline at end of file
+
diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml
similarity index 98%
rename from osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml
rename to osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml
index de7935b2ef..4a1545a423 100644
--- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/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.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 9674186039..25335754d2 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,49 +1,24 @@
-
-
+
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {531F1092-DB27-445D-AA33-2A77C7187C99}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- {122416d6-6b49-4ee2-a1e8-b825f31c79fe}
+ net6.0-android
+ Exe
osu.Game.Rulesets.Mania.Tests
osu.Game.Rulesets.Mania.Tests.Android
- Properties\AndroidManifest.xml
- armeabi-v7a;x86;arm64-v8a
-
-
- None
- cjk;mideast;other;rare;west
- true
-
-
-
-
-
-
-
+
%(RecursiveDir)%(Filename)%(Extension)
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ Android\%(RecursiveDir)%(Filename)%(Extension)
+
-
- {48f4582b-7687-4621-9cbe-5c24197cb536}
- osu.Game.Rulesets.Mania
-
-
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}
- osu.Game
-
+
+
-
-
- 5.0.0
-
-
-
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs
index 2d1015387a..a508198f7f 100644
--- a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs
+++ b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs
@@ -3,7 +3,6 @@
#nullable disable
-using osu.Framework.iOS;
using UIKit;
namespace osu.Game.Rulesets.Mania.Tests.iOS
@@ -12,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Tests.iOS
{
public static void Main(string[] args)
{
- UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate));
+ UIApplication.Main(args, null, typeof(AppDelegate));
}
}
}
diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist b/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist
index 82d1c8ea24..ff5dde856e 100644
--- a/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist
+++ b/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist
@@ -13,7 +13,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 10.0
+ 13.4
UIDeviceFamily
1
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 88ad484bc1..51e07dd6c1 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,35 +1,19 @@
-
-
+
- Debug
- iPhoneSimulator
- {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}
Exe
+ net6.0-ios
+ 13.4
osu.Game.Rulesets.Mania.Tests
osu.Game.Rulesets.Mania.Tests.iOS
-
-
-
- Linker.xml
-
-
-
%(RecursiveDir)%(Filename)%(Extension)
-
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}
- osu.Game
-
-
- {48F4582B-7687-4621-9CBE-5C24197CB536}
- osu.Game.Rulesets.Mania
-
+
+
-
-
\ No newline at end of file
+
diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
index 4f6840f9ca..72f172188e 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 @@
- netstandard2.1
+ net6.0
Library
true
smash the keys. to the beat.
@@ -15,4 +15,4 @@
-
\ No newline at end of file
+
diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml
similarity index 98%
rename from osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml
rename to osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml
index 3ce17ccc27..45d27dda70 100644
--- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/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.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 f4b673f10b..e8a46a9828 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,49 +1,27 @@
-
-
+
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {90CAB706-39CB-4B93-9629-3218A6FF8E9B}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- {122416d6-6b49-4ee2-a1e8-b825f31c79fe}
+ net6.0-android
+ Exe
osu.Game.Rulesets.Osu.Tests
osu.Game.Rulesets.Osu.Tests.Android
- Properties\AndroidManifest.xml
- armeabi-v7a;x86;arm64-v8a
-
-
- None
- cjk;mideast;other;rare;west
- true
-
-
-
-
-
-
-
+
%(RecursiveDir)%(Filename)%(Extension)
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ Android\%(RecursiveDir)%(Filename)%(Extension)
+
-
- {c92a607b-1fdd-4954-9f92-03ff547d9080}
- osu.Game.Rulesets.Osu
-
-
- {2a66dd92-adb1-4994-89e2-c94e04acda0d}
- osu.Game
-
+
+
-
- 5.0.0
-
+
-
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs
index ad23f3ee33..6ef29fa68e 100644
--- a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs
+++ b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs
@@ -3,7 +3,6 @@
#nullable disable
-using osu.Framework.iOS;
using UIKit;
namespace osu.Game.Rulesets.Osu.Tests.iOS
@@ -12,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Tests.iOS
{
public static void Main(string[] args)
{
- UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate));
+ UIApplication.Main(args, null, typeof(AppDelegate));
}
}
}
diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist b/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist
index a88b74695c..1e33f2ff16 100644
--- a/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist
+++ b/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist
@@ -13,7 +13,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 10.0
+ 13.4
UIDeviceFamily
1
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 545abcec6c..7d50deb8ba 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,35 +1,20 @@
-
-
+
- Debug
- iPhoneSimulator
- {6653CA6F-DB06-4604-A3FD-762E25C2AF96}
+ Exe
+ net6.0-ios
+ 13.4
Exe
osu.Game.Rulesets.Osu.Tests
osu.Game.Rulesets.Osu.Tests.iOS
-
-
-
- Linker.xml
-
-
-
%(RecursiveDir)%(Filename)%(Extension)
-
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}
- osu.Game
-
-
- {C92A607B-1FDD-4954-9F92-03FF547D9080}
- osu.Game.Rulesets.Osu
-
+
+
-
-
\ No newline at end of file
+
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
index 3a175888d9..66d99e0bf1 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs
@@ -133,6 +133,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(e.NewItems != null);
+
// If inserting in the path (not appending),
// update indices of existing connections after insert location
if (e.NewStartingIndex < Pieces.Count)
@@ -164,6 +166,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
break;
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(e.OldItems != null);
+
foreach (var point in e.OldItems.Cast())
{
foreach (var piece in Pieces.Where(p => p.ControlPoint == point).ToArray())
diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs
index 1cb3208c30..2f62968029 100644
--- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs
+++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs
@@ -82,7 +82,7 @@ namespace osu.Game.Rulesets.Osu.Replays
private class ReplayFrameComparer : IComparer
{
- public int Compare(ReplayFrame f1, ReplayFrame f2)
+ public int Compare(ReplayFrame? f1, ReplayFrame? f2)
{
if (f1 == null) throw new ArgumentNullException(nameof(f1));
if (f2 == null) throw new ArgumentNullException(nameof(f2));
diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
index 98f1e69bd1..bf776fe5dd 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 @@
- netstandard2.1
+ net6.0
Library
true
click the circles. to the beat.
@@ -15,4 +15,4 @@
-
\ No newline at end of file
+
diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml
similarity index 98%
rename from osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml
rename to osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml
index d9de0fde4e..452b9683ec 100644
--- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/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.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 4d4dabebe6..a639326ebd 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,49 +1,24 @@
-
-
+
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {3701A0A1-8476-42C6-B5C4-D24129B4A484}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- {122416d6-6b49-4ee2-a1e8-b825f31c79fe}
+ net6.0-android
+ Exe
osu.Game.Rulesets.Taiko.Tests
osu.Game.Rulesets.Taiko.Tests.Android
- Properties\AndroidManifest.xml
- armeabi-v7a;x86;arm64-v8a
-
-
- None
- cjk;mideast;other;rare;west
- true
-
-
-
-
-
-
-
+
%(RecursiveDir)%(Filename)%(Extension)
+
+
+ %(RecursiveDir)%(Filename)%(Extension)
+ Android\%(RecursiveDir)%(Filename)%(Extension)
+
-
- {f167e17a-7de6-4af5-b920-a5112296c695}
- osu.Game.Rulesets.Taiko
-
-
- {2a66dd92-adb1-4994-89e2-c94e04acda0d}
- osu.Game
-
+
+
-
-
- 5.0.0
-
-
-
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs
index 1ebbd61a94..0e3a953728 100644
--- a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs
+++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs
@@ -3,7 +3,6 @@
#nullable disable
-using osu.Framework.iOS;
using UIKit;
namespace osu.Game.Rulesets.Taiko.Tests.iOS
@@ -12,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.iOS
{
public static void Main(string[] args)
{
- UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate));
+ UIApplication.Main(args, null, typeof(AppDelegate));
}
}
}
diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist b/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist
index 9628475b3e..76cb3c0db0 100644
--- a/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist
+++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist
@@ -13,7 +13,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 10.0
+ 13.4
UIDeviceFamily
1
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 8ee640cd99..e648a11299 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,35 +1,19 @@
-
-
+
- Debug
- iPhoneSimulator
- {7E408809-66AC-49D1-AF4D-98834F9B979A}
Exe
+ net6.0-ios
+ 13.4
osu.Game.Rulesets.Taiko.Tests
osu.Game.Rulesets.Taiko.Tests.iOS
-
-
-
- Linker.xml
-
-
-
%(RecursiveDir)%(Filename)%(Extension)
-
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}
- osu.Game
-
-
- {F167E17A-7DE6-4AF5-B920-A5112296C695}
- osu.Game.Rulesets.Taiko
-
+
+
-
-
\ No newline at end of file
+
diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
index b752c13d18..f0e1cb8e8f 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 @@
- netstandard2.1
+ net6.0
Library
true
bash the drum. to the beat.
diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/AndroidManifest.xml
similarity index 98%
rename from osu.Game.Tests.Android/Properties/AndroidManifest.xml
rename to osu.Game.Tests.Android/AndroidManifest.xml
index 4a63f0c357..f25b2e5328 100644
--- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml
+++ b/osu.Game.Tests.Android/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Tests.Android/MainActivity.cs b/osu.Game.Tests.Android/MainActivity.cs
index 6c4f9bac58..bdb947fbb4 100644
--- a/osu.Game.Tests.Android/MainActivity.cs
+++ b/osu.Game.Tests.Android/MainActivity.cs
@@ -3,7 +3,9 @@
#nullable disable
+using System.Reflection;
using Android.App;
+using Android.OS;
using osu.Framework.Android;
namespace osu.Game.Tests.Android
@@ -12,5 +14,16 @@ namespace osu.Game.Tests.Android
public class MainActivity : AndroidGameActivity
{
protected override Framework.Game CreateGame() => new OsuTestBrowser();
+
+ protected override void OnCreate(Bundle savedInstanceState)
+ {
+ base.OnCreate(savedInstanceState);
+
+ // See the comment in OsuGameActivity
+ Assembly.Load("osu.Game.Rulesets.Osu");
+ Assembly.Load("osu.Game.Rulesets.Taiko");
+ Assembly.Load("osu.Game.Rulesets.Catch");
+ Assembly.Load("osu.Game.Rulesets.Mania");
+ }
}
}
diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj
index afafec6b1f..b745d91980 100644
--- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj
+++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj
@@ -1,88 +1,34 @@
-
-
+
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- {122416d6-6b49-4ee2-a1e8-b825f31c79fe}
+ net6.0-android
+ Exe
osu.Game.Tests
osu.Game.Tests.Android
- Properties\AndroidManifest.xml
- armeabi-v7a;x86;arm64-v8a
-
-
-
-
-
-
$(NoWarn);CA2007
-
- None
- cjk;mideast;other;rare;west
- true
-
-
+
%(RecursiveDir)%(Filename)%(Extension)
-
-
+
+
%(RecursiveDir)%(Filename)%(Extension)
-
-
- %(RecursiveDir)%(Filename)%(Extension)
-
-
- %(RecursiveDir)%(Filename)%(Extension)
-
-
- %(RecursiveDir)%(Filename)%(Extension)
-
-
- %(RecursiveDir)%(Filename)%(Extension)
-
-
- %(RecursiveDir)%(Filename)%(Extension)
-
-
- %(RecursiveDir)%(Filename)%(Extension)
-
+ Android\%(RecursiveDir)%(Filename)%(Extension)
+
-
- {58f6c80c-1253-4a0e-a465-b8c85ebeadf3}
- osu.Game.Rulesets.Catch
-
-
- {48f4582b-7687-4621-9cbe-5c24197cb536}
- osu.Game.Rulesets.Mania
-
-
- {c92a607b-1fdd-4954-9f92-03ff547d9080}
- osu.Game.Rulesets.Osu
-
-
- {f167e17a-7de6-4af5-b920-a5112296c695}
- osu.Game.Rulesets.Taiko
-
-
- {2a66dd92-adb1-4994-89e2-c94e04acda0d}
- osu.Game
-
+
+
+
+
+
-
- 5.0.0
-
-
diff --git a/osu.Game.Tests.iOS/Application.cs b/osu.Game.Tests.iOS/Application.cs
index cf36fea139..4678be4fb8 100644
--- a/osu.Game.Tests.iOS/Application.cs
+++ b/osu.Game.Tests.iOS/Application.cs
@@ -3,7 +3,6 @@
#nullable disable
-using osu.Framework.iOS;
using UIKit;
namespace osu.Game.Tests.iOS
@@ -12,7 +11,7 @@ namespace osu.Game.Tests.iOS
{
public static void Main(string[] args)
{
- UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate));
+ UIApplication.Main(args, null, typeof(AppDelegate));
}
}
}
diff --git a/osu.Game.Tests.iOS/Info.plist b/osu.Game.Tests.iOS/Info.plist
index 31e2b3f257..ac661f6263 100644
--- a/osu.Game.Tests.iOS/Info.plist
+++ b/osu.Game.Tests.iOS/Info.plist
@@ -13,7 +13,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 10.0
+ 13.4
UIDeviceFamily
1
diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj
index 05b3cad6da..79771fcd50 100644
--- a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj
+++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj
@@ -1,54 +1,26 @@
-
-
+
- Debug
- iPhoneSimulator
Exe
- {65FF8E19-6934-469B-B690-23C6D6E56A17}
+ net6.0-ios
+ 13.4
osu.Game.Tests
osu.Game.Tests.iOS
-
-
-
- Linker.xml
-
-
-
%(RecursiveDir)%(Filename)%(Extension)
-
- $(NoWarn);CA2007
-
-
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}
- osu.Game
-
-
- {C92A607B-1FDD-4954-9F92-03FF547D9080}
- osu.Game.Rulesets.Osu
-
-
- {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}
- osu.Game.Rulesets.Catch
-
-
- {48F4582B-7687-4621-9CBE-5C24197CB536}
- osu.Game.Rulesets.Mania
-
-
- {F167E17A-7DE6-4AF5-B920-A5112296C695}
- osu.Game.Rulesets.Taiko
-
+
+
+
+
+
-
diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs
index ebfa9bd8b7..3c35dc311f 100644
--- a/osu.Game.Tests/Chat/MessageFormatterTests.cs
+++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs
@@ -26,6 +26,16 @@ namespace osu.Game.Tests.Chat
MessageFormatter.WebsiteRootUrl = originalWebsiteRootUrl;
}
+ [Test]
+ public void TestUnsupportedProtocolLink()
+ {
+ Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a gopher://really-old-protocol we don't support." });
+
+ Assert.AreEqual(result.Content, result.DisplayContent);
+ Assert.AreEqual(1, result.Links.Count);
+ Assert.AreEqual("gopher://really-old-protocol", result.Links[0].Url);
+ }
+
[Test]
public void TestBareLink()
{
diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs
index 8d82843134..d925141510 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneCommentActions.cs
@@ -189,7 +189,7 @@ namespace osu.Game.Tests.Visual.Online
if (request is not CommentDeleteRequest req)
return false;
- req.TriggerFailure(new Exception());
+ req.TriggerFailure(new InvalidOperationException());
delete = true;
return false;
};
diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs
index e47b7e25a8..11d55bc0bd 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs
@@ -136,7 +136,7 @@ namespace osu.Game.Tests.Visual.SongSelect
if (testRequest.Progress >= 0.5f)
{
- testRequest.TriggerFailure(new Exception());
+ testRequest.TriggerFailure(new InvalidOperationException());
return true;
}
}
diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs
index f940571ffe..2d47560947 100644
--- a/osu.Game.Tournament/IPC/FileBasedIPC.cs
+++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs
@@ -245,8 +245,10 @@ namespace osu.Game.Tournament.IPC
{
string stableInstallPath;
+#pragma warning disable CA1416
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
+#pragma warning restore CA1416
if (ipcFileExistsInDirectory(stableInstallPath))
return stableInstallPath;
diff --git a/osu.Game.Tournament/SaveChangesOverlay.cs b/osu.Game.Tournament/SaveChangesOverlay.cs
index a81f11cbe1..1bc576bc63 100644
--- a/osu.Game.Tournament/SaveChangesOverlay.cs
+++ b/osu.Game.Tournament/SaveChangesOverlay.cs
@@ -70,7 +70,7 @@ namespace osu.Game.Tournament
private async Task checkForChanges()
{
- string serialisedLadder = await Task.Run(() => tournamentGame.GetSerialisedLadder());
+ string serialisedLadder = await Task.Run(() => tournamentGame.GetSerialisedLadder()).ConfigureAwait(false);
// If a save hasn't been triggered by the user yet, populate the initial value
lastSerialisedLadder ??= serialisedLadder;
diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs
index 988f0a02f0..eb5c9a879a 100644
--- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs
+++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -54,8 +53,6 @@ namespace osu.Game.Tournament.Screens.Editors
});
}
- Debug.Assert(countries != null);
-
foreach (var c in countries)
Storage.Add(c);
}
diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs
index 8f0d1de0cb..0fb6c1367b 100644
--- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs
+++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs
@@ -4,6 +4,7 @@
#nullable disable
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -102,10 +103,14 @@ namespace osu.Game.Tournament.Screens.Editors
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(args.NewItems != null);
+
args.NewItems.Cast().ForEach(i => flow.Add(CreateDrawable(i)));
break;
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(args.OldItems != null);
+
args.OldItems.Cast().ForEach(i => flow.RemoveAll(d => d.Model == i, true));
break;
}
diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs
index 603a7830c7..5aea551c00 100644
--- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs
+++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -20,8 +21,6 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{
public partial class LadderEditorSettings : PlayerSettingsGroup
{
- private const int padding = 10;
-
private SettingsDropdown roundDropdown;
private PlayerCheckbox losersCheckbox;
private DateTextBox dateTimeBox;
@@ -103,10 +102,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(args.NewItems != null);
+
args.NewItems.Cast().ForEach(add);
break;
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(args.OldItems != null);
+
args.OldItems.Cast().ForEach(i => Control.RemoveDropdownItem(i));
break;
}
diff --git a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs
index c90cdb7775..f7a42e4f50 100644
--- a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs
+++ b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions;
@@ -25,10 +26,14 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(args.NewItems != null);
+
args.NewItems.Cast().ForEach(add);
break;
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(args.OldItems != null);
+
args.OldItems.Cast().ForEach(i => Control.RemoveDropdownItem(i));
break;
}
diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs
index 595f08ed36..176c06c0e5 100644
--- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs
+++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs
@@ -4,6 +4,7 @@
#nullable disable
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Caching;
@@ -81,11 +82,15 @@ namespace osu.Game.Tournament.Screens.Ladder
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(args.NewItems != null);
+
foreach (var p in args.NewItems.Cast())
addMatch(p);
break;
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(args.OldItems != null);
+
foreach (var p in args.OldItems.Cast())
{
foreach (var d in MatchesContainer.Where(d => d.Match == p))
@@ -153,7 +158,7 @@ namespace osu.Game.Tournament.Screens.Ladder
foreach (var round in LadderInfo.Rounds)
{
- var topMatch = MatchesContainer.Where(p => !p.Match.Losers.Value && p.Match.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault();
+ var topMatch = MatchesContainer.Where(p => !p.Match.Losers.Value && p.Match.Round.Value == round).MinBy(p => p.Y);
if (topMatch == null) continue;
@@ -167,7 +172,7 @@ namespace osu.Game.Tournament.Screens.Ladder
foreach (var round in LadderInfo.Rounds)
{
- var topMatch = MatchesContainer.Where(p => p.Match.Losers.Value && p.Match.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault();
+ var topMatch = MatchesContainer.Where(p => p.Match.Losers.Value && p.Match.Round.Value == round).MinBy(p => p.Y);
if (topMatch == null) continue;
diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj
index b049542bb0..ab67e490cd 100644
--- a/osu.Game.Tournament/osu.Game.Tournament.csproj
+++ b/osu.Game.Tournament/osu.Game.Tournament.csproj
@@ -1,6 +1,6 @@
- netstandard2.1
+ net6.0
Library
true
tools for tournaments.
@@ -11,4 +11,4 @@
-
\ No newline at end of file
+
diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs
index 19c78f34b2..0191f96825 100644
--- a/osu.Game/Audio/SampleInfo.cs
+++ b/osu.Game/Audio/SampleInfo.cs
@@ -35,7 +35,7 @@ namespace osu.Game.Audio
public bool Equals(SampleInfo? other)
=> other != null && sampleNames.SequenceEqual(other.sampleNames);
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
=> obj is SampleInfo other && Equals(other);
}
}
diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs
index 8a6315fc65..4752a88199 100644
--- a/osu.Game/Beatmaps/BeatmapImporter.cs
+++ b/osu.Game/Beatmaps/BeatmapImporter.cs
@@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps
public override async Task?> ImportAsUpdate(ProgressNotification notification, ImportTask importTask, BeatmapSetInfo original)
{
- var imported = await Import(notification, new[] { importTask });
+ var imported = await Import(notification, new[] { importTask }).ConfigureAwait(true);
if (!imported.Any())
return null;
diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs
index 2fd1d06b7b..71d40b1a48 100644
--- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs
+++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs
@@ -178,7 +178,7 @@ namespace osu.Game.Beatmaps
{
try
{
- await cacheDownloadRequest.PerformAsync();
+ await cacheDownloadRequest.PerformAsync().ConfigureAwait(false);
}
catch
{
diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs
index 0a09e6e7e6..f46e4af332 100644
--- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs
+++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs
@@ -16,7 +16,7 @@ namespace osu.Game.Beatmaps.ControlPoints
public void AttachGroup(ControlPointGroup pointGroup) => Time = pointGroup.Time;
- public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time);
+ public int CompareTo(ControlPoint? other) => Time.CompareTo(other?.Time);
public virtual Color4 GetRepresentingColour(OsuColour colours) => colours.Yellow;
@@ -32,7 +32,7 @@ namespace osu.Game.Beatmaps.ControlPoints
///
public ControlPoint DeepClone()
{
- var copy = (ControlPoint)Activator.CreateInstance(GetType());
+ var copy = (ControlPoint)Activator.CreateInstance(GetType())!;
copy.CopyFrom(this);
diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs
index db479f0e5b..1f34f3777d 100644
--- a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs
+++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs
@@ -26,7 +26,7 @@ namespace osu.Game.Beatmaps.ControlPoints
Time = time;
}
- public int CompareTo(ControlPointGroup other) => Time.CompareTo(other.Time);
+ public int CompareTo(ControlPointGroup? other) => Time.CompareTo(other?.Time);
public void Add(ControlPoint point)
{
diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs
index 422e306450..55119c800a 100644
--- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs
+++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs
@@ -70,14 +70,14 @@ namespace osu.Game.Beatmaps.ControlPoints
///
[JsonIgnore]
public double BPMMaximum =>
- 60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength;
+ 60000 / (TimingPoints.MinBy(c => c.BeatLength) ?? TimingControlPoint.DEFAULT).BeatLength;
///
/// Finds the minimum BPM represented by any timing control point.
///
[JsonIgnore]
public double BPMMinimum =>
- 60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength;
+ 60000 / (TimingPoints.MaxBy(c => c.BeatLength) ?? TimingControlPoint.DEFAULT).BeatLength;
///
/// Remove all s and return to a pristine state.
@@ -300,7 +300,7 @@ namespace osu.Game.Beatmaps.ControlPoints
public ControlPointInfo DeepClone()
{
- var controlPointInfo = (ControlPointInfo)Activator.CreateInstance(GetType());
+ var controlPointInfo = (ControlPointInfo)Activator.CreateInstance(GetType())!;
foreach (var point in AllControlPoints)
controlPointInfo.Add(point.Time, point.DeepClone());
diff --git a/osu.Game/Beatmaps/DifficultyRecommender.cs b/osu.Game/Beatmaps/DifficultyRecommender.cs
index 7a23b32c84..ec00756fd9 100644
--- a/osu.Game/Beatmaps/DifficultyRecommender.cs
+++ b/osu.Game/Beatmaps/DifficultyRecommender.cs
@@ -51,11 +51,11 @@ namespace osu.Game.Beatmaps
if (!recommendedDifficultyMapping.TryGetValue(r, out double recommendation))
continue;
- BeatmapInfo beatmapInfo = beatmaps.Where(b => b.Ruleset.ShortName.Equals(r)).OrderBy(b =>
+ BeatmapInfo beatmapInfo = beatmaps.Where(b => b.Ruleset.ShortName.Equals(r, StringComparison.Ordinal)).MinBy(b =>
{
double difference = b.StarRating - recommendation;
return difference >= 0 ? difference * 2 : difference * -1; // prefer easier over harder
- }).FirstOrDefault();
+ });
if (beatmapInfo != null)
return beatmapInfo;
@@ -90,7 +90,7 @@ namespace osu.Game.Beatmaps
return recommendedDifficultyMapping
.OrderByDescending(pair => pair.Value)
.Select(pair => pair.Key)
- .Where(r => !r.Equals(ruleset.Value.ShortName))
+ .Where(r => !r.Equals(ruleset.Value.ShortName, StringComparison.Ordinal))
.Prepend(ruleset.Value.ShortName);
}
}
diff --git a/osu.Game/Configuration/SettingSourceAttribute.cs b/osu.Game/Configuration/SettingSourceAttribute.cs
index 043bba3134..1e425c88a6 100644
--- a/osu.Game/Configuration/SettingSourceAttribute.cs
+++ b/osu.Game/Configuration/SettingSourceAttribute.cs
@@ -91,15 +91,15 @@ namespace osu.Game.Configuration
OrderPosition = orderPosition;
}
- public int CompareTo(SettingSourceAttribute other)
+ public int CompareTo(SettingSourceAttribute? other)
{
- if (OrderPosition == other.OrderPosition)
+ if (OrderPosition == other?.OrderPosition)
return 0;
// unordered items come last (are greater than any ordered items).
if (OrderPosition == null)
return 1;
- if (other.OrderPosition == null)
+ if (other?.OrderPosition == null)
return -1;
// ordered items are sorted by the order value.
@@ -113,7 +113,7 @@ namespace osu.Game.Configuration
{
foreach (var (attr, property) in obj.GetOrderedSettingsSourceProperties())
{
- object value = property.GetValue(obj);
+ object value = property.GetValue(obj)!;
if (attr.SettingControlType != null)
{
@@ -121,7 +121,7 @@ namespace osu.Game.Configuration
if (controlType.EnumerateBaseTypes().All(t => !t.IsGenericType || t.GetGenericTypeDefinition() != typeof(SettingsItem<>)))
throw new InvalidOperationException($"{nameof(SettingSourceAttribute)} had an unsupported custom control type ({controlType.ReadableName()})");
- var control = (Drawable)Activator.CreateInstance(controlType);
+ var control = (Drawable)Activator.CreateInstance(controlType)!;
controlType.GetProperty(nameof(SettingsItem
public virtual Mod DeepClone()
{
- var result = (Mod)Activator.CreateInstance(GetType());
+ var result = (Mod)Activator.CreateInstance(GetType())!;
result.CopyFrom(this);
return result;
}
@@ -150,8 +150,8 @@ namespace osu.Game.Rulesets.Mods
foreach (var (_, prop) in this.GetSettingsSourceProperties())
{
- var targetBindable = (IBindable)prop.GetValue(this);
- var sourceBindable = (IBindable)prop.GetValue(source);
+ var targetBindable = (IBindable)prop.GetValue(this)!;
+ var sourceBindable = (IBindable)prop.GetValue(source)!;
CopyAdjustedSetting(targetBindable, sourceBindable);
}
@@ -183,9 +183,9 @@ namespace osu.Game.Rulesets.Mods
}
}
- public bool Equals(IMod other) => other is Mod them && Equals(them);
+ public bool Equals(IMod? other) => other is Mod them && Equals(them);
- public bool Equals(Mod other)
+ public bool Equals(Mod? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
@@ -209,16 +209,16 @@ namespace osu.Game.Rulesets.Mods
///
/// Reset all custom settings for this mod back to their defaults.
///
- public virtual void ResetSettingsToDefaults() => CopyFrom((Mod)Activator.CreateInstance(GetType()));
+ public virtual void ResetSettingsToDefaults() => CopyFrom((Mod)Activator.CreateInstance(GetType())!);
private class ModSettingsEqualityComparer : IEqualityComparer
{
public static ModSettingsEqualityComparer Default { get; } = new ModSettingsEqualityComparer();
- public bool Equals(IBindable x, IBindable y)
+ public bool Equals(IBindable? x, IBindable? y)
{
- object xValue = x.GetUnderlyingSettingValue();
- object yValue = y.GetUnderlyingSettingValue();
+ object? xValue = x?.GetUnderlyingSettingValue();
+ object? yValue = y?.GetUnderlyingSettingValue();
return EqualityComparer.Default.Equals(xValue, yValue);
}
diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs
index ddc121eb5b..c9d2928dc3 100644
--- a/osu.Game/Rulesets/Objects/SliderPath.cs
+++ b/osu.Game/Rulesets/Objects/SliderPath.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Bindables;
@@ -57,12 +58,16 @@ namespace osu.Game.Rulesets.Objects
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(args.NewItems != null);
+
foreach (var c in args.NewItems.Cast())
c.Changed += invalidate;
break;
case NotifyCollectionChangedAction.Reset:
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(args.OldItems != null);
+
foreach (var c in args.OldItems.Cast())
c.Changed -= invalidate;
break;
diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs
index a446210c8a..a73151362b 100644
--- a/osu.Game/Rulesets/Ruleset.cs
+++ b/osu.Game/Rulesets/Ruleset.cs
@@ -89,6 +89,8 @@ namespace osu.Game.Rulesets
// Confine all mods of each mod type into a single IEnumerable
.SelectMany(GetModsFor)
// Filter out all null mods
+ // This is to handle old rulesets which were doing mods bad. Can be removed at some point we are sure nulls will not appear here.
+ // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
.Where(mod => mod != null)
// Resolve MultiMods as their .Mods property
.SelectMany(mod => (mod as MultiMod)?.Mods ?? new[] { mod });
diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs
index 91954320a4..6a4e0f0b48 100644
--- a/osu.Game/Rulesets/RulesetInfo.cs
+++ b/osu.Game/Rulesets/RulesetInfo.cs
@@ -53,21 +53,21 @@ namespace osu.Game.Rulesets
public bool Equals(IRulesetInfo? other) => other is RulesetInfo r && Equals(r);
- public int CompareTo(RulesetInfo other)
+ public int CompareTo(RulesetInfo? other)
{
- if (OnlineID >= 0 && other.OnlineID >= 0)
+ if (OnlineID >= 0 && other?.OnlineID >= 0)
return OnlineID.CompareTo(other.OnlineID);
// Official rulesets are always given precedence for the time being.
if (OnlineID >= 0)
return -1;
- if (other.OnlineID >= 0)
+ if (other?.OnlineID >= 0)
return 1;
- return string.Compare(ShortName, other.ShortName, StringComparison.Ordinal);
+ return string.Compare(ShortName, other?.ShortName, StringComparison.Ordinal);
}
- public int CompareTo(IRulesetInfo other)
+ public int CompareTo(IRulesetInfo? other)
{
if (!(other is RulesetInfo ruleset))
throw new ArgumentException($@"Object is not of type {nameof(RulesetInfo)}.", nameof(other));
diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs
index e2b8cd2c4e..881b09bd1b 100644
--- a/osu.Game/Rulesets/RulesetStore.cs
+++ b/osu.Game/Rulesets/RulesetStore.cs
@@ -75,10 +75,7 @@ namespace osu.Game.Rulesets
return false;
return args.Name.Contains(name, StringComparison.Ordinal);
- })
- // Pick the greatest assembly version.
- .OrderByDescending(a => a.GetName().Version)
- .FirstOrDefault();
+ }).MaxBy(a => a.GetName().Version);
if (domainAssembly != null)
return domainAssembly;
@@ -114,7 +111,10 @@ namespace osu.Game.Rulesets
{
try
{
- string[] files = Directory.GetFiles(RuntimeInfo.StartupDirectory, @$"{ruleset_library_prefix}.*.dll");
+ // On net6-android (Debug), StartupDirectory can be different from where assemblies are placed.
+ // Search sub-directories too.
+
+ string[] files = Directory.GetFiles(RuntimeInfo.StartupDirectory, @$"{ruleset_library_prefix}.*.dll", SearchOption.AllDirectories);
foreach (string file in files.Where(f => !Path.GetFileName(f).Contains("Tests")))
loadRulesetFromFile(file);
@@ -127,7 +127,7 @@ namespace osu.Game.Rulesets
private void loadRulesetFromFile(string file)
{
- string? filename = Path.GetFileNameWithoutExtension(file);
+ string filename = Path.GetFileNameWithoutExtension(file);
if (LoadedAssemblies.Values.Any(t => Path.GetFileNameWithoutExtension(t.Assembly.Location) == filename))
return;
@@ -158,7 +158,7 @@ namespace osu.Game.Rulesets
}
catch (Exception e)
{
- LogFailedLoad(assembly.GetName().Name.Split('.').Last(), e);
+ LogFailedLoad(assembly.GetName().Name!.Split('.').Last(), e);
}
}
diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs
index cdfe71943e..b70ddd5e24 100644
--- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs
+++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs
@@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Scoring
{
foreach (var condition in FailConditions.GetInvocationList())
{
- bool conditionResult = (bool)condition.Method.Invoke(condition.Target, new object[] { this, result });
+ bool conditionResult = (bool)condition.Method.Invoke(condition.Target, new object[] { this, result })!;
if (conditionResult)
return true;
}
diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
index b048566c8a..4228840461 100644
--- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
+++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
@@ -534,7 +534,7 @@ namespace osu.Game.Rulesets.Scoring
break;
default:
- maxResult = maxBasicResult ??= ruleset.GetHitResults().OrderByDescending(kvp => Judgement.ToNumericResult(kvp.result)).First().result;
+ maxResult = maxBasicResult ??= ruleset.GetHitResults().MaxBy(kvp => Judgement.ToNumericResult(kvp.result)).result;
break;
}
diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs
index d068f8d016..d2244df3b8 100644
--- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs
+++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs
@@ -79,9 +79,7 @@ namespace osu.Game.Rulesets.UI
// We need to use lifetime entries to find the next object (we can't just use `hitObjectContainer.Objects` due to pooling - it may even be empty).
// If required, we can make this lookup more efficient by adding support to get next-future-entry in LifetimeEntryManager.
fallbackObject = hitObjectContainer.Entries
- .Where(e => e.Result?.HasResult != true)
- .OrderBy(e => e.HitObject.StartTime)
- .FirstOrDefault();
+ .Where(e => e.Result?.HasResult != true).MinBy(e => e.HitObject.StartTime);
// In the case there are no unjudged objects, the last hit object should be used instead.
fallbackObject ??= hitObjectContainer.Entries.LastOrDefault();
diff --git a/osu.Game/Scoring/ScoreImporter.cs b/osu.Game/Scoring/ScoreImporter.cs
index 4656f02897..797d80b7fa 100644
--- a/osu.Game/Scoring/ScoreImporter.cs
+++ b/osu.Game/Scoring/ScoreImporter.cs
@@ -101,8 +101,7 @@ namespace osu.Game.Scoring
// Populate the maximum statistics.
HitResult maxBasicResult = rulesetInstance.GetHitResults()
.Select(h => h.result)
- .Where(h => h.IsBasic())
- .OrderByDescending(Judgement.ToNumericResult).First();
+ .Where(h => h.IsBasic()).MaxBy(Judgement.ToNumericResult);
foreach ((HitResult result, int count) in score.Statistics)
{
diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs
index a9ced62c95..1009474d89 100644
--- a/osu.Game/Scoring/ScoreInfo.cs
+++ b/osu.Game/Scoring/ScoreInfo.cs
@@ -317,7 +317,7 @@ namespace osu.Game.Scoring
#endregion
- public bool Equals(ScoreInfo other) => other.ID == ID;
+ public bool Equals(ScoreInfo? other) => other?.ID == ID;
public override string ToString() => this.GetDisplayTitle();
}
diff --git a/osu.Game/Scoring/ScoreModelDownloader.cs b/osu.Game/Scoring/ScoreModelDownloader.cs
index 514b7a57de..c5434e8faf 100644
--- a/osu.Game/Scoring/ScoreModelDownloader.cs
+++ b/osu.Game/Scoring/ScoreModelDownloader.cs
@@ -17,7 +17,7 @@ namespace osu.Game.Scoring
protected override ArchiveDownloadRequest CreateDownloadRequest(IScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score);
- public override ArchiveDownloadRequest GetExistingDownload(IScoreInfo model)
+ public override ArchiveDownloadRequest? GetExistingDownload(IScoreInfo model)
=> CurrentDownloads.Find(r => r.Model.MatchesOnlineID(model));
}
}
diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs
index 2d26e6f90b..111ba0b732 100644
--- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Bindables;
using osu.Game.Beatmaps.ControlPoints;
@@ -33,6 +34,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
break;
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(args.NewItems != null);
+
foreach (var group in args.NewItems.OfType())
{
// as an optimisation, don't add a visualisation if there are already groups with the same types in close proximity.
@@ -47,6 +50,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
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));
diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs
index 903c117422..9f422d5aa9 100644
--- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs
@@ -479,7 +479,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
// copied from SliderBar so we can do custom spacing logic.
float xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth;
- CurrentNumber.Value = beatDivisor.ValidDivisors.Value.Presets.OrderBy(d => Math.Abs(getMappedPosition(d) - xPosition)).First();
+ CurrentNumber.Value = beatDivisor.ValidDivisors.Value.Presets.MinBy(d => Math.Abs(getMappedPosition(d) - xPosition));
OnUserChange(Current.Value);
}
diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
index 60fec5bcc6..77892f21e6 100644
--- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
@@ -58,6 +58,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(args.NewItems != null);
+
foreach (object o in args.NewItems)
{
if (blueprintMap.TryGetValue((T)o, out var blueprint))
@@ -67,6 +69,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
break;
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(args.OldItems != null);
+
foreach (object o in args.OldItems)
{
if (blueprintMap.TryGetValue((T)o, out var blueprint))
diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs
index 9783c4184a..29983c9cbf 100644
--- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs
@@ -4,6 +4,7 @@
#nullable disable
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Bindables;
using osu.Game.Beatmaps.ControlPoints;
@@ -33,11 +34,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
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));
diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs
index 3af7a400e2..dc026f7eac 100644
--- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs
+++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs
@@ -152,7 +152,7 @@ namespace osu.Game.Screens.Edit.Compose
if (composer == null)
return string.Empty;
- double displayTime = EditorBeatmap.SelectedHitObjects.OrderBy(h => h.StartTime).FirstOrDefault()?.StartTime ?? clock.CurrentTime;
+ double displayTime = EditorBeatmap.SelectedHitObjects.MinBy(h => h.StartTime)?.StartTime ?? clock.CurrentTime;
string selectionAsString = composer.ConvertSelectionToString();
return !string.IsNullOrEmpty(selectionAsString)
diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs
index e204b44db3..1554bf1bb1 100644
--- a/osu.Game/Screens/Edit/EditorBeatmap.cs
+++ b/osu.Game/Screens/Edit/EditorBeatmap.cs
@@ -304,7 +304,7 @@ namespace osu.Game.Screens.Edit
/// The index of the to remove.
public void RemoveAt(int index)
{
- var hitObject = (HitObject)mutableHitObjects[index];
+ HitObject hitObject = (HitObject)mutableHitObjects[index]!;
mutableHitObjects.RemoveAt(index);
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs
index 3b66355dab..c31633eefc 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs
@@ -4,6 +4,7 @@
#nullable disable
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -197,11 +198,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(e.NewItems != null);
+
foreach (var added in e.NewItems.OfType())
addUser(added);
break;
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(e.OldItems != null);
+
foreach (var removed in e.OldItems.OfType())
removeUser(removed);
break;
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs
index e723dfe3e6..ac6403bb34 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -117,10 +118,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(args.NewItems != null);
+
addRooms(args.NewItems.Cast());
break;
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(args.OldItems != null);
+
removeRooms(args.OldItems.Cast());
break;
}
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs
index fe27e2cf20..2d2aa0f1d5 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs
@@ -34,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
///
/// Whether all spectating players have finished loading.
///
- public bool AllPlayersLoaded => instances.All(p => p?.PlayerLoaded == true);
+ public bool AllPlayersLoaded => instances.All(p => p.PlayerLoaded);
protected override UserActivity InitialActivity => new UserActivity.SpectatingMultiplayerGame(Beatmap.Value.BeatmapInfo, Ruleset.Value);
@@ -171,9 +171,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
if (!isCandidateAudioSource(currentAudioSource?.SpectatorPlayerClock))
{
- currentAudioSource = instances.Where(i => isCandidateAudioSource(i.SpectatorPlayerClock))
- .OrderBy(i => Math.Abs(i.SpectatorPlayerClock.CurrentTime - syncManager.CurrentMasterTime))
- .FirstOrDefault();
+ currentAudioSource = instances.Where(i => isCandidateAudioSource(i.SpectatorPlayerClock)).MinBy(i => Math.Abs(i.SpectatorPlayerClock.CurrentTime - syncManager.CurrentMasterTime));
// Only bind adjustments if there's actually a valid source, else just use the previous ones to ensure no sudden changes to audio.
if (currentAudioSource != null)
diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs
index 50a9992f4f..e93f56c2e2 100644
--- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs
+++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs
@@ -349,7 +349,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
public void SelectBeatmap() => editPlaylistButton.TriggerClick();
- private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) =>
+ private void onPlaylistChanged(object? sender, NotifyCollectionChangedEventArgs e) =>
playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}";
private bool hasValidSettings => RoomID.Value == null && NameField.Text.Length > 0 && Playlist.Count > 0;
diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs
index 2743173a6d..620f3718c2 100644
--- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs
+++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using System.Threading;
using osu.Framework.Allocation;
@@ -153,11 +154,13 @@ namespace osu.Game.Screens.Play.HUD
}
}
- private void playingUsersChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void playingUsersChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
+ Debug.Assert(e.OldItems != null);
+
foreach (int userId in e.OldItems.OfType())
{
spectatorClient.StopWatchingUser(userId);
diff --git a/osu.Game/Screens/Play/HUD/SkinnableInfo.cs b/osu.Game/Screens/Play/HUD/SkinnableInfo.cs
index 6d63776dbb..da759b4329 100644
--- a/osu.Game/Screens/Play/HUD/SkinnableInfo.cs
+++ b/osu.Game/Screens/Play/HUD/SkinnableInfo.cs
@@ -67,7 +67,7 @@ namespace osu.Game.Screens.Play.HUD
foreach (var (_, property) in component.GetSettingsSourceProperties())
{
- var bindable = (IBindable)property.GetValue(component);
+ var bindable = (IBindable)property.GetValue(component)!;
if (!bindable.IsDefault)
Settings.Add(property.Name.ToSnakeCase(), bindable.GetUnderlyingSettingValue());
@@ -88,7 +88,7 @@ namespace osu.Game.Screens.Play.HUD
{
try
{
- Drawable d = (Drawable)Activator.CreateInstance(Type);
+ Drawable d = (Drawable)Activator.CreateInstance(Type)!;
d.ApplySkinnableInfo(this);
return d;
}
diff --git a/osu.Game/Screens/Utility/LatencyCertifierScreen.cs b/osu.Game/Screens/Utility/LatencyCertifierScreen.cs
index 8ff6d3cf4f..212cebeaf5 100644
--- a/osu.Game/Screens/Utility/LatencyCertifierScreen.cs
+++ b/osu.Game/Screens/Utility/LatencyCertifierScreen.cs
@@ -259,10 +259,7 @@ namespace osu.Game.Screens.Utility
var displayMode = host.Window?.CurrentDisplayMode.Value;
- string exclusive = "unknown";
-
- if (host.Renderer is IWindowsRenderer windowsRenderer)
- exclusive = windowsRenderer.FullscreenCapability.ToString();
+ string exclusive = (host.Renderer as IWindowsRenderer)?.FullscreenCapability.ToString() ?? "unknown";
statusText.Clear();
diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs
index 8e9256214f..9812406aad 100644
--- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs
+++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -65,17 +66,24 @@ namespace osu.Game.Skinning.Editor
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
+ Debug.Assert(e.NewItems != null);
+
foreach (var item in e.NewItems.Cast())
AddBlueprintFor(item);
break;
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Reset:
+ Debug.Assert(e.OldItems != null);
+
foreach (var item in e.OldItems.Cast())
RemoveBlueprintFor(item);
break;
case NotifyCollectionChangedAction.Replace:
+ Debug.Assert(e.NewItems != null);
+ Debug.Assert(e.OldItems != null);
+
foreach (var item in e.OldItems.Cast())
RemoveBlueprintFor(item);
diff --git a/osu.Game/Skinning/Editor/SkinComponentToolbox.cs b/osu.Game/Skinning/Editor/SkinComponentToolbox.cs
index 68ac84df48..053119557f 100644
--- a/osu.Game/Skinning/Editor/SkinComponentToolbox.cs
+++ b/osu.Game/Skinning/Editor/SkinComponentToolbox.cs
@@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using System.Diagnostics;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -59,9 +58,7 @@ namespace osu.Game.Skinning.Editor
{
try
{
- var instance = (Drawable)Activator.CreateInstance(type);
-
- Debug.Assert(instance != null);
+ Drawable instance = (Drawable)Activator.CreateInstance(type)!;
if (!((ISkinnableDrawable)instance).IsEditable) return;
diff --git a/osu.Game/Skinning/GameplaySkinComponentLookup.cs b/osu.Game/Skinning/GameplaySkinComponentLookup.cs
index 2d1dec4691..9247ca0e4d 100644
--- a/osu.Game/Skinning/GameplaySkinComponentLookup.cs
+++ b/osu.Game/Skinning/GameplaySkinComponentLookup.cs
@@ -16,7 +16,7 @@ namespace osu.Game.Skinning
}
protected virtual string RulesetPrefix => string.Empty;
- protected virtual string ComponentName => Component.ToString();
+ protected virtual string ComponentName => Component.ToString() ?? string.Empty;
public string LookupName =>
string.Join('/', new[] { "Gameplay", RulesetPrefix, ComponentName }.Where(s => !string.IsNullOrEmpty(s)));
diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs
index ea223d172d..5f12d2ce23 100644
--- a/osu.Game/Skinning/LegacySkin.cs
+++ b/osu.Game/Skinning/LegacySkin.cs
@@ -105,7 +105,7 @@ namespace osu.Game.Skinning
return SkinUtils.As(GetComboColour(Configuration, comboColour.ColourIndex, comboColour.Combo));
case SkinCustomColourLookup customColour:
- return SkinUtils.As(getCustomColour(Configuration, customColour.Lookup.ToString()));
+ return SkinUtils.As(getCustomColour(Configuration, customColour.Lookup.ToString() ?? string.Empty));
case LegacyManiaSkinConfigurationLookup maniaLookup:
if (!AllowManiaSkin)
@@ -277,7 +277,7 @@ namespace osu.Game.Skinning
=> source.CustomColours.TryGetValue(lookup, out var col) ? new Bindable(col) : null;
private IBindable? getManiaImage(LegacyManiaSkinConfiguration source, string lookup)
- => source.ImageLookups.TryGetValue(lookup, out string image) ? new Bindable(image) : null;
+ => source.ImageLookups.TryGetValue(lookup, out string? image) ? new Bindable(image) : null;
private IBindable? legacySettingLookup(SkinConfiguration.LegacySetting legacySetting)
where TValue : notnull
@@ -298,7 +298,7 @@ namespace osu.Game.Skinning
{
try
{
- if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString(), out string val))
+ if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString() ?? string.Empty, out string? val))
{
// special case for handling skins which use 1 or 0 to signify a boolean state.
// ..or in some cases 2 (https://github.com/ppy/osu/issues/18579).
diff --git a/osu.Game/Skinning/RealmBackedResourceStore.cs b/osu.Game/Skinning/RealmBackedResourceStore.cs
index 0cc90f1dcb..cc887a7a61 100644
--- a/osu.Game/Skinning/RealmBackedResourceStore.cs
+++ b/osu.Game/Skinning/RealmBackedResourceStore.cs
@@ -52,7 +52,7 @@ namespace osu.Game.Skinning
private string? getPathForFile(string filename)
{
- if (fileToStoragePathMapping.Value.TryGetValue(filename.ToLowerInvariant(), out string path))
+ if (fileToStoragePathMapping.Value.TryGetValue(filename.ToLowerInvariant(), out string? path))
return path;
return null;
diff --git a/osu.Game/Skinning/SkinImporter.cs b/osu.Game/Skinning/SkinImporter.cs
index f594a7b2d2..1685562cc7 100644
--- a/osu.Game/Skinning/SkinImporter.cs
+++ b/osu.Game/Skinning/SkinImporter.cs
@@ -37,7 +37,7 @@ namespace osu.Game.Skinning
protected override string[] HashableFileTypes => new[] { ".ini", ".json" };
- protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == @".osk";
+ protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path).ToLowerInvariant() == @".osk";
protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name ?? @"No name" };
diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs
index d051149155..7b31c8fe88 100644
--- a/osu.Game/Skinning/SkinInfo.cs
+++ b/osu.Game/Skinning/SkinInfo.cs
@@ -56,7 +56,7 @@ namespace osu.Game.Skinning
return new TrianglesSkin(this, resources);
}
- return (Skin)Activator.CreateInstance(type, this, resources);
+ return (Skin)Activator.CreateInstance(type, this, resources)!;
}
public IList Files { get; } = null!;
diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs
index e86ee9e63d..e598c79b08 100644
--- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs
+++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs
@@ -137,7 +137,7 @@ namespace osu.Game.Storyboards.Drawables
// When reading from a skin, we match stables weird behaviour where `FrameCount` is ignored
// and resources are retrieved until the end of the animation.
- foreach (var texture in skin.GetTextures(Path.GetFileNameWithoutExtension(Animation.Path), default, default, true, string.Empty, out _))
+ foreach (var texture in skin.GetTextures(Path.GetFileNameWithoutExtension(Animation.Path)!, default, default, true, string.Empty, out _))
AddFrame(texture, Animation.FrameDelay);
}
diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs
index 8133244e89..566e064aad 100644
--- a/osu.Game/Storyboards/Storyboard.cs
+++ b/osu.Game/Storyboards/Storyboard.cs
@@ -32,7 +32,7 @@ namespace osu.Game.Storyboards
///
/// This iterates all elements and as such should be used sparingly or stored locally.
///
- public double? EarliestEventTime => Layers.SelectMany(l => l.Elements).OrderBy(e => e.StartTime).FirstOrDefault()?.StartTime;
+ public double? EarliestEventTime => Layers.SelectMany(l => l.Elements).MinBy(e => e.StartTime)?.StartTime;
///
/// Across all layers, find the latest point in time that a storyboard element ends at.
@@ -42,7 +42,7 @@ namespace osu.Game.Storyboards
/// This iterates all elements and as such should be used sparingly or stored locally.
/// Videos and samples return StartTime as their EndTIme.
///
- public double? LatestEventTime => Layers.SelectMany(l => l.Elements).OrderBy(e => e.GetEndTime()).LastOrDefault()?.GetEndTime();
+ public double? LatestEventTime => Layers.SelectMany(l => l.Elements).MaxBy(e => e.GetEndTime())?.GetEndTime();
///
/// Depth of the currently front-most storyboard layer, excluding the overlay layer.
diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs
index cd7788bb08..5b7b194be7 100644
--- a/osu.Game/Storyboards/StoryboardSprite.cs
+++ b/osu.Game/Storyboards/StoryboardSprite.cs
@@ -48,7 +48,7 @@ namespace osu.Game.Storyboards
if (alphaCommands.Count > 0)
{
- var firstAlpha = alphaCommands.OrderBy(t => t.startTime).First();
+ var firstAlpha = alphaCommands.MinBy(t => t.startTime);
if (firstAlpha.isZeroStartValue)
return firstAlpha.startTime;
diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs
index c5f6f58b86..79f629ce49 100644
--- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs
+++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs
@@ -185,7 +185,7 @@ namespace osu.Game.Tests.Beatmaps
private Stream openResource(string name)
{
- string localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).AsNonNull();
+ string localPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).AsNonNull();
return Assembly.LoadFrom(Path.Combine(localPath, $"{ResourceAssembly}.dll")).GetManifestResourceStream($@"{ResourceAssembly}.Resources.{name}");
}
diff --git a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs
index c7441f68bd..16434406b5 100644
--- a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs
+++ b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs
@@ -3,7 +3,6 @@
#nullable disable
-using System;
using System.IO;
using System.Reflection;
using NUnit.Framework;
@@ -54,7 +53,7 @@ namespace osu.Game.Tests.Beatmaps
private Stream openResource(string name)
{
- string localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)).AsNonNull();
+ string localPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).AsNonNull();
return Assembly.LoadFrom(Path.Combine(localPath, $"{ResourceAssembly}.dll")).GetManifestResourceStream($@"{ResourceAssembly}.Resources.{name}");
}
diff --git a/osu.Game/Tests/PollingNotificationsClient.cs b/osu.Game/Tests/PollingNotificationsClient.cs
index 571a7a1ed1..450c763170 100644
--- a/osu.Game/Tests/PollingNotificationsClient.cs
+++ b/osu.Game/Tests/PollingNotificationsClient.cs
@@ -24,8 +24,8 @@ namespace osu.Game.Tests
{
while (!cancellationToken.IsCancellationRequested)
{
- await API.PerformAsync(CreateInitialFetchRequest());
- await Task.Delay(1000, cancellationToken);
+ await API.PerformAsync(CreateInitialFetchRequest()).ConfigureAwait(true);
+ await Task.Delay(1000, cancellationToken).ConfigureAwait(true);
}
}, cancellationToken);
diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
index 765c665966..ad5e3f6c4d 100644
--- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
@@ -108,9 +108,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
// simulate the server's automatic assignment of users to teams on join.
// the "best" team is the one with the least users on it.
int bestTeam = teamVersus.Teams
- .Select(team => (teamID: team.ID, userCount: ServerRoom.Users.Count(u => (u.MatchState as TeamVersusUserState)?.TeamID == team.ID)))
- .OrderBy(pair => pair.userCount)
- .First().teamID;
+ .Select(team => (teamID: team.ID, userCount: ServerRoom.Users.Count(u => (u.MatchState as TeamVersusUserState)?.TeamID == team.ID))).MinBy(pair => pair.userCount).teamID;
user.MatchState = new TeamVersusUserState { TeamID = bestTeam };
((IMultiplayerClient)this).MatchUserStateChanged(clone(user.UserID), clone(user.MatchState)).WaitSafely();
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 8639ce6361..8bb68faf7b 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -1,6 +1,6 @@
- netstandard2.1
+ net6.0
Library
true
@@ -35,7 +35,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 184e3303c8..98d3e129d4 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -1,72 +1,19 @@
- 8.0
- {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Resources
- PackageReference
- bin\$(Platform)\$(Configuration)
- cjk,mideast,other,rare,west
- false
- NSUrlSessionHandler
-
iPhone Developer
- true
-
-
-
- --nosymbolstrip=BASS_FX_BPM_BeatCallbackReset --nosymbolstrip=BASS_FX_BPM_BeatCallbackSet --nosymbolstrip=BASS_FX_BPM_BeatDecodeGet --nosymbolstrip=BASS_FX_BPM_BeatFree --nosymbolstrip=BASS_FX_BPM_BeatGetParameters --nosymbolstrip=BASS_FX_BPM_BeatSetParameters --nosymbolstrip=BASS_FX_BPM_CallbackReset --nosymbolstrip=BASS_FX_BPM_CallbackSet --nosymbolstrip=BASS_FX_BPM_DecodeGet --nosymbolstrip=BASS_FX_BPM_Free --nosymbolstrip=BASS_FX_BPM_Translate --nosymbolstrip=BASS_FX_GetVersion --nosymbolstrip=BASS_FX_ReverseCreate --nosymbolstrip=BASS_FX_ReverseGetSource --nosymbolstrip=BASS_FX_TempoCreate --nosymbolstrip=BASS_FX_TempoGetRateRatio --nosymbolstrip=BASS_FX_TempoGetSource --nosymbolstrip=BASS_Mixer_ChannelFlags --nosymbolstrip=BASS_Mixer_ChannelGetData --nosymbolstrip=BASS_Mixer_ChannelGetEnvelopePos --nosymbolstrip=BASS_Mixer_ChannelGetLevel --nosymbolstrip=BASS_Mixer_ChannelGetLevelEx --nosymbolstrip=BASS_Mixer_ChannelGetMatrix --nosymbolstrip=BASS_Mixer_ChannelGetMixer --nosymbolstrip=BASS_Mixer_ChannelGetPosition --nosymbolstrip=BASS_Mixer_ChannelGetPositionEx --nosymbolstrip=BASS_Mixer_ChannelIsActive --nosymbolstrip=BASS_Mixer_ChannelRemove --nosymbolstrip=BASS_Mixer_ChannelRemoveSync --nosymbolstrip=BASS_Mixer_ChannelSetEnvelope --nosymbolstrip=BASS_Mixer_ChannelSetEnvelopePos --nosymbolstrip=BASS_Mixer_ChannelSetMatrix --nosymbolstrip=BASS_Mixer_ChannelSetMatrixEx --nosymbolstrip=BASS_Mixer_ChannelSetPosition --nosymbolstrip=BASS_Mixer_ChannelSetSync --nosymbolstrip=BASS_Mixer_GetVersion --nosymbolstrip=BASS_Mixer_StreamAddChannel --nosymbolstrip=BASS_Mixer_StreamAddChannelEx --nosymbolstrip=BASS_Mixer_StreamCreate --nosymbolstrip=BASS_Mixer_StreamGetChannels --nosymbolstrip=BASS_Split_StreamCreate --nosymbolstrip=BASS_Split_StreamGetAvailable --nosymbolstrip=BASS_Split_StreamGetSource --nosymbolstrip=BASS_Split_StreamGetSplits --nosymbolstrip=BASS_Split_StreamReset --nosymbolstrip=BASS_Split_StreamResetEx
-
- --nolinkaway --nostrip $(GeneratedMtouchSymbolStripFlags)
-
-
- true
- full
- false
- DEBUG;ENABLE_TEST_CLOUD;
- true
- true
-
-
- pdbonly
- true
-
-
- x86_64
- None
+ true
+
+ true
+
+ $(NoWarn);MT7091
- true
- SdkOnly
- ARM64
- Entitlements.plist
+ ios-arm64
-
- true
- 25823
- false
-
-
- true
-
-
- true
- 28126
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(NoWarn);NU1605
+
+ iossimulator-x64
@@ -77,16 +24,15 @@
none
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ <_LinkerFrameworks Remove="Quartz"/>
+
+
diff --git a/osu.iOS/Application.cs b/osu.iOS/Application.cs
index c5b2d0b451..64eb5c63f5 100644
--- a/osu.iOS/Application.cs
+++ b/osu.iOS/Application.cs
@@ -3,7 +3,6 @@
#nullable disable
-using osu.Framework.iOS;
using UIKit;
namespace osu.iOS
@@ -12,7 +11,7 @@ namespace osu.iOS
{
public static void Main(string[] args)
{
- UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate));
+ UIApplication.Main(args, null, typeof(AppDelegate));
}
}
}
diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist
index 16cb68fa7d..c4b08ab78e 100644
--- a/osu.iOS/Info.plist
+++ b/osu.iOS/Info.plist
@@ -15,7 +15,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 10.0
+ 13.4
UIDeviceFamily
1
diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs
index b3194e497b..cb3b260033 100644
--- a/osu.iOS/OsuGameIOS.cs
+++ b/osu.iOS/OsuGameIOS.cs
@@ -5,6 +5,7 @@
using System;
using Foundation;
+using Microsoft.Maui.Devices;
using osu.Framework.Graphics;
using osu.Framework.Input.Handlers;
using osu.Framework.iOS.Input;
@@ -12,7 +13,6 @@ using osu.Game;
using osu.Game.Overlays.Settings;
using osu.Game.Updater;
using osu.Game.Utils;
-using Xamarin.Essentials;
namespace osu.iOS
{
diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj
index b9da874f30..def538af1a 100644
--- a/osu.iOS/osu.iOS.csproj
+++ b/osu.iOS/osu.iOS.csproj
@@ -1,124 +1,16 @@
-
-
-
- Debug
- iPhoneSimulator
+
+
+ net6.0-ios
+ 13.4
Exe
- {3F082D0B-A964-43D7-BDF7-C256D76A50D0}
- osu.iOS
- osu.iOS
- false
+ true
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}
- osu.Game
-
-
- {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}
- osu.Game.Rulesets.Catch
-
-
- {48F4582B-7687-4621-9CBE-5C24197CB536}
- osu.Game.Rulesets.Mania
-
-
- {C92A607B-1FDD-4954-9F92-03FF547D9080}
- osu.Game.Rulesets.Osu
-
-
- {F167E17A-7DE6-4AF5-B920-A5112296C695}
- osu.Game.Rulesets.Taiko
-
-
-
-
-
-
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
-
-
-
-
diff --git a/osu.sln b/osu.sln
index aeec0843be..5b23ff9ae6 100644
--- a/osu.sln
+++ b/osu.sln
@@ -63,6 +63,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
CodeAnalysis\osu.ruleset = CodeAnalysis\osu.ruleset
osu.sln.DotSettings = osu.sln.DotSettings
osu.TestProject.props = osu.TestProject.props
+ global.json = global.json
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Benchmarks", "osu.Game.Benchmarks\osu.Game.Benchmarks.csproj", "{93632F2D-2BB4-46C1-A7B8-F8CF2FB27118}"
diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings
index 154ad0fe8c..ef3b08e1f5 100644
--- a/osu.sln.DotSettings
+++ b/osu.sln.DotSettings
@@ -218,6 +218,7 @@
WARNING
WARNING
WARNING
+ WARNING
WARNING
HINT
WARNING