Skip to content

Commit e9b669a

Browse files
authored
Merge branch 'master' into autopilot-cursor-logic-improvement-10698393220144712166
2 parents 0748a14 + 861c6d3 commit e9b669a

42 files changed

Lines changed: 836 additions & 194 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
uses: actions/setup-dotnet@v4
2020
with:
2121
dotnet-version: "8.0.x"
22+
cache: 'dotnet'
2223

2324
- name: Restore Tools
2425
run: dotnet tool restore
@@ -68,6 +69,7 @@ jobs:
6869
# - { prettyname: macOS, fullname: macos-latest }
6970
- { prettyname: Linux, fullname: ubuntu-latest }
7071
threadingMode: ['SingleThread', 'MultiThreaded']
72+
suite: ['Visual', 'NonVisual', 'Rulesets']
7173
timeout-minutes: 120
7274
steps:
7375
- name: Checkout
@@ -77,32 +79,37 @@ jobs:
7779
uses: actions/setup-dotnet@v4
7880
with:
7981
dotnet-version: "8.0.x"
82+
cache: 'dotnet'
8083

8184
- name: Compile
8285
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
8386

8487
- name: Test
85-
run: >
86-
dotnet test
87-
osu.Game.Tests/bin/Debug/**/osu.Game.Tests.dll
88-
osu.Game.Rulesets.Osu.Tests/bin/Debug/**/osu.Game.Rulesets.Osu.Tests.dll
89-
osu.Game.Rulesets.Taiko.Tests/bin/Debug/**/osu.Game.Rulesets.Taiko.Tests.dll
90-
osu.Game.Rulesets.Catch.Tests/bin/Debug/**/osu.Game.Rulesets.Catch.Tests.dll
91-
osu.Game.Rulesets.Mania.Tests/bin/Debug/**/osu.Game.Rulesets.Mania.Tests.dll
92-
osu.Game.Tournament.Tests/bin/Debug/**/osu.Game.Tournament.Tests.dll
93-
Templates/**/*.Tests/bin/Debug/**/*.Tests.dll
94-
--logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
95-
--
96-
NUnit.ConsoleOut=0
88+
shell: bash
89+
run: |
90+
if [ "${{ matrix.suite }}" == "Visual" ]; then
91+
dotnet test osu.Game.Tests/bin/Debug/**/osu.Game.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.suite}}.trx" -- NUnit.ConsoleOut=0 --filter "FullyQualifiedName~osu.Game.Tests.Visual"
92+
elif [ "${{ matrix.suite }}" == "NonVisual" ]; then
93+
dotnet test osu.Game.Tests/bin/Debug/**/osu.Game.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.suite}}.trx" -- NUnit.ConsoleOut=0 --filter "FullyQualifiedName!~osu.Game.Tests.Visual"
94+
else
95+
dotnet test osu.Game.Rulesets.Osu.Tests/bin/Debug/**/osu.Game.Rulesets.Osu.Tests.dll \
96+
osu.Game.Rulesets.Taiko.Tests/bin/Debug/**/osu.Game.Rulesets.Taiko.Tests.dll \
97+
osu.Game.Rulesets.Catch.Tests/bin/Debug/**/osu.Game.Rulesets.Catch.Tests.dll \
98+
osu.Game.Rulesets.Mania.Tests/bin/Debug/**/osu.Game.Rulesets.Mania.Tests.dll \
99+
osu.Game.Tournament.Tests/bin/Debug/**/osu.Game.Tournament.Tests.dll \
100+
Templates/**/*.Tests/bin/Debug/**/*.Tests.dll \
101+
--logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.suite}}.trx" \
102+
-- NUnit.ConsoleOut=0
103+
fi
97104
98105
# Attempt to upload results even if test fails.
99106
# https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#always
100107
- name: Upload Test Results
101108
uses: actions/upload-artifact@v4
102109
if: ${{ always() }}
103110
with:
104-
name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
105-
path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx
111+
name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.suite}}
112+
path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.suite}}.trx
106113

107114
build-only-android:
108115
name: Build only (Android)
@@ -122,16 +129,18 @@ jobs:
122129
uses: actions/setup-dotnet@v4
123130
with:
124131
dotnet-version: "8.0.x"
132+
cache: 'dotnet'
125133

126134
- name: Install .NET workloads
127-
run: dotnet workload install android
135+
run: dotnet workload install android wasi-experimental
128136

129137
- name: Compile
130138
run: dotnet build -c Debug osu.Android.slnf
131139

132140
build-only-ios:
133141
name: Build only (iOS)
134142
runs-on: macos-15
143+
continue-on-error: true
135144
timeout-minutes: 60
136145
steps:
137146
- name: Checkout
@@ -141,6 +150,7 @@ jobs:
141150
uses: actions/setup-dotnet@v4
142151
with:
143152
dotnet-version: "8.0.x"
153+
cache: 'dotnet'
144154

145155
- name: Install .NET Workloads
146156
run: dotnet workload install ios

