Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/PatchElfPageSize.targets
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,6 @@ finally
<ItemGroup>
<_NuGetNativeLibs Include="$(NuGetPackageRoot)/**/runtimes/android-*/native/*.so" />
</ItemGroup>
<PatchElfPageSize FilePath="%(Identity)" Condition="'@(_NuGetNativeLibs)' != ''" />
<PatchElfPageSize FilePath="%(Identity)" Condition="'$(PatchElfPageSizeEnabled)' != 'false' AND '@(_NuGetNativeLibs)' != ''" />
</Target>
</Project>
29 changes: 29 additions & 0 deletions osu.Android.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,33 @@
the patch in some build orderings. This suppression is harmless since we do fix them. -->
<AndroidPageSize16KBCompatibilityCheck>false</AndroidPageSize16KBCompatibilityCheck>
</PropertyGroup>

<!-- Patch NuGet-provided .so files that ship with 4 KB ELF alignment to 16 KB.
See build/PatchElfPageSize.targets for details.
TODO: Remove once ppy.Veldrid.SPIRV ships 16 KB-aligned native libraries. -->
<Import Project="$(MSBuildThisFileDirectory)build\PatchElfPageSize.targets" />

<!-- Release-only optimisations: AOT for low-latency gameplay, trimming for smaller APK.
Suppress trim analysis warnings because the project uses reflection extensively
(Newtonsoft.Json, Realm, AutoMapper, RuntimeBinder). -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<RunAOTCompilation>true</RunAOTCompilation>
<AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
<!-- Disable ELF patching in Release to prevent signature corruption -->
<PatchElfPageSizeEnabled>false</PatchElfPageSizeEnabled>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>partial</TrimMode>
</PropertyGroup>

<ItemGroup Condition="'$(Configuration)' == 'Release'">
<!-- Force Microsoft.CSharp into the trimmer input graph (.NET 10+). -->
<!-- A bare TrimmerRootAssembly is ignored if the assembly is not in the -->
<!-- linker's input set; adding this reference ensures it is included. -->
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" NoWarn="NU1510" />
<TrimmerRootAssembly Include="Microsoft.CSharp" RootMode="all" />
</ItemGroup>

<ItemGroup>
<!-- IMPORTANT: ppy.osu.Framework.Android v2026.318.0 only ships net8.0-android34.0 assets.
NuGet silently falls back to those assets when the app targets net10.0-android (API 36).
Expand All @@ -33,9 +48,23 @@
TODO: Remove this comment once ppy.osu.Framework.Android ships net10.0-android assets. -->
<PackageReference Include="ppy.osu.Framework.Android" Version="2026.318.0" />
</ItemGroup>

<PropertyGroup>
<!-- Fody does not handle Android build well, and warns when unchanged.
Since Realm objects are not declared directly in Android projects, simply disable Fody. -->
<DisableFody>true</DisableFody>
</PropertyGroup>

<!-- Fix for .NET 10 Android AOT misclassifying non-managed assets in runtime pack.
This is critical for Android 16 (API 36) which has stricter manifest/parsing rules. -->
<Target Name="FixRuntimePackAssetTypes" AfterTargets="ResolveRuntimePackAssets;ComputeFilesToPublish;ComputeResolvedFilesToPublishList">
<ItemGroup>
<RuntimePackAsset Update="@(RuntimePackAsset)" Condition="'%(Extension)' != '.dll'">
<AssetType>native</AssetType>
</RuntimePackAsset>
<ResolvedFileToPublish Update="@(ResolvedFileToPublish)" Condition="'%(Extension)' != '.dll'">
<AssetType>native</AssetType>
</ResolvedFileToPublish>
</ItemGroup>
</Target>
</Project>
2 changes: 1 addition & 1 deletion osu.Android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="sh.ppy.osulazer" android:installLocation="auto">
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="36" />
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher" android:largeHeap="true">
<application android:extractNativeLibs="true" android:allowBackup="true" android:supportsRtl="true" android:label="osu!" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher" android:largeHeap="true">
<provider android:name="androidx.core.content.FileProvider" android:authorities="sh.ppy.osulazer.fileprovider" android:grantUriPermissions="true" android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" />
</provider>
Expand Down
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
<!-- using a different name because package name cannot contain 'catch' -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Catch_Tests.Android" android:installLocation="auto">
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="36" />
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!catch Test" />
<application android:extractNativeLibs="true" android:allowBackup="true" android:supportsRtl="true" android:label="osu!catch Test" />
</manifest>
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Mania.Tests.Android" android:installLocation="auto">
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="36" />
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!mania Test" />
<application android:extractNativeLibs="true" android:allowBackup="true" android:supportsRtl="true" android:label="osu!mania Test" />
</manifest>
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Osu.Tests.Android" android:installLocation="auto">
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="36" />
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!standard Test" />
<application android:extractNativeLibs="true" android:allowBackup="true" android:supportsRtl="true" android:label="osu!standard Test" />
</manifest>
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Taiko.Tests.Android" android:installLocation="auto">
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="36" />
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!taiko Test" />
<application android:extractNativeLibs="true" android:allowBackup="true" android:supportsRtl="true" android:label="osu!taiko Test" />
</manifest>
2 changes: 1 addition & 1 deletion osu.Game.Tests.Android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Tests.Android" android:installLocation="auto">
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="36" />
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!visual Test" />
<application android:extractNativeLibs="true" android:allowBackup="true" android:supportsRtl="true" android:label="osu!visual Test" />
</manifest>
6 changes: 4 additions & 2 deletions osu.Game/Online/Spectator/SpectatorClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,10 @@ public void BeginPlaying(long? scoreToken, GameplayState state, Score score)
Schedule(() =>
{
if (isPlaying)
throw new InvalidOperationException($"Cannot invoke {nameof(BeginPlaying)} when already playing");

{
Logger.Log($"Cannot invoke {nameof(BeginPlaying)} when already playing. Ignoring.");
return;
}
isPlaying = true;

// transfer state at point of beginning play
Expand Down
9 changes: 7 additions & 2 deletions osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,9 @@ public async Task SendUserMatchRequest(int userId, MatchUserRequest request)
break;

case StopCountdownRequest stopCountdown:
await StopCountdown(ServerRoom.ActiveCountdowns.First(c => c.ID == stopCountdown.ID)).ConfigureAwait(false);
var countdownToRemove = ServerRoom.ActiveCountdowns.FirstOrDefault(c => c.ID == stopCountdown.ID);
if (countdownToRemove != null)
await StopCountdown(countdownToRemove).ConfigureAwait(false);
break;

case RollRequest rollRequest:
Expand Down Expand Up @@ -487,7 +489,10 @@ public async Task StopCountdown(MultiplayerCountdown countdown)
Debug.Assert(ServerRoom != null);
Debug.Assert(LocalUser != null);

ServerRoom.ActiveCountdowns.Remove(ServerRoom.ActiveCountdowns.First(c => c.ID == countdown.ID));
var existing = ServerRoom.ActiveCountdowns.FirstOrDefault(c => c.ID == countdown.ID);

if (existing != null)
ServerRoom.ActiveCountdowns.Remove(existing);
await ((IMultiplayerClient)this).MatchEvent(clone(new CountdownStoppedEvent(countdown.ID))).ConfigureAwait(false);
}

Expand Down
Loading