.github/workflows/release.yml

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
release:
6+
types: [published]
7+
8+
jobs:
9+
build-android:
10+
name: Build Android
11+
runs-on: windows-latest
12+
env:
13+
ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
14+
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
15+
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
16+
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Setup Java
22+
uses: actions/setup-java@v4
23+
with:
24+
distribution: 'microsoft'
25+
java-version: '11'
26+
27+
- name: Setup .NET
28+
uses: actions/setup-dotnet@v4
29+
with:
30+
dotnet-version: '8.0.x'
31+
32+
- name: Install Android Workload
33+
run: dotnet workload install android wasi-experimental
34+
35+
- name: Decode Keystore
36+
if: env.ANDROID_KEYSTORE_FILE != ''
37+
run: |
38+
$bytes = [System.Convert]::FromBase64String($env:ANDROID_KEYSTORE_FILE)
39+
[System.IO.File]::WriteAllBytes("keystore.jks", $bytes)
40+
shell: pwsh
41+
42+
- name: Build Android (Signed)
43+
if: env.ANDROID_KEYSTORE_FILE != ''
44+
run: >
45+
dotnet publish -c Release -f net8.0-android osu.Android/osu.Android.csproj
46+
-p:AndroidKeyStore=true
47+
-p:AndroidSigningKeyStore=keystore.jks
48+
-p:AndroidSigningStorePass="$env:ANDROID_KEYSTORE_PASSWORD"
49+
-p:AndroidSigningKeyAlias="$env:ANDROID_KEY_ALIAS"
50+
-p:AndroidSigningKeyPass="$env:ANDROID_KEY_PASSWORD"
51+
52+
- name: Build Android (Unsigned)
53+
if: env.ANDROID_KEYSTORE_FILE == ''
54+
run: dotnet publish -c Release -f net8.0-android osu.Android/osu.Android.csproj
55+
56+
- name: Upload Artifact
57+
uses: actions/upload-artifact@v4
58+
with:
59+
name: osu-android
60+
path: osu.Android/bin/Release/net8.0-android/*.apk
61+
62+
build-windows:
63+
name: Build Windows
64+
runs-on: windows-latest
65+
steps:
66+
- name: Checkout
67+
uses: actions/checkout@v4
68+
69+
- name: Setup .NET
70+
uses: actions/setup-dotnet@v4
71+
with:
72+
dotnet-version: '8.0.x'
73+
74+
- name: Build Windows
75+
run: dotnet publish -c Release -r win-x64 --self-contained osu.Desktop/osu.Desktop.csproj -o publish/win-x64
76+
77+
- name: Compress Windows Build
78+
run: Compress-Archive -Path publish/win-x64/* -DestinationPath osu-win-x64.zip
79+
80+
- name: Upload Artifact
81+
uses: actions/upload-artifact@v4
82+
with:
83+
name: osu-win-x64
84+
path: osu-win-x64.zip
85+
86+
build-linux:
87+
name: Build Linux
88+
runs-on: ubuntu-latest
89+
steps:
90+
- name: Checkout
91+
uses: actions/checkout@v4
92+
93+
- name: Setup .NET
94+
uses: actions/setup-dotnet@v4
95+
with:
96+
dotnet-version: '8.0.x'
97+
98+
- name: Build Linux
99+
run: dotnet publish -c Release -r linux-x64 --self-contained osu.Desktop/osu.Desktop.csproj -o publish/linux-x64
100+
101+
- name: Compress Linux Build
102+
run: zip -r osu-linux-x64.zip publish/linux-x64
103+
104+
- name: Upload Artifact
105+
uses: actions/upload-artifact@v4
106+
with:
107+
name: osu-linux-x64
108+
path: osu-linux-x64.zip
109+
110+
build-ios:
111+
name: Build iOS
112+
runs-on: macos-15
113+
continue-on-error: true
114+
steps:
115+
- name: Checkout
116+
uses: actions/checkout@v4
117+
118+
- name: Setup .NET
119+
uses: actions/setup-dotnet@v4
120+
with:
121+
dotnet-version: '8.0.x'
122+
123+
- name: Install iOS Workload
124+
run: dotnet workload install ios
125+
126+
- name: Select Xcode
127+
run: sudo xcode-select -switch /Applications/Xcode_16.4.app
128+
129+
- name: Build iOS
130+
run: dotnet publish -c Release -r ios-arm64 osu.iOS/osu.iOS.csproj /p:ArchiveOnBuild=true
131+
continue-on-error: true
132+
133+
- name: Upload Artifact
134+
uses: actions/upload-artifact@v4
135+
with:
136+
name: osu-ios
137+
path: |
138+
osu.iOS/bin/Release/net8.0-ios/ios-arm64/**/*.ipa
139+
osu.iOS/bin/Release/net8.0-ios/ios-arm64/**/*.app
140+
141+
release:
142+
name: Upload Release Assets
143+
needs: [build-android, build-windows, build-linux, build-ios]
144+
if: github.event_name == 'release'
145+
runs-on: ubuntu-latest
146+
steps:
147+
- name: Download artifacts
148+
uses: actions/download-artifact@v4
149+
with:
150+
path: artifacts
151+
152+
- name: Display structure of downloaded files
153+
run: ls -R artifacts
154+
155+
- name: Upload to Release
156+
uses: softprops/action-gh-release@v1
157+
with:
158+
files: |
159+
artifacts/osu-android/*.apk
160+
artifacts/osu-win-x64/*.zip
161+
artifacts/osu-linux-x64/*.zip
162+
artifacts/osu-ios/**/*.ipa

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,4 @@ FodyWeavers.xsd
344344

345345
.idea/.idea.osu.Desktop/.idea/misc.xml
346346
.idea/.idea.osu.Android/.idea/deploymentTargetDropDown.xml
347+
test_output.txt
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2+
// See the LICENCE file in the repository root for full licence text.
3+
4+
using System.Collections.Generic;
5+
using NUnit.Framework;
6+
using osu.Game.Beatmaps;
7+
using osu.Game.Rulesets.Catch.Beatmaps;
8+
using osu.Game.Rulesets.Catch.Objects;
9+
10+
namespace osu.Game.Rulesets.Catch.Tests
11+
{
12+
[TestFixture]
13+
public class CatchBeatmapProcessorTest
14+
{
15+
[Test]
16+
public void TestHardRockOffsetDoublePrecision()
17+
{
18+
// Setup a beatmap with two fruits that will trigger the logic difference.
19+
// We need a time difference that has a fractional part.
20+
// And we need HardRock enabled.
21+
22+
// lastPosition = 100, lastStartTime = 1000.
23+
// offsetPosition = 133.2, startTime = 1100.5.
24+
25+
// positionDiff = 33.2.
26+
// timeDiff (int) = 100.
27+
// timeDiff (double) = 100.5.
28+
29+
// positionDiff < timeDiff / 3
30+
// 33.2 < 33 (False)
31+
// 33.2 < 33.5 (True)
32+
33+
var beatmap = new Beatmap<CatchHitObject>
34+
{
35+
HitObjects = new List<CatchHitObject>
36+
{
37+
new Fruit { StartTime = 1000, X = 100 },
38+
new Fruit { StartTime = 1000 + 100.5, X = 100 + 33.2f }
39+
}
40+
};
41+
42+
var processor = new CatchBeatmapProcessor(beatmap)
43+
{
44+
HardRockOffsets = true
45+
};
46+
47+
processor.ApplyPositionOffsets(beatmap);
48+
49+
var secondObj = beatmap.HitObjects[1];
50+
51+
// If bug is present (int truncation), condition is false, XOffset is 0.
52+
// If fixed (double), condition is true, XOffset is 33.2 (approx).
53+
54+
Assert.That(secondObj.XOffset, Is.Not.EqualTo(0).Within(0.001));
55+
Assert.That(secondObj.XOffset, Is.EqualTo(33.2f).Within(0.001));
56+
}
57+
}
58+
}

osu.Game.Rulesets.Catch.Tests/Resources/Testing/Beatmaps/1431386-expected-conversion.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2+
// See the LICENCE file in the repository root for full licence text.
3+
4+
using NUnit.Framework;
5+
using osu.Framework.Graphics.Containers;
6+
using osu.Game.Rulesets.Catch.UI;
7+
using osu.Game.Tests.Visual;
8+
using osuTK;
9+
10+
namespace osu.Game.Rulesets.Catch.Tests
11+
{
12+
[TestFixture]
13+
public partial class TestSceneCatcherTrail : OsuTestScene
14+
{
15+
[Test]
16+
public void TestCatcherTrailClock()
17+
{
18+
TestCatcherTrail trail = null!;
19+
20+
AddStep("create trail", () =>
21+
{
22+
trail = new TestCatcherTrail();
23+
});
24+
25+
AddStep("apply entry at time 1000", () =>
26+
{
27+
var entry = new CatcherTrailEntry(1000, CatcherAnimationState.Idle, 0, Vector2.One, CatcherTrailAnimation.Dashing);
28+
trail.Apply(entry);
29+
});
30+
31+
AddAssert("clock is at 1000", () => trail.GetInnerClockTime() == 1000);
32+
}
33+
34+
private partial class TestCatcherTrail : CatcherTrail
35+
{
36+
public double GetInnerClockTime()
37+
{
38+
// InternalChildren[0] is the body (SkinnableCatcher)
39+
var body = (CompositeDrawable)InternalChildren[0];
40+
return body.Clock.CurrentTime;
41+
}
42+
}
43+
}
44+
}

osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ private static void applyHardRockOffset(CatchHitObject hitObject, ref float? las
132132

133133
float positionDiff = offsetPosition - lastPosition.Value;
134134

135-
// Todo: BUG!! Stable calculated time deltas as ints, which affects randomisation. This should be changed to a double.
136-
int timeDiff = (int)(startTime - lastStartTime);
135+
// Stable calculated time deltas as ints, which affects randomisation. This has been changed to a double to fix the issue.
136+
double timeDiff = startTime - lastStartTime;
137137

138138
if (timeDiff > 1000)
139139
{

0 commit comments

Comments
 (0)