Compare commits
369 Commits
2025.1108.
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 86f0159e65 | |||
| ae5a64ba81 | |||
| e3a7ae30cd | |||
| b6f845d99c | |||
| a1d6bda63e | |||
| 547d22a4b5 | |||
| b4c530ac04 | |||
| 5af05d2479 | |||
| 43ab18ffea | |||
| 9f59259a40 | |||
| 82b3015fcc | |||
| 68f92ab57c | |||
| d76d4d9a35 | |||
|
|
bb7417c099 | ||
|
|
066e093987 | ||
|
|
56e0c3e65d | ||
|
|
89d7726903 | ||
|
|
36f1bfef07 | ||
|
|
118f07878a | ||
|
|
e144968893 | ||
|
|
d2ffea41c6 | ||
|
|
a8be9b1381 | ||
|
|
42b184f167 | ||
|
|
27737bd4e9 | ||
|
|
8bb885a0dc | ||
|
|
0b06acb29d | ||
|
|
b129837e57 | ||
|
|
3e221c7f61 | ||
|
|
7106a6a5e5 | ||
|
|
eaf2721f5b | ||
| 490a6fd724 | |||
|
|
59a27dad3d | ||
|
|
d6cd748d2a | ||
| 237e1828f8 | |||
| 3413f722f7 | |||
| 9f779dac03 | |||
| 0727c53cdc | |||
| a57ff24191 | |||
|
|
c23d6b7fd1 | ||
|
|
582ff999aa | ||
|
|
a96b024ac5 | ||
|
|
1c10acba76 | ||
|
|
4ae4c700ae | ||
|
|
2be50d917a | ||
|
|
35fdc6f8b9 | ||
|
|
d04029bcc7 | ||
|
|
fbac5db964 | ||
|
|
5a920d15c1 | ||
|
|
324d088d46 | ||
|
|
1db4b897eb | ||
|
|
8e2230d149 | ||
|
|
8d33c35646 | ||
|
|
c359898a75 | ||
|
|
6343bf7d29 | ||
|
|
b1e27d842b | ||
|
|
28eeb7f743 | ||
|
|
38c3167a9d | ||
|
|
66ebce8c12 | ||
|
|
fed9564b40 | ||
|
|
f595a47059 | ||
|
|
8a9f60df68 | ||
|
|
2d8b1e7152 | ||
|
|
fef8117b5c | ||
|
|
99da986e02 | ||
|
|
1c33291b3f | ||
|
|
c6cc92315c | ||
|
|
12170df80a | ||
|
|
3e4c038a37 | ||
|
|
5d76353ae4 | ||
|
|
0b3ec3f1e1 | ||
|
|
043a1c2793 | ||
|
|
ca8247c667 | ||
|
|
a5ae542502 | ||
|
|
fe5cbc4932 | ||
|
|
0a378e5efd | ||
|
|
1d221c1a7a | ||
| bdb3418b67 | |||
|
|
82f4406c79 | ||
|
|
92e9a36744 | ||
|
|
c6eba26a67 | ||
|
|
8f927ea7b5 | ||
|
|
a8f058141b | ||
|
|
6bb25b2abe | ||
|
|
037743e002 | ||
|
|
6244617e5e | ||
|
|
ddfcb4d6da | ||
|
|
2660f4dcb0 | ||
|
|
5a865476ce | ||
|
|
2472c91924 | ||
|
|
db50019f31 | ||
|
|
1e43509e4a | ||
|
|
ded8aaecfd | ||
|
|
75df8e3639 | ||
|
|
0d9a50e839 | ||
|
|
7473c62949 | ||
|
|
8d30e3d852 | ||
|
|
97fdc89fe3 | ||
|
|
f6a6c9f885 | ||
|
|
26c50b874c | ||
|
|
83706b7fb6 | ||
|
|
9e3486d4e6 | ||
|
|
545b13c3fb | ||
|
|
2c9fc32756 | ||
|
|
0786e619f1 | ||
|
|
c968981697 | ||
|
|
45567f19b7 | ||
|
|
f0f4e7c7a5 | ||
|
|
1d353ef637 | ||
|
|
52af905237 | ||
|
|
64668eafb9 | ||
|
|
b0762fc8ec | ||
|
|
d59e9572d2 | ||
|
|
098da946e1 | ||
|
|
510fc506fb | ||
|
|
da09ad9c46 | ||
|
|
aaff7d358f | ||
|
|
a69b2cd803 | ||
|
|
855d5dba3c | ||
|
|
9c981a52f8 | ||
|
|
96de47ac4f | ||
|
|
43834b55f2 | ||
|
|
8fb402665e | ||
|
|
e4975e8d3b | ||
|
|
dbd9f13f2d | ||
|
|
ec890cd459 | ||
|
|
33c8c4d639 | ||
|
|
83ce56b718 | ||
|
|
9d88c761d3 | ||
|
|
49eb013967 | ||
|
|
b6ccc8cae4 | ||
|
|
d0e09e5b5c | ||
|
|
8900c79758 | ||
|
|
fd652982ce | ||
|
|
a2bfb409d2 | ||
| 936640edeb | |||
| 1187d03333 | |||
|
|
26da75ecfb | ||
|
|
9f8554cc13 | ||
|
|
713b6453c0 | ||
|
|
1b3ac49f2a | ||
|
|
d8b71423b0 | ||
|
|
2c40e116e1 | ||
|
|
90e7faf271 | ||
|
|
fc74726d11 | ||
|
|
5d3997152a | ||
|
|
41b56971e5 | ||
|
|
98e7a10e1e | ||
|
|
e99b9984d0 | ||
|
|
38504fed22 | ||
|
|
13dab24d41 | ||
|
|
67530b39cf | ||
|
|
19f5e5ba7c | ||
|
|
56ce955e0c | ||
|
|
73349ab182 | ||
|
|
a6a98fc078 | ||
|
|
a8594f1c08 | ||
|
|
d3860f1630 | ||
|
|
15ee49348d | ||
|
|
908a950cd2 | ||
|
|
df79269e6f | ||
|
|
34146b8bcb | ||
|
|
08ed2844b4 | ||
|
|
871c0ebe3d | ||
|
|
6362cdb675 | ||
|
|
8e78f4dac4 | ||
|
|
fa8d303922 | ||
|
|
d465bee0ab | ||
|
|
721ba8aeba | ||
|
|
1dd026c0f0 | ||
|
|
a873f2be65 | ||
|
|
edf7a126c8 | ||
|
|
f0f33b6df4 | ||
|
|
6052ed790d | ||
|
|
107c481fb9 | ||
|
|
aba567d258 | ||
|
|
094454499c | ||
|
|
c7e1a5770d | ||
|
|
a8ac82aa1f | ||
|
|
47faf774b0 | ||
|
|
be77257ddb | ||
|
|
397041099e | ||
|
|
4b59a4657f | ||
|
|
02090bf6c4 | ||
| 3bd996ee43 | |||
| 37b9f91d42 | |||
|
|
603c77e3e9 | ||
|
|
f284864f96 | ||
| 1a5a5606dc | |||
|
|
fa1bf7bd96 | ||
|
|
ef4408a73e | ||
|
|
6f7f9802bd | ||
| 87ff1051e9 | |||
|
|
277f4268db | ||
|
|
80474565fc | ||
| 2e4b0ff197 | |||
| 499f410c94 | |||
| 616c0d8ecd | |||
| ed889138a0 | |||
|
|
89f2c7160d | ||
|
|
f0ca079fe6 | ||
|
|
fbd83cb048 | ||
|
|
843c318ec1 | ||
|
|
19b6761697 | ||
|
|
0c341c1f3e | ||
|
|
ae5584bd88 | ||
|
|
edf08b176a | ||
| 18075bef29 | |||
| bc7780a870 | |||
| 8930b8fadb | |||
| 2d457f4305 | |||
| a784734f94 | |||
|
|
7b952b83bf | ||
|
|
214122f633 | ||
|
|
76c0bd4750 | ||
|
|
4bf3d9397f | ||
|
|
fe56ba2921 | ||
|
|
1ca4c8860b | ||
|
|
1e05613859 | ||
|
|
424ef9237f | ||
|
|
e541e917a4 | ||
|
|
7796394685 | ||
|
|
32900f563c | ||
|
|
e349a597ba | ||
|
|
8b778e8106 | ||
|
|
ce5e54c9d2 | ||
| ecfd4764e7 | |||
| f5ca5083d6 | |||
| 1d7c77d8d6 | |||
| 774e52fbd6 | |||
|
|
45e8df7af2 | ||
|
|
1c30cb8371 | ||
| a9d7a9d5d5 | |||
| f7069b1009 | |||
| c3ce5dc787 | |||
| 98076e2092 | |||
| b7d1092f90 | |||
| 08db90c278 | |||
|
|
bd4ed49c06 | ||
| b7e36164c3 | |||
|
|
1e91dde92e | ||
|
|
a593a40429 | ||
|
|
02b88de76e | ||
|
|
435cd272ea | ||
| 0f5f13858d | |||
|
|
b64abbf1f5 | ||
|
|
4265e72180 | ||
| 89a0c75156 | |||
|
|
72507b80c7 | ||
| ab7e5c94f1 | |||
| 8dc9ea4553 | |||
| dcf553c252 | |||
|
|
cb9d9734d6 | ||
|
|
5763b7dbe9 | ||
|
|
e1baa03622 | ||
|
|
4f783f8c41 | ||
|
|
4c72a60ee2 | ||
| 43f3a506ea | |||
| ab51579c27 | |||
| d8e977c05f | |||
|
|
c56c528824 | ||
|
|
013de9f85d | ||
|
|
cd6c9405fe | ||
|
|
1df640898f | ||
|
|
7b55b9e4f2 | ||
|
|
822cb9e2fb | ||
|
|
680614fbee | ||
|
|
cb8ddc706f | ||
|
|
04d2ce150a | ||
|
|
eaffb89b4c | ||
|
|
650a61539b | ||
|
|
75bc934aa5 | ||
|
|
8d80e2bd2c | ||
|
|
34a3b1ba78 | ||
|
|
b354fa4472 | ||
|
|
1fbe1bd6c9 | ||
|
|
3c215f6574 | ||
|
|
8c28d26130 | ||
|
|
933fbd274d | ||
|
|
55ae7e8bb8 | ||
|
|
4a22ef88ce | ||
|
|
43ca046f9b | ||
|
|
dbefba57ce | ||
|
|
20904de276 | ||
|
|
6a6c7ad3ba | ||
|
|
fb2fe65a77 | ||
|
|
4662c5d678 | ||
|
|
243cd9c073 | ||
|
|
e8db35a5c9 | ||
|
|
d98cb9ca45 | ||
|
|
a7e4aa8b12 | ||
|
|
0f54608cee | ||
|
|
f8331e0b28 | ||
|
|
6ff2a6225d | ||
|
|
a8020dea7c | ||
|
|
88dd458394 | ||
|
|
23cb7f3b23 | ||
|
|
7da051b144 | ||
|
|
78f639d760 | ||
|
|
4ea03d0e07 | ||
|
|
4d706b12ac | ||
|
|
c44f701abe | ||
|
|
4c81d661aa | ||
|
|
f4049c7ec1 | ||
|
|
645d27bb32 | ||
|
|
73f1849365 | ||
|
|
89b443bccc | ||
|
|
be9170832c | ||
|
|
9db200ed41 | ||
|
|
1ab017d4e2 | ||
|
|
2413e98108 | ||
|
|
65fb5311ea | ||
|
|
14cdc40f0f | ||
|
|
9a393f912b | ||
|
|
a9ca4634fc | ||
|
|
bdcc0ee937 | ||
|
|
6f94b1ab6d | ||
|
|
b20a41c1e8 | ||
|
|
d0ce74063d | ||
|
|
373162df02 | ||
|
|
8e0c9281d3 | ||
|
|
25a1a1ba37 | ||
|
|
73e05e3fae | ||
|
|
2a01e3d148 | ||
|
|
cf0e5edf34 | ||
|
|
a825104688 | ||
|
|
ea1798d731 | ||
|
|
a435dfe93e | ||
|
|
5c1171f358 | ||
|
|
3fcc626e29 | ||
|
|
7ff6edeb64 | ||
|
|
657bc31539 | ||
|
|
f9f7740acb | ||
|
|
5e4dd77e64 | ||
|
|
ce96c0b037 | ||
|
|
5af9bb784b | ||
|
|
4c60df21db | ||
|
|
3c6fb14a32 | ||
|
|
3afc7b045c | ||
|
|
2f2847f1dd | ||
|
|
ee7c52465b | ||
|
|
beb977892e | ||
|
|
7203f419a2 | ||
|
|
722cfb72d8 | ||
|
|
5da132cc2f | ||
|
|
9fac96cf07 | ||
|
|
fadcb9882c | ||
|
|
0610781c6c | ||
|
|
e9260de56f | ||
|
|
2d177226fd | ||
|
|
bd912710f1 | ||
|
|
4e76bd0f24 | ||
|
|
9a965a2546 | ||
|
|
7b0121a430 | ||
|
|
627fec2e3a | ||
|
|
c779e142e6 | ||
|
|
89fffa5a1a | ||
|
|
6d597fc815 | ||
|
|
a78b456e20 | ||
|
|
9237c76942 | ||
|
|
378c64b7f8 | ||
|
|
87b66685d6 | ||
|
|
c524bf5432 | ||
|
|
a40230da4b | ||
|
|
afdebcf188 | ||
|
|
0558f9f2d9 | ||
|
|
1ec6735a35 | ||
|
|
245ade004a | ||
|
|
6cb46106fe | ||
|
|
3666e4c332 |
12
.github/ISSUE_TEMPLATE/config.yml
vendored
12
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,12 +1,6 @@
|
||||
blank_issues_enabled: false
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Help
|
||||
url: https://github.com/ppy/osu/discussions/categories/q-a
|
||||
about: osu! not working or performing as you'd expect? Not sure it's a bug? Check the Q&A section!
|
||||
- name: Suggestions or feature request
|
||||
url: https://github.com/ppy/osu/discussions/categories/ideas
|
||||
about: Got something you think should change or be added? Search for or start a new discussion!
|
||||
- name: osu!stable issues
|
||||
url: https://github.com/ppy/osu-stable-issues
|
||||
about: For osu!(stable) - ie. the current "live" game version, check out the dedicated repository. Note that this is for serious bug reports only, not tech support.
|
||||
url: https://t.me/jvnkosu_chat
|
||||
about: Your jvnkosu! is not working right? Please contact us using our Telegram chat
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
name: Update osu-web mod definitions
|
||||
name: Update osu-web mod definitions (DO NOT USE YET!!!!!)
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
workflow_dispatch:
|
||||
# push:
|
||||
# tags:
|
||||
# - '*'
|
||||
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@@ -1,4 +1,10 @@
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
name: Continuous Integration
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -33,7 +39,7 @@ jobs:
|
||||
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', 'osu*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }}
|
||||
|
||||
- name: Dotnet code style
|
||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf -p:EnforceCodeStyleInBuild=true
|
||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
||||
|
||||
- name: CodeFileSanity
|
||||
run: |
|
||||
|
||||
3
.github/workflows/deploy.yml
vendored
3
.github/workflows/deploy.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
notify_pending_production_deploy:
|
||||
@@ -12,7 +13,7 @@ jobs:
|
||||
- name: Submit pending deployment notification
|
||||
run: |
|
||||
export TITLE="Pending osu Production Deployment: $GITHUB_REF_NAME"
|
||||
export URL="https://github.com/ppy/osu/actions/runs/$GITHUB_RUN_ID"
|
||||
export URL="https://github.com/jvnkosu-dev/client/actions/runs/$GITHUB_RUN_ID"
|
||||
export DESCRIPTION="Awaiting approval for building NuGet packages for tag $GITHUB_REF_NAME:
|
||||
[View Workflow Run]($URL)"
|
||||
export ACTOR_ICON="https://avatars.githubusercontent.com/u/$GITHUB_ACTOR_ID"
|
||||
|
||||
8
.github/workflows/sentry-release.yml
vendored
8
.github/workflows/sentry-release.yml
vendored
@@ -21,9 +21,9 @@ jobs:
|
||||
uses: getsentry/action-release@v1
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ppy
|
||||
SENTRY_PROJECT: osu
|
||||
SENTRY_URL: https://sentry.ppy.sh/
|
||||
SENTRY_ORG: jvnkosu
|
||||
SENTRY_PROJECT: client
|
||||
SENTRY_URL: https://satellite.jvnko.boats/
|
||||
with:
|
||||
environment: production
|
||||
version: osu@${{ github.ref_name }}
|
||||
version: jvnkosu@${{ github.ref_name }}
|
||||
|
||||
@@ -73,6 +73,9 @@ Aside from the above, below is a brief checklist of things to watch out when you
|
||||
After you're done with your changes and you wish to open the PR, please observe the following recommendations:
|
||||
|
||||
- Please submit the pull request from a [topic branch](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#_topic_branch) (not `master`), and keep the *Allow edits from maintainers* check box selected, so that we can push fixes to your PR if necessary.
|
||||
- Please pick the following target branch for your pull request:
|
||||
- `pp-dev`, if the change impacts star rating or performance points calculations for any of the rulesets,
|
||||
- `master`, otherwise.
|
||||
- Please avoid pushing untested or incomplete code.
|
||||
- Please do not force-push or rebase unless we ask you to.
|
||||
- Please do not merge `master` continually if there are no conflicts to resolve. We will do this for you when the change is ready for merge.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<PackageType>Template</PackageType>
|
||||
<PackageId>ppy.osu.Game.Templates</PackageId>
|
||||
<PackageId>jvnkosu.Client.Templates</PackageId>
|
||||
<Title>osu! templates</Title>
|
||||
<Authors>ppy Pty Ltd</Authors>
|
||||
<PackageLicenseUrl>https://github.com/ppy/osu/blob/master/LICENCE</PackageLicenseUrl>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1028.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1209.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="sh.ppy.osulazer" android:installLocation="auto">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="boats.jvnko.osu.android" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||
<application android:allowBackup="true"
|
||||
android:supportsRtl="true"
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace osu.Desktop
|
||||
{
|
||||
internal partial class DiscordRichPresence : Component
|
||||
{
|
||||
private const string client_id = "1216669957799018608";
|
||||
private const string client_id = "1440647613358800918";
|
||||
|
||||
private DiscordRpcClient client = null!;
|
||||
|
||||
|
||||
@@ -115,12 +115,10 @@ namespace osu.Desktop
|
||||
if (IsFirstRun)
|
||||
LocalConfig.SetValue(OsuSetting.ReleaseStream, ReleaseStream.Lazer);
|
||||
|
||||
// if (IsPackageManaged)
|
||||
// return new NoActionUpdateManager();
|
||||
if (IsPackageManaged)
|
||||
return new NoActionUpdateManager();
|
||||
|
||||
// return new VelopackUpdateManager();
|
||||
|
||||
return new NoActionUpdateManager(); // for now, APIs are useless for actually downloading the releases. TODO: adapt UpdateManager for gitea
|
||||
return new VelopackUpdateManager(); // yay
|
||||
}
|
||||
|
||||
public override bool RestartAppWhenExited()
|
||||
@@ -150,7 +148,13 @@ namespace osu.Desktop
|
||||
|
||||
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
||||
if (iconStream != null)
|
||||
host.Window.SetIconFromStream(iconStream);
|
||||
try
|
||||
{
|
||||
host.Window.SetIconFromStream(iconStream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
host.Window.Title = Name;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace osu.Desktop
|
||||
|
||||
// While .NET 8 only supports Windows 10 and above, running on Windows 7/8.1 may still work. We are limited by realm currently, as they choose to only support 8.1 and higher.
|
||||
// See https://www.mongodb.com/docs/realm/sdk/dotnet/compatibility/
|
||||
if (windowsVersion.Major < 6 || (windowsVersion.Major == 6 && windowsVersion.Minor <= 2))
|
||||
if (windowsVersion.Major < 6)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
@@ -53,13 +53,26 @@ namespace osu.Desktop
|
||||
// We could also better detect compatibility mode if required:
|
||||
// https://stackoverflow.com/questions/10744651/how-i-can-detect-if-my-application-is-running-under-compatibility-mode#comment58183249_10744730
|
||||
SDL3.SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR,
|
||||
"Your operating system is too old to run osu!"u8,
|
||||
"This version of osu! requires at least Windows 8.1 to run.\n"u8
|
||||
+ "Please upgrade your operating system or consider using an older version of osu!.\n\n"u8
|
||||
+ "If you are running a newer version of windows, please check you don't have \"Compatibility mode\" turned on for osu!"u8, null);
|
||||
"Your operating system is too old to run this game!"u8,
|
||||
"This version of the game requires at least Windows 8.1 to run reliably.\n"u8
|
||||
+ "You may try to run it on Windows 8 or older, but it's not guaranteed to actually work.\n\n"u8
|
||||
+ "Please upgrade your operating system or consider using an older game version.\n\n"u8
|
||||
+ "If you are running a newer version of Windows, please check you don't have \"Compatibility mode\" turned on for the game's executable."u8, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (windowsVersion.Major == 6 && windowsVersion.Minor <= 2)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
SDL3.SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_WARNING,
|
||||
"Your operating system is too old to run this game!"u8,
|
||||
"While the version of Windows you're using may be able to launch it, it's likely to work unreliably and crash.\n"u8
|
||||
+ "Please upgrade your operating system or consider using an older game version.\n\n"u8
|
||||
+ "If you are running a newer version of Windows, please check you don't have \"Compatibility mode\" turned on for the game's executable."u8, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NVIDIA profiles are based on the executable name of a process.
|
||||
@@ -208,9 +221,10 @@ namespace osu.Desktop
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void configureWindows(VelopackApp app)
|
||||
{
|
||||
app.OnFirstRun(_ => WindowsAssociationManager.InstallAssociations());
|
||||
app.OnAfterUpdateFastCallback(_ => WindowsAssociationManager.UpdateAssociations());
|
||||
app.OnBeforeUninstallFastCallback(_ => WindowsAssociationManager.UninstallAssociations());
|
||||
// we do not want associations here, as that breaks official lazer's associations
|
||||
// app.OnFirstRun(_ => WindowsAssociationManager.InstallAssociations());
|
||||
// app.OnAfterUpdateFastCallback(_ => WindowsAssociationManager.UpdateAssociations());
|
||||
// app.OnBeforeUninstallFastCallback(_ => WindowsAssociationManager.UninstallAssociations());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace osu.Desktop.Updater
|
||||
|
||||
try
|
||||
{
|
||||
IUpdateSource updateSource = new GithubSource(@"https://github.com/ppy/osu", null, ReleaseStream.Value == Game.Configuration.ReleaseStream.Tachyon);
|
||||
IUpdateSource updateSource = new GiteaSource(@"https://gitea.jvnko.boats/jvnkosu/client", null, ReleaseStream.Value == Game.Configuration.ReleaseStream.Tachyon);
|
||||
Velopack.UpdateManager updateManager = new Velopack.UpdateManager(updateSource, new UpdateOptions
|
||||
{
|
||||
AllowVersionDowngrade = true
|
||||
|
||||
@@ -53,8 +53,8 @@ namespace osu.Desktop.Windows
|
||||
|
||||
private static readonly UriAssociation[] uri_associations =
|
||||
{
|
||||
new UriAssociation(@"osu", WindowsAssociationManagerStrings.OsuProtocol, Icons.Lazer),
|
||||
new UriAssociation(@"osump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer),
|
||||
new UriAssociation(@"jvnkosu", WindowsAssociationManagerStrings.OsuProtocol, Icons.Lazer),
|
||||
new UriAssociation(@"jvnkosump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 401 KiB |
@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
|
||||
private double placementStartTime;
|
||||
private double placementEndTime;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public BananaShowerPlacementBlueprint()
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
|
||||
|
||||
private InputManager inputManager = null!;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public JuiceStreamPlacementBlueprint()
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -224,7 +225,8 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
#region Clipboard handling
|
||||
|
||||
public override string ConvertSelectionToString()
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<CatchHitObject>().OrderBy(h => h.StartTime).Select(h => (h.IndexInCurrentCombo + 1).ToString()));
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<CatchHitObject>().OrderBy(h => h.StartTime)
|
||||
.Select(h => (h.IndexInCurrentCombo + 1).ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
// 1,2,3,4 ...
|
||||
private static readonly Regex selection_regex = new Regex(@"^\d+(,\d+)*$", RegexOptions.Compiled);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<PropertyGroup Label="Nuget">
|
||||
<Title>osu!catch (ruleset)</Title>
|
||||
<PackageId>ppy.osu.Game.Rulesets.Catch</PackageId>
|
||||
<PackageId>jvnkosu.Client.Rulesets.Catch</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
@@ -16,6 +17,7 @@ using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Input;
|
||||
|
||||
@@ -36,21 +38,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
[Test]
|
||||
public void TestPlaceBeforeCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("seek to 200", () => HitObjectContainer.Dependencies.Get<EditorClock>().Seek(200));
|
||||
AddStep("move mouse before current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(-100));
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time < 0", () => getNote().StartTime < 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPlaceAfterCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("move mouse after current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(100));
|
||||
@@ -58,7 +47,22 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time > 0", () => getNote().StartTime > 0);
|
||||
AddAssert("note start time < 200", () => getNote().StartTime < 200);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPlaceAfterCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("seek to 200", () => HitObjectContainer.Dependencies.Get<EditorClock>().Seek(200));
|
||||
AddStep("move mouse after current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(300));
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time > 200", () => getNote().StartTime > 200);
|
||||
}
|
||||
|
||||
private Note getNote() => this.ChildrenOfType<DrawableNote>().FirstOrDefault()?.HitObject;
|
||||
|
||||
@@ -18,15 +18,11 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
public void TestNormalSelection()
|
||||
{
|
||||
addStepClickLink("00:05:920 (5920|3,6623|3,6857|2,7326|1)");
|
||||
AddAssert("selected group", () => checkSnapAndSelectColumn(5_920, new List<(int, int)>
|
||||
{ (5_920, 3), (6_623, 3), (6_857, 2), (7_326, 1) }
|
||||
));
|
||||
AddAssert("selected group", () => checkSnapAndSelectColumn(5_920, [(5_920, 3), (6_623, 3), (6_857, 2), (7_326, 1)]));
|
||||
|
||||
addReset();
|
||||
addStepClickLink("00:42:716 (42716|3,43420|2,44123|0,44357|1,45295|1)");
|
||||
AddAssert("selected ungrouped", () => checkSnapAndSelectColumn(42_716, new List<(int, int)>
|
||||
{ (42_716, 3), (43_420, 2), (44_123, 0), (44_357, 1), (45_295, 1) }
|
||||
));
|
||||
AddAssert("selected ungrouped", () => checkSnapAndSelectColumn(42_716, [(42_716, 3), (43_420, 2), (44_123, 0), (44_357, 1), (45_295, 1)]));
|
||||
|
||||
addReset();
|
||||
AddStep("add notes to row", () =>
|
||||
@@ -41,15 +37,20 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
EditorBeatmap.AddRange(new[] { second, third, forth });
|
||||
});
|
||||
addStepClickLink("00:11:545 (11545|0,11545|1,11545|2,11545|3)");
|
||||
AddAssert("selected in row", () => checkSnapAndSelectColumn(11_545, new List<(int, int)>
|
||||
{ (11_545, 0), (11_545, 1), (11_545, 2), (11_545, 3) }
|
||||
));
|
||||
AddAssert("selected in row", () => checkSnapAndSelectColumn(11_545, [(11_545, 0), (11_545, 1), (11_545, 2), (11_545, 3)]));
|
||||
|
||||
addReset();
|
||||
addStepClickLink("01:36:623 (96623|1,97560|1,97677|1,97795|1,98966|1)");
|
||||
AddAssert("selected in column", () => checkSnapAndSelectColumn(96_623, new List<(int, int)>
|
||||
{ (96_623, 1), (97_560, 1), (97_677, 1), (97_795, 1), (98_966, 1) }
|
||||
));
|
||||
AddAssert("selected in column", () => checkSnapAndSelectColumn(96_623, [(96_623, 1), (97_560, 1), (97_677, 1), (97_795, 1), (98_966, 1)]));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRoundingToNearestMillisecondApplied()
|
||||
{
|
||||
AddStep("resnap note to have fractional coordinates",
|
||||
() => EditorBeatmap.HitObjects.OfType<ManiaHitObject>().Single(ho => ho.StartTime == 85_373 && ho.Column == 1).StartTime = 85_373.125);
|
||||
addStepClickLink("01:25:373 (85373|1)");
|
||||
AddAssert("selected note", () => checkSnapAndSelectColumn(85_373.125, [(85_373.125, 1)]));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -75,7 +76,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
|
||||
private void addReset() => addStepClickLink("00:00:000", "reset", false);
|
||||
|
||||
private bool checkSnapAndSelectColumn(double startTime, IReadOnlyCollection<(int, int)>? columnPairs = null)
|
||||
private bool checkSnapAndSelectColumn(double startTime, IReadOnlyCollection<(double, int)>? columnPairs = null)
|
||||
{
|
||||
bool checkColumns = columnPairs != null
|
||||
? EditorBeatmap.SelectedHitObjects.All(x => columnPairs.Any(col => isNoteAt(x, col.Item1, col.Item2)))
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
[TestCase("mania-samples")]
|
||||
[TestCase("mania-slider")] // e.g. second and fourth notes of https://osu.ppy.sh/beatmapsets/73883#mania/216407
|
||||
[TestCase("slider-convert-samples")]
|
||||
[TestCase("spinner-convert-samples")]
|
||||
public void Test(string name) => base.Test(name);
|
||||
|
||||
protected override IEnumerable<SampleConvertValue> CreateConvertValue(HitObject hitObject)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
osu file format v14
|
||||
|
||||
[General]
|
||||
Mode: 0
|
||||
|
||||
[TimingPoints]
|
||||
0,300,4,0,2,100,1,0
|
||||
|
||||
[HitObjects]
|
||||
444,320,1000,5,2,0:0:0:0:
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"Mappings": [{
|
||||
"StartTime": 1000.0,
|
||||
"Objects": [{
|
||||
"StartTime": 1000.0,
|
||||
"EndTime": 8000.0,
|
||||
"Column": 0,
|
||||
"PlaySlidingSamples": false,
|
||||
"NodeSamples": [
|
||||
["Gameplay/soft-hitnormal"],
|
||||
["Gameplay/soft-hitnormal", "Gameplay/soft-hitfinish"]
|
||||
],
|
||||
"Samples": ["Gameplay/soft-hitnormal", "Gameplay/soft-hitfinish"],
|
||||
}]
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
osu file format v14
|
||||
|
||||
[General]
|
||||
Mode: 0
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:5
|
||||
CircleSize:5
|
||||
OverallDifficulty:5
|
||||
ApproachRate:5
|
||||
SliderMultiplier:1.4
|
||||
SliderTickRate:1
|
||||
|
||||
[TimingPoints]
|
||||
0,500,4,2,0,100,1,0
|
||||
|
||||
[HitObjects]
|
||||
256,192,1000,8,4,8000,0:2:0:0:
|
||||
@@ -45,5 +45,19 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
AssertBeatmapLookup(expected_sample);
|
||||
AssertNoLookup(unwanted_sample);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConvertHitObjectCustomSampleBank()
|
||||
{
|
||||
const string beatmap_sample = "normal-hitwhistle2";
|
||||
const string user_skin_sample = "normal-hitnormal";
|
||||
|
||||
SetupSkins(beatmap_sample, user_skin_sample);
|
||||
|
||||
CreateTestWithBeatmap("convert-beatmap-custom-sample-bank.osu");
|
||||
|
||||
AssertBeatmapLookup(beatmap_sample);
|
||||
AssertUserLookup(user_skin_sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
Duration = endTime - HitObject.StartTime,
|
||||
Column = column,
|
||||
Samples = HitObject.Samples,
|
||||
NodeSamples = (HitObject as IHasRepeats)?.NodeSamples
|
||||
NodeSamples =
|
||||
[
|
||||
HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_NORMAL).ToList(),
|
||||
HitObject.Samples
|
||||
]
|
||||
};
|
||||
}
|
||||
else
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
[Resolved]
|
||||
private IScrollingInfo scrollingInfo { get; set; } = null!;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public HoldNotePlacementBlueprint()
|
||||
: base(new HoldNote())
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
@@ -54,7 +56,8 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
};
|
||||
|
||||
public override string ConvertSelectionToString()
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime).Select(h => $"{h.StartTime}|{h.Column}"));
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime)
|
||||
.Select(h => FormattableString.Invariant($"{Math.Round(h.StartTime)}|{h.Column}")));
|
||||
|
||||
// 123|0,456|1,789|2 ...
|
||||
private static readonly Regex selection_regex = new Regex(@"^\d+\|\d+(,\d+\|\d+)*$", RegexOptions.Compiled);
|
||||
@@ -73,10 +76,10 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
if (split.Length != 2)
|
||||
continue;
|
||||
|
||||
if (!double.TryParse(split[0], out double time) || !int.TryParse(split[1], out int column))
|
||||
if (!int.TryParse(split[0], out int time) || !int.TryParse(split[1], out int column))
|
||||
continue;
|
||||
|
||||
ManiaHitObject? current = remainingHitObjects.FirstOrDefault(h => h.StartTime == time && h.Column == column);
|
||||
ManiaHitObject? current = remainingHitObjects.FirstOrDefault(h => Precision.AlmostEquals(h.StartTime, time, 0.5) && h.Column == column);
|
||||
|
||||
if (current == null)
|
||||
continue;
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Acronym => Name;
|
||||
public abstract int KeyCount { get; }
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
public override bool Ranked => UsesDefaultConfiguration;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
typeof(ManiaModFadeIn)
|
||||
}).ToArray();
|
||||
|
||||
public override bool Ranked => false;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public override bool ValidForFreestyleAsRequiredMod => false;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public class ManiaModHardRock : ModHardRock, IApplicableToHitObject
|
||||
{
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => false;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public const double HIT_WINDOW_DIFFICULTY_MULTIPLIER = 1.4;
|
||||
|
||||
|
||||
@@ -14,6 +14,5 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Acronym => "1K";
|
||||
public override IconUsage? Icon => OsuIcon.ModOneKey;
|
||||
public override LocalisableString Description => @"Play with one key.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,5 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Acronym => "10K";
|
||||
public override IconUsage? Icon => OsuIcon.ModTenKeys;
|
||||
public override LocalisableString Description => @"Play with ten keys.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,5 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Acronym => "2K";
|
||||
public override IconUsage? Icon => OsuIcon.ModTwoKeys;
|
||||
public override LocalisableString Description => @"Play with two keys.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,5 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Acronym => "3K";
|
||||
public override IconUsage? Icon => OsuIcon.ModThreeKeys;
|
||||
public override LocalisableString Description => @"Play with three keys.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public class ManiaModMirror : ModMirror, IApplicableToBeatmap
|
||||
{
|
||||
public override LocalisableString Description => "Notes are flipped horizontally.";
|
||||
public override bool Ranked => UsesDefaultConfiguration;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
|
||||
@@ -64,11 +64,13 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
private readonly Lazy<bool> hasKeyTexture;
|
||||
|
||||
private readonly ManiaBeatmap beatmap;
|
||||
private readonly bool isBeatmapConverted;
|
||||
|
||||
public ManiaLegacySkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||
: base(skin)
|
||||
{
|
||||
this.beatmap = (ManiaBeatmap)beatmap;
|
||||
isBeatmapConverted = !beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo);
|
||||
|
||||
isLegacySkin = new Lazy<bool>(() => GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version) != null);
|
||||
hasKeyTexture = new Lazy<bool>(() =>
|
||||
@@ -196,8 +198,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
|
||||
public override ISample GetSample(ISampleInfo sampleInfo)
|
||||
{
|
||||
// layered hit sounds never play in mania
|
||||
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered)
|
||||
// layered hit sounds never play in mania-native beatmaps (but do play on converts)
|
||||
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered && !isBeatmapConverted)
|
||||
return new SampleVirtual();
|
||||
|
||||
return base.GetSample(sampleInfo);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<PropertyGroup Label="Nuget">
|
||||
<Title>osu!mania (ruleset)</Title>
|
||||
<PackageId>ppy.osu.Game.Rulesets.Mania</PackageId>
|
||||
<PackageId>jvnkosu.Client.Rulesets.Mania</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -245,13 +245,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
AddAssert("grid spacing is distance to slider tail", () =>
|
||||
{
|
||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.01)
|
||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.1)
|
||||
&& Precision.AlmostEquals(composer.Spacing.Value.X, composer.Spacing.Value.Y);
|
||||
});
|
||||
AddAssert("grid rotation points to slider tail", () =>
|
||||
{
|
||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||
return Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.01);
|
||||
return Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.1);
|
||||
});
|
||||
|
||||
AddStep("start grid placement", () => InputManager.Key(Key.Number5));
|
||||
@@ -280,9 +280,9 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
AddAssert("grid spacing and rotation unchanged", () =>
|
||||
{
|
||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.01)
|
||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.1)
|
||||
&& Precision.AlmostEquals(composer.Spacing.Value.X, composer.Spacing.Value.Y)
|
||||
&& Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.01);
|
||||
&& Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@@ -22,7 +23,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
[TestFixture]
|
||||
public partial class TestSceneSliderDrawing : TestSceneOsuEditor
|
||||
{
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new TestBeatmap(ruleset, false);
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTouchInputPlaceHitCircleDirectly()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Events;
|
||||
@@ -10,6 +11,7 @@ using osu.Framework.Input.States;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Testing.Input;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
@@ -58,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
foreach (var smokeContainer in smokeContainers)
|
||||
{
|
||||
if (smokeContainer.Children.Count != 0)
|
||||
if (smokeContainer.Children.OfType<SkinnableDrawable>().Any())
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
{
|
||||
this.gridToolboxGroup = gridToolboxGroup;
|
||||
originalOrigin = gridToolboxGroup.StartPosition.Value;
|
||||
originalSpacing = gridToolboxGroup.Spacing.Value;
|
||||
originalSpacing = gridToolboxGroup.GridLineSpacing.Value;
|
||||
originalRotation = gridToolboxGroup.GridLinesRotation.Value;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
{
|
||||
// Reset the grid to the default values.
|
||||
gridToolboxGroup.StartPosition.Value = gridToolboxGroup.StartPosition.Default;
|
||||
gridToolboxGroup.Spacing.Value = gridToolboxGroup.Spacing.Default;
|
||||
gridToolboxGroup.GridLineSpacing.Value = gridToolboxGroup.GridLineSpacing.Default;
|
||||
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||
gridToolboxGroup.GridLinesRotation.Value = gridToolboxGroup.GridLinesRotation.Default;
|
||||
EndPlacement(true);
|
||||
@@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
// Default to the original spacing and rotation if the distance is too small.
|
||||
if (Vector2.Distance(gridToolboxGroup.StartPosition.Value, pos) < 2)
|
||||
{
|
||||
gridToolboxGroup.Spacing.Value = originalSpacing;
|
||||
gridToolboxGroup.GridLineSpacing.Value = originalSpacing;
|
||||
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||
gridToolboxGroup.GridLinesRotation.Value = originalRotation;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
private void resetGridState()
|
||||
{
|
||||
gridToolboxGroup.StartPosition.Value = originalOrigin;
|
||||
gridToolboxGroup.Spacing.Value = originalSpacing;
|
||||
gridToolboxGroup.GridLineSpacing.Value = originalSpacing;
|
||||
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||
gridToolboxGroup.GridLinesRotation.Value = originalRotation;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
|
||||
private readonly IncrementalBSplineBuilder bSplineBuilder = new IncrementalBSplineBuilder { Degree = 4 };
|
||||
|
||||
protected override bool IsValidForPlacement => HitObject.Path.HasValidLengthForPlacement;
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || HitObject.Path.HasValidLengthForPlacement);
|
||||
|
||||
public SliderPlacementBlueprint()
|
||||
: base(new Slider())
|
||||
|
||||
@@ -5,8 +5,10 @@ using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
@@ -42,25 +44,31 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
private readonly BindableInt displayTolerance = new BindableInt(90)
|
||||
{
|
||||
MinValue = 5,
|
||||
MaxValue = 100
|
||||
MaxValue = 100,
|
||||
Precision = 1,
|
||||
};
|
||||
|
||||
private readonly BindableInt displayCornerThreshold = new BindableInt(40)
|
||||
{
|
||||
MinValue = 5,
|
||||
MaxValue = 100
|
||||
MaxValue = 100,
|
||||
Precision = 1,
|
||||
};
|
||||
|
||||
private readonly BindableInt displayCircleThreshold = new BindableInt(30)
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 100
|
||||
MaxValue = 100,
|
||||
Precision = 1,
|
||||
};
|
||||
|
||||
private ExpandableSlider<int> toleranceSlider = null!;
|
||||
private ExpandableSlider<int> cornerThresholdSlider = null!;
|
||||
private ExpandableSlider<int> circleThresholdSlider = null!;
|
||||
|
||||
[Resolved]
|
||||
private IExpandingContainer? expandingContainer { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@@ -68,15 +76,18 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
toleranceSlider = new ExpandableSlider<int>
|
||||
{
|
||||
Current = displayTolerance
|
||||
Current = displayTolerance,
|
||||
ExpandedLabelText = "Control point spacing",
|
||||
},
|
||||
cornerThresholdSlider = new ExpandableSlider<int>
|
||||
{
|
||||
Current = displayCornerThreshold
|
||||
Current = displayCornerThreshold,
|
||||
ExpandedLabelText = "Corner bias",
|
||||
},
|
||||
circleThresholdSlider = new ExpandableSlider<int>
|
||||
{
|
||||
Current = displayCircleThreshold
|
||||
Current = displayCircleThreshold,
|
||||
ExpandedLabelText = "Perfect curve bias"
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -88,24 +99,18 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
displayTolerance.BindValueChanged(tolerance =>
|
||||
{
|
||||
toleranceSlider.ContractedLabelText = $"C. P. S.: {tolerance.NewValue:N0}";
|
||||
toleranceSlider.ExpandedLabelText = $"Control Point Spacing: {tolerance.NewValue:N0}";
|
||||
|
||||
Tolerance.Value = displayToInternalTolerance(tolerance.NewValue);
|
||||
}, true);
|
||||
|
||||
displayCornerThreshold.BindValueChanged(threshold =>
|
||||
{
|
||||
cornerThresholdSlider.ContractedLabelText = $"C. T.: {threshold.NewValue:N0}";
|
||||
cornerThresholdSlider.ExpandedLabelText = $"Corner Threshold: {threshold.NewValue:N0}";
|
||||
|
||||
cornerThresholdSlider.ContractedLabelText = $"C. B.: {threshold.NewValue:N0}";
|
||||
CornerThreshold.Value = displayToInternalCornerThreshold(threshold.NewValue);
|
||||
}, true);
|
||||
|
||||
displayCircleThreshold.BindValueChanged(threshold =>
|
||||
{
|
||||
circleThresholdSlider.ContractedLabelText = $"P. C. T.: {threshold.NewValue:N0}";
|
||||
circleThresholdSlider.ExpandedLabelText = $"Perfect Curve Threshold: {threshold.NewValue:N0}";
|
||||
|
||||
circleThresholdSlider.ContractedLabelText = $"P. C. B.: {threshold.NewValue:N0}";
|
||||
CircleThreshold.Value = displayToInternalCircleThreshold(threshold.NewValue);
|
||||
}, true);
|
||||
|
||||
@@ -119,6 +124,11 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
displayCircleThreshold.Value = internalToDisplayCircleThreshold(threshold.NewValue)
|
||||
);
|
||||
|
||||
expandingContainer?.Expanded.BindValueChanged(v =>
|
||||
{
|
||||
Spacing = v.NewValue ? new Vector2(5) : new Vector2(15);
|
||||
}, true);
|
||||
|
||||
float displayToInternalTolerance(float v) => v / 50f;
|
||||
int internalToDisplayTolerance(float v) => (int)Math.Round(v * 50f);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
MinValue = 0f,
|
||||
MaxValue = OsuPlayfield.BASE_SIZE.X,
|
||||
Precision = 0.01f,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -48,17 +48,17 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
MinValue = 0f,
|
||||
MaxValue = OsuPlayfield.BASE_SIZE.Y,
|
||||
Precision = 0.01f,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The spacing between grid lines.
|
||||
/// </summary>
|
||||
public BindableFloat Spacing { get; } = new BindableFloat(4f)
|
||||
public BindableFloat GridLineSpacing { get; } = new BindableFloat(4f)
|
||||
{
|
||||
MinValue = 4f,
|
||||
MaxValue = 256f,
|
||||
Precision = 0.01f,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
MinValue = -180f,
|
||||
MaxValue = 180f,
|
||||
Precision = 0.01f,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
float dist = Vector2.Distance(point1, point2);
|
||||
while (dist >= max_automatic_spacing)
|
||||
dist /= 2;
|
||||
Spacing.Value = dist;
|
||||
GridLineSpacing.Value = dist;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@@ -127,21 +127,25 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
Current = StartPositionX,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "X offset",
|
||||
},
|
||||
startPositionYSlider = new ExpandableSlider<float>
|
||||
{
|
||||
Current = StartPositionY,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "Y offset",
|
||||
},
|
||||
spacingSlider = new ExpandableSlider<float>
|
||||
{
|
||||
Current = Spacing,
|
||||
Current = GridLineSpacing,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "Spacing",
|
||||
},
|
||||
gridLinesRotationSlider = new ExpandableSlider<float>
|
||||
{
|
||||
Current = GridLinesRotation,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "Rotation",
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
@@ -170,7 +174,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
},
|
||||
};
|
||||
|
||||
Spacing.Value = editorBeatmap.GridSize;
|
||||
GridLineSpacing.Value = editorBeatmap.GridSize;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -182,14 +186,12 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
StartPositionX.BindValueChanged(x =>
|
||||
{
|
||||
startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:#,0.##}";
|
||||
startPositionXSlider.ExpandedLabelText = $"X Offset: {x.NewValue:#,0.##}";
|
||||
StartPosition.Value = new Vector2(x.NewValue, StartPosition.Value.Y);
|
||||
}, true);
|
||||
|
||||
StartPositionY.BindValueChanged(y =>
|
||||
{
|
||||
startPositionYSlider.ContractedLabelText = $"Y: {y.NewValue:#,0.##}";
|
||||
startPositionYSlider.ExpandedLabelText = $"Y Offset: {y.NewValue:#,0.##}";
|
||||
StartPosition.Value = new Vector2(StartPosition.Value.X, y.NewValue);
|
||||
}, true);
|
||||
|
||||
@@ -199,10 +201,9 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
StartPositionY.Value = pos.NewValue.Y;
|
||||
});
|
||||
|
||||
Spacing.BindValueChanged(spacing =>
|
||||
GridLineSpacing.BindValueChanged(spacing =>
|
||||
{
|
||||
spacingSlider.ContractedLabelText = $"S: {spacing.NewValue:#,0.##}";
|
||||
spacingSlider.ExpandedLabelText = $"Spacing: {spacing.NewValue:#,0.##}";
|
||||
SpacingVector.Value = new Vector2(spacing.NewValue);
|
||||
editorBeatmap.GridSize = (int)spacing.NewValue;
|
||||
}, true);
|
||||
@@ -210,7 +211,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
GridLinesRotation.BindValueChanged(rotation =>
|
||||
{
|
||||
gridLinesRotationSlider.ContractedLabelText = $"R: {rotation.NewValue:#,0.##}";
|
||||
gridLinesRotationSlider.ExpandedLabelText = $"Rotation: {rotation.NewValue:#,0.##}";
|
||||
}, true);
|
||||
|
||||
GridType.BindValueChanged(v =>
|
||||
@@ -239,6 +239,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
gridTypeButtons.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint);
|
||||
gridTypeButtons.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None;
|
||||
|
||||
Spacing = v.NewValue ? new Vector2(5) : new Vector2(15);
|
||||
}, true);
|
||||
}
|
||||
|
||||
@@ -252,7 +254,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
switch (e.Action)
|
||||
{
|
||||
case GlobalAction.EditorCycleGridSpacing:
|
||||
Spacing.Value = Spacing.Value * 2 >= max_automatic_spacing ? Spacing.Value / 8 : Spacing.Value * 2;
|
||||
GridLineSpacing.Value = GridLineSpacing.Value * 2 >= max_automatic_spacing ? GridLineSpacing.Value / 8 : GridLineSpacing.Value * 2;
|
||||
return true;
|
||||
|
||||
case GlobalAction.EditorCycleGridType:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using JetBrains.Annotations;
|
||||
@@ -142,7 +143,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
case PositionSnapGridType.Triangle:
|
||||
var triangularPositionSnapGrid = new TriangularPositionSnapGrid();
|
||||
|
||||
triangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.Spacing);
|
||||
triangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);
|
||||
triangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation);
|
||||
|
||||
positionSnapGrid = triangularPositionSnapGrid;
|
||||
@@ -151,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
case PositionSnapGridType.Circle:
|
||||
var circularPositionSnapGrid = new CircularPositionSnapGrid();
|
||||
|
||||
circularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.Spacing);
|
||||
circularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);
|
||||
|
||||
positionSnapGrid = circularPositionSnapGrid;
|
||||
break;
|
||||
@@ -171,7 +172,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
=> new OsuBlueprintContainer(this);
|
||||
|
||||
public override string ConvertSelectionToString()
|
||||
=> string.Join(',', selectedHitObjects.Cast<OsuHitObject>().OrderBy(h => h.StartTime).Select(h => (h.IndexInCurrentCombo + 1).ToString()));
|
||||
=> string.Join(',', selectedHitObjects.Cast<OsuHitObject>().OrderBy(h => h.StartTime)
|
||||
.Select(h => (h.IndexInCurrentCombo + 1).ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
// 1,2,3,4 ...
|
||||
private static readonly Regex selection_regex = new Regex(@"^\d+(,\d+)*$", RegexOptions.Compiled);
|
||||
|
||||
@@ -67,6 +67,9 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
if (LastAcceptedAction != null && nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime))
|
||||
LastAcceptedAction = null;
|
||||
|
||||
if (LastAcceptedAction != null && gameplayClock.IsRewinding)
|
||||
LastAcceptedAction = null;
|
||||
}
|
||||
|
||||
protected abstract bool CheckValidNewAction(OsuAction action);
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override LocalisableString Description => @"Don't use the same key twice in a row!";
|
||||
public override IconUsage? Icon => OsuIcon.ModAlternate;
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModSingleTap) }).ToArray();
|
||||
public override bool Ranked => true;
|
||||
|
||||
protected override bool CheckValidNewAction(OsuAction action) => LastAcceptedAction != action;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override IconUsage? Icon => OsuIcon.ModSingleTap;
|
||||
public override LocalisableString Description => @"You must only use one key!";
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAlternate) }).ToArray();
|
||||
public override bool Ranked => true;
|
||||
|
||||
protected override bool CheckValidNewAction(OsuAction action) => LastAcceptedAction == null || LastAcceptedAction == action;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override LocalisableString Description => @"Spinners will be automatically completed.";
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot), typeof(OsuModTargetPractice) };
|
||||
public override bool Ranked => UsesDefaultConfiguration;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToDrawableHitObject(DrawableHitObject hitObject)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public class OsuModTouchDevice : ModTouchDevice
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModBloom) }).ToArray();
|
||||
public override bool Ranked => UsesDefaultConfiguration;
|
||||
public override bool Ranked => true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +230,11 @@ namespace osu.Game.Rulesets.Osu
|
||||
new ModScoreV2(),
|
||||
};
|
||||
|
||||
case ModType.Special:
|
||||
#if DEBUG
|
||||
return Array.Empty<Mod>();
|
||||
#endif
|
||||
|
||||
default:
|
||||
return Array.Empty<Mod>();
|
||||
}
|
||||
@@ -249,7 +254,11 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override string ShortName => SHORT_NAME;
|
||||
|
||||
#if !DEBUG
|
||||
public override string PlayingVerb => "Clicking circles";
|
||||
#else
|
||||
public override string PlayingVerb => "Debugging circles";
|
||||
#endif
|
||||
|
||||
public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this);
|
||||
|
||||
|
||||
@@ -77,9 +77,14 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
||||
base.LoadComplete();
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
LifetimeStart = smokeStartTime = Time.Current;
|
||||
|
||||
public void StartDrawing(double time)
|
||||
{
|
||||
LifetimeStart = smokeStartTime = time;
|
||||
LifetimeEnd = smokeEndTime = double.MaxValue;
|
||||
SmokePoints.Clear();
|
||||
lastPosition = null;
|
||||
totalDistance = pointInterval;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osu.Framework.Graphics.Performance;
|
||||
using osu.Game.Graphics;
|
||||
@@ -12,7 +11,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI.ReplayAnalysis
|
||||
{
|
||||
public partial class CursorPathContainer : Path
|
||||
public partial class CursorPathContainer : SmoothPath
|
||||
{
|
||||
private readonly LifetimeEntryManager lifetimeManager = new LifetimeEntryManager();
|
||||
private readonly SortedSet<AnalysisFrameEntry> aliveEntries = new SortedSet<AnalysisFrameEntry>(new AimLinePointComparator());
|
||||
@@ -22,14 +21,13 @@ namespace osu.Game.Rulesets.Osu.UI.ReplayAnalysis
|
||||
lifetimeManager.EntryBecameAlive += entryBecameAlive;
|
||||
lifetimeManager.EntryBecameDead += entryBecameDead;
|
||||
|
||||
PathRadius = 0.5f;
|
||||
PathRadius = 1f;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Colour = colours.Pink2;
|
||||
BackgroundColour = colours.Pink2.Opacity(0);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
@@ -19,17 +19,24 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
/// </summary>
|
||||
public partial class SmokeContainer : Container, IRequireHighFrequencyMousePosition, IKeyBindingHandler<OsuAction>
|
||||
{
|
||||
private DrawablePool<SmokeSkinnableDrawable> segmentPool = null!;
|
||||
private SmokeSkinnableDrawable? currentSegmentSkinnable;
|
||||
|
||||
private Vector2 lastMousePosition;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 _) => true;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddInternal(segmentPool = new DrawablePool<SmokeSkinnableDrawable>(10));
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<OsuAction> e)
|
||||
{
|
||||
if (e.Action == OsuAction.Smoke)
|
||||
{
|
||||
AddInternal(currentSegmentSkinnable = new SmokeSkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorSmoke), _ => new DefaultSmokeSegment()));
|
||||
AddInternal(currentSegmentSkinnable = segmentPool.Get(segment => segment.Segment?.StartDrawing(Time.Current)));
|
||||
|
||||
// Add initial position immediately.
|
||||
addPosition();
|
||||
@@ -59,17 +66,19 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
private void addPosition() => (currentSegmentSkinnable?.Drawable as SmokeSegment)?.AddPosition(lastMousePosition, Time.Current);
|
||||
private void addPosition() => currentSegmentSkinnable?.Segment?.AddPosition(lastMousePosition, Time.Current);
|
||||
|
||||
private partial class SmokeSkinnableDrawable : SkinnableDrawable
|
||||
{
|
||||
public SmokeSegment? Segment => Drawable as SmokeSegment;
|
||||
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
public override double LifetimeStart => Drawable.LifetimeStart;
|
||||
public override double LifetimeEnd => Drawable.LifetimeEnd;
|
||||
|
||||
public SmokeSkinnableDrawable(ISkinComponentLookup lookup, Func<ISkinComponentLookup, Drawable>? defaultImplementation = null, ConfineMode confineMode = ConfineMode.NoScaling)
|
||||
: base(lookup, defaultImplementation, confineMode)
|
||||
public SmokeSkinnableDrawable()
|
||||
: base(new OsuSkinComponentLookup(OsuSkinComponents.CursorSmoke), _ => new DefaultSmokeSegment())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<PropertyGroup Label="Nuget">
|
||||
<Title>osu! (ruleset)</Title>
|
||||
<PackageId>ppy.osu.Game.Rulesets.Osu</PackageId>
|
||||
<PackageId>jvnkosu.Client.Rulesets.Osu</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
|
||||
[Resolved]
|
||||
private TaikoHitObjectComposer? composer { get; set; }
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(spanPlacementObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(spanPlacementObject.Duration, 0));
|
||||
|
||||
public TaikoSpanPlacementBlueprint(HitObject hitObject)
|
||||
: base(hitObject)
|
||||
|
||||
@@ -13,9 +13,9 @@ namespace osu.Game.Rulesets.Taiko.Edit.Checks
|
||||
protected override IEnumerable<(DifficultyRating rating, double thresholdMs, string name)> GetThresholds()
|
||||
{
|
||||
// See lowest difficulty requirements in https://osu.ppy.sh/wiki/en/Ranking_criteria/osu%21taiko#general
|
||||
yield return (DifficultyRating.Hard, new TimeSpan(0, 3, 30).TotalMilliseconds, "Muzukashii");
|
||||
yield return (DifficultyRating.Insane, new TimeSpan(0, 4, 15).TotalMilliseconds, "Oni");
|
||||
yield return (DifficultyRating.Expert, new TimeSpan(0, 5, 0).TotalMilliseconds, "Inner Oni");
|
||||
yield return (DifficultyRating.Hard, new TimeSpan(0, 2, 30).TotalMilliseconds, "Muzukashii");
|
||||
yield return (DifficultyRating.Insane, new TimeSpan(0, 3, 15).TotalMilliseconds, "Oni");
|
||||
yield return (DifficultyRating.Expert, new TimeSpan(0, 4, 0).TotalMilliseconds, "Inner Oni");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
public override IconUsage? Icon => OsuIcon.ModSingleTap;
|
||||
public override LocalisableString Description => @"One key for dons, one key for kats.";
|
||||
|
||||
public override bool Ranked => true;
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax), typeof(TaikoModCinema) };
|
||||
public override ModType Type => ModType.Conversion;
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModRandom)).ToArray();
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
private int rollingHits;
|
||||
|
||||
private readonly Container tickContainer;
|
||||
private SkinnableDrawable headPiece;
|
||||
|
||||
private Color4 colourIdle;
|
||||
private Color4 colourEngaged;
|
||||
@@ -59,7 +60,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
Content.Add(tickContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = float.MinValue
|
||||
Depth = -1,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,7 +80,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
|
||||
protected override void RecreatePieces()
|
||||
{
|
||||
if (headPiece != null)
|
||||
Content.Remove(headPiece, true);
|
||||
|
||||
base.RecreatePieces();
|
||||
|
||||
Content.Add(headPiece = createHeadPiece());
|
||||
|
||||
updateColour();
|
||||
Height = HitObject.IsStrong ? TaikoStrongableHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE;
|
||||
}
|
||||
@@ -122,6 +129,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
protected override SkinnableDrawable CreateMainPiece() => new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.DrumRollBody),
|
||||
_ => new ElongatedCirclePiece());
|
||||
|
||||
private SkinnableDrawable createHeadPiece() => new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.DrumRollHead), _ => Empty())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Depth = -2,
|
||||
};
|
||||
|
||||
public override bool OnPressed(KeyBindingPressEvent<TaikoAction> e) => false;
|
||||
|
||||
private void onNewResult(DrawableHitObject obj, JudgementResult result)
|
||||
@@ -174,7 +187,23 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
private void updateColour(double fadeDuration = 0)
|
||||
{
|
||||
Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1);
|
||||
(MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration);
|
||||
|
||||
if (fadeDuration == 0)
|
||||
{
|
||||
// fade duration is 0 when calling via `RecreatePieces()`.
|
||||
// in this case we want to apply the colour *without* using transforms.
|
||||
// using transforms may result in the application of colour being undone via `DrawableHitObject.UpdateState()` clearing transforms.
|
||||
if (MainPiece.Drawable is IHasAccentColour mainPieceWithAccentColour)
|
||||
mainPieceWithAccentColour.AccentColour = newColour;
|
||||
|
||||
if (headPiece.Drawable is IHasAccentColour headPieceWithAccentColour)
|
||||
headPieceWithAccentColour.AccentColour = newColour;
|
||||
}
|
||||
else
|
||||
{
|
||||
(MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration);
|
||||
(headPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class StrongNestedHit : DrawableStrongNestedHit
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -21,14 +20,10 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
{
|
||||
get
|
||||
{
|
||||
// the reason why this calculation is so involved is that the head & tail sprites have different sizes/radii.
|
||||
// therefore naively taking the SSDQs of them and making a quad out of them results in a trapezoid shape and not a box.
|
||||
var headCentre = headCircle.ScreenSpaceDrawQuad.Centre;
|
||||
var headCentre = (body.ScreenSpaceDrawQuad.TopLeft + body.ScreenSpaceDrawQuad.BottomLeft) / 2;
|
||||
var tailCentre = (tailCircle.ScreenSpaceDrawQuad.TopLeft + tailCircle.ScreenSpaceDrawQuad.BottomLeft) / 2;
|
||||
|
||||
float headRadius = headCircle.ScreenSpaceDrawQuad.Height / 2;
|
||||
float tailRadius = tailCircle.ScreenSpaceDrawQuad.Height / 2;
|
||||
float radius = Math.Max(headRadius, tailRadius);
|
||||
float radius = body.ScreenSpaceDrawQuad.Height / 2;
|
||||
|
||||
var rectangle = new RectangleF(headCentre.X, headCentre.Y, tailCentre.X - headCentre.X, 0).Inflate(radius);
|
||||
return new Quad(rectangle.TopLeft, rectangle.TopRight, rectangle.BottomLeft, rectangle.BottomRight);
|
||||
@@ -37,8 +32,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => ScreenSpaceDrawQuad.Contains(screenSpacePos);
|
||||
|
||||
private LegacyCirclePiece headCircle = null!;
|
||||
|
||||
private Sprite body = null!;
|
||||
|
||||
private Sprite tailCircle = null!;
|
||||
@@ -66,10 +59,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Texture = skin.GetTexture("taiko-roll-middle", WrapMode.ClampToEdge, WrapMode.ClampToEdge),
|
||||
},
|
||||
headCircle = new LegacyCirclePiece
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
},
|
||||
};
|
||||
|
||||
AccentColour = colours.YellowDark;
|
||||
@@ -101,7 +90,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
{
|
||||
var colour = LegacyColourCompatibility.DisallowZeroAlpha(accentColour);
|
||||
|
||||
headCircle.AccentColour = colour;
|
||||
body.Colour = colour;
|
||||
tailCircle.Colour = colour;
|
||||
}
|
||||
|
||||
@@ -103,6 +103,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
{
|
||||
switch (taikoComponent.Component)
|
||||
{
|
||||
case TaikoSkinComponents.DrumRollHead:
|
||||
if (GetTexture("taiko-roll-middle") != null)
|
||||
return new LegacyCirclePiece();
|
||||
|
||||
return null;
|
||||
|
||||
case TaikoSkinComponents.DrumRollBody:
|
||||
if (GetTexture("taiko-roll-middle") != null)
|
||||
return new LegacyDrumRoll();
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Taiko
|
||||
InputDrum,
|
||||
CentreHit,
|
||||
RimHit,
|
||||
DrumRollHead,
|
||||
DrumRollBody,
|
||||
DrumRollTick,
|
||||
Swell,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<PropertyGroup Label="Nuget">
|
||||
<Title>osu!taiko (ruleset)</Title>
|
||||
<PackageId>ppy.osu.Game.Rulesets.Taiko</PackageId>
|
||||
<PackageId>jvnkosu.Client.Rulesets.Taiko</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace osu.Game.Tests.Chat
|
||||
public void OneTimeSetUp()
|
||||
{
|
||||
originalWebsiteRootUrl = MessageFormatter.WebsiteRootUrl;
|
||||
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
||||
MessageFormatter.WebsiteRootUrl = "osu.jvnko.boats";
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
@@ -47,11 +47,11 @@ namespace osu.Game.Tests.Chat
|
||||
[Test]
|
||||
public void TestSupportedProtocolLinkParsing()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "forgotspacehttps://dev.ppy.sh joinmyosump://12345 jointheosu://chan/#english" });
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "forgotspacehttps://osu.jvnko.boats joinmyjvnkosump://12345 jointhejvnkosu://chan/#english" });
|
||||
|
||||
Assert.AreEqual("https://dev.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual("osump://12345", result.Links[1].Url);
|
||||
Assert.AreEqual("osu://chan/#english", result.Links[2].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats", result.Links[0].Url);
|
||||
Assert.AreEqual("jvnkosump://12345", result.Links[1].Url);
|
||||
Assert.AreEqual("jvnkosu://chan/#english", result.Links[2].Url);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -66,15 +66,15 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual(36, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456?whatever")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123/456")]
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc/def", "https://dev.ppy.sh/beatmapsets/abc/def")]
|
||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123")]
|
||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123/whatever")]
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc", "https://dev.ppy.sh/beatmapsets/abc")]
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/discussions", "https://dev.ppy.sh/beatmapsets/discussions")]
|
||||
[TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/discussions/123", "https://dev.ppy.sh/beatmapsets/discussions/123")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://osu.jvnko.boats/beatmapsets/123#osu/456")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://osu.jvnko.boats/beatmapsets/123#osu/456?whatever")]
|
||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://osu.jvnko.boats/beatmapsets/123/456")]
|
||||
[TestCase(LinkAction.External, "https://osu.jvnko.boats/beatmapsets/abc/def", "https://osu.jvnko.boats/beatmapsets/abc/def")]
|
||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://osu.jvnko.boats/beatmapsets/123")]
|
||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://osu.jvnko.boats/beatmapsets/123/whatever")]
|
||||
[TestCase(LinkAction.External, "https://osu.jvnko.boats/beatmapsets/abc", "https://osu.jvnko.boats/beatmapsets/abc")]
|
||||
[TestCase(LinkAction.External, "https://osu.jvnko.boats/beatmapsets/discussions", "https://osu.jvnko.boats/beatmapsets/discussions")]
|
||||
[TestCase(LinkAction.External, "https://osu.jvnko.boats/beatmapsets/discussions/123", "https://osu.jvnko.boats/beatmapsets/discussions/123")]
|
||||
public void TestBeatmapLinks(LinkAction expectedAction, string expectedArg, string link)
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = link });
|
||||
@@ -150,7 +150,7 @@ namespace osu.Game.Tests.Chat
|
||||
|
||||
Assert.AreEqual("This is a Wiki Link.", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(9, result.Links[0].Length);
|
||||
}
|
||||
@@ -163,15 +163,15 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual("This is a Wiki Link Wiki:LinkWiki.Link.", result.DisplayContent);
|
||||
Assert.AreEqual(3, result.Links.Count);
|
||||
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats/wiki/Wiki Link", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(9, result.Links[0].Length);
|
||||
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki:Link", result.Links[1].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats/wiki/Wiki:Link", result.Links[1].Url);
|
||||
Assert.AreEqual(20, result.Links[1].Index);
|
||||
Assert.AreEqual(9, result.Links[1].Length);
|
||||
|
||||
Assert.AreEqual("https://dev.ppy.sh/wiki/Wiki.Link", result.Links[2].Url);
|
||||
Assert.AreEqual("https://osu.jvnko.boats/wiki/Wiki.Link", result.Links[2].Url);
|
||||
Assert.AreEqual(29, result.Links[2].Index);
|
||||
Assert.AreEqual(9, result.Links[2].Length);
|
||||
}
|
||||
@@ -452,7 +452,7 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual($"{OsuGameBase.OSU_PROTOCOL}chan/#english", result.Links[0].Url);
|
||||
Assert.AreEqual(26, result.Links[0].Index);
|
||||
Assert.AreEqual(19, result.Links[0].Length);
|
||||
Assert.AreEqual(23, result.Links[0].Length);
|
||||
|
||||
result = MessageFormatter.FormatMessage(new Message { Content = $"This is a [custom protocol]({OsuGameBase.OSU_PROTOCOL}chan/#english)." });
|
||||
|
||||
@@ -467,13 +467,13 @@ namespace osu.Game.Tests.Chat
|
||||
[Test]
|
||||
public void TestOsuMpProtocol()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "Join my multiplayer game osump://12346." });
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "Join my multiplayer game jvnkosump://12346." });
|
||||
|
||||
Assert.AreEqual(result.Content, result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("osump://12346", result.Links[0].Url);
|
||||
Assert.AreEqual("jvnkosump://12346", result.Links[0].Url);
|
||||
Assert.AreEqual(25, result.Links[0].Index);
|
||||
Assert.AreEqual(13, result.Links[0].Length);
|
||||
Assert.AreEqual(17, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -499,7 +499,7 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual("This is a simple test with some [traps] and wiki links. Don't forget to visit https://osu.ppy.sh now![emoji]", result.DisplayContent);
|
||||
Assert.AreEqual(4, result.Links.Count);
|
||||
|
||||
Link f = result.Links.Find(l => l.Url == "https://dev.ppy.sh/wiki/wiki links");
|
||||
Link f = result.Links.Find(l => l.Url == "https://osu.jvnko.boats/wiki/wiki links");
|
||||
Assert.That(f, Is.Not.Null);
|
||||
Assert.AreEqual(44, f.Index);
|
||||
Assert.AreEqual(10, f.Length);
|
||||
@@ -554,8 +554,8 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual("/relative", result.Argument);
|
||||
}
|
||||
|
||||
[TestCase("https://dev.ppy.sh/home/changelog", "")]
|
||||
[TestCase("https://dev.ppy.sh/home/changelog/lazer/2021.1012", "lazer/2021.1012")]
|
||||
[TestCase("https://osu.jvnko.boats/home/changelog", "")]
|
||||
[TestCase("https://osu.jvnko.boats/home/changelog/lazer/2021.1012", "lazer/2021.1012")]
|
||||
public void TestChangelogLinks(string link, string expectedArg)
|
||||
{
|
||||
LinkDetails result = MessageFormatter.GetLinkDetails(link);
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace osu.Game.Tests.Chat
|
||||
sentMessages = new List<Message>();
|
||||
silencedUserIds = new List<int>();
|
||||
|
||||
((DummyAPIAccess)API).LocalUserState.Blocks.Clear();
|
||||
((DummyAPIAccess)API).HandleRequest = req =>
|
||||
{
|
||||
switch (req)
|
||||
@@ -63,6 +64,10 @@ namespace osu.Game.Tests.Chat
|
||||
silencedUserIds.Clear();
|
||||
return true;
|
||||
|
||||
case GetMessagesRequest getMessages:
|
||||
getMessages.TriggerSuccess(sentMessages);
|
||||
return true;
|
||||
|
||||
case GetUpdatesRequest updatesRequest:
|
||||
updatesRequest.TriggerSuccess(new GetUpdatesResponse
|
||||
{
|
||||
@@ -161,6 +166,85 @@ namespace osu.Game.Tests.Chat
|
||||
AddUntilStep("/help command received", () => channel.Messages.Last().Content.Contains("Supported commands"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBlockedUserMessagesAreDeletedFromInitialMessageBatch()
|
||||
{
|
||||
Channel channel = null;
|
||||
|
||||
AddStep("create channel", () => channel = createChannel(1, ChannelType.Public));
|
||||
AddStep("post a message from blocked user", () => sentMessages.Add(new Message
|
||||
{
|
||||
ChannelId = channel.Id,
|
||||
Content = "i am blocked",
|
||||
SenderId = 1234
|
||||
}));
|
||||
AddStep("mark user as blocked", () => ((DummyAPIAccess)API).LocalUserState.Blocks.Add(new APIRelation
|
||||
{
|
||||
TargetUser = new APIUser { Username = "blocked", Id = 1234 },
|
||||
TargetID = 1234,
|
||||
}));
|
||||
|
||||
AddStep("join channel and select it", () =>
|
||||
{
|
||||
channelManager.JoinChannel(channel);
|
||||
channelManager.CurrentChannel.Value = channel;
|
||||
});
|
||||
AddAssert("channel has no messages", () => channel.Messages, () => Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBlockedUserMessagesAreDeletedImmediatelyOnBlock()
|
||||
{
|
||||
Channel channel = null;
|
||||
|
||||
AddStep("create channel", () => channel = createChannel(1, ChannelType.Public));
|
||||
|
||||
AddStep("join channel and select it", () =>
|
||||
{
|
||||
channelManager.JoinChannel(channel);
|
||||
channelManager.CurrentChannel.Value = channel;
|
||||
});
|
||||
AddStep("post a message from blocked user", () => sentMessages.Add(new Message
|
||||
{
|
||||
ChannelId = channel.Id,
|
||||
Content = "i am blocked",
|
||||
SenderId = 1234
|
||||
}));
|
||||
AddUntilStep("channel has message", () => channel.Messages, () => Is.Not.Empty);
|
||||
|
||||
AddStep("block user", () => ((DummyAPIAccess)API).LocalUserState.Blocks.Add(new APIRelation
|
||||
{
|
||||
TargetUser = new APIUser { Username = "blocked", Id = 1234 },
|
||||
TargetID = 1234,
|
||||
}));
|
||||
AddAssert("channel has no messages", () => channel.Messages, () => Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPrivateChannelsPurgedOnUserChange()
|
||||
{
|
||||
var pmChannel = createChannel(1002, ChannelType.PM);
|
||||
AddStep("join a few private channels", () =>
|
||||
{
|
||||
channelManager.JoinChannel(createChannel(1001, ChannelType.PM));
|
||||
channelManager.JoinChannel(createChannel(1003, ChannelType.Team));
|
||||
channelManager.JoinChannel(pmChannel);
|
||||
});
|
||||
AddStep("close a PM channel", () => channelManager.LeaveChannel(pmChannel));
|
||||
|
||||
AddStep("switch user", () =>
|
||||
{
|
||||
((DummyAPIAccess.DummyLocalUserState)API.LocalUserState).User.Value = new APIUser
|
||||
{
|
||||
Id = 9009,
|
||||
Username = "someone_else"
|
||||
};
|
||||
});
|
||||
|
||||
AddAssert("not joined to private channels of previous user",
|
||||
() => !channelManager.JoinedChannels.Select(ch => ch.Id).Any(id => id >= 1001 && id <= 1003));
|
||||
}
|
||||
|
||||
private void handlePostMessageRequest(PostMessageRequest request)
|
||||
{
|
||||
var message = new Message(++currentMessageId)
|
||||
@@ -191,7 +275,7 @@ namespace osu.Game.Tests.Chat
|
||||
}
|
||||
}
|
||||
|
||||
private Channel createChannel(int id, ChannelType type) => new Channel(new APIUser())
|
||||
private Channel createChannel(int id, ChannelType type) => new Channel(new APIUser { Id = id })
|
||||
{
|
||||
Id = id,
|
||||
Name = $"Channel {id}",
|
||||
|
||||
@@ -126,6 +126,22 @@ namespace osu.Game.Tests.Gameplay
|
||||
AssertBeatmapLookup(expected_sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that a hitobject which specifies a specific sample file which doesn't exist (or isn't allowed to be looked up)
|
||||
/// falls back to a normal sample.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestFileSampleFallsBackToNormal()
|
||||
{
|
||||
const string expected_sample = "normal-hitnormal";
|
||||
|
||||
SetupSkins(null, expected_sample);
|
||||
|
||||
CreateTestWithBeatmap("file-beatmap-sample.osu");
|
||||
|
||||
AssertUserLookup(expected_sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that a default hitobject and control point causes <see cref="TestDefaultSampleFromUserSkin"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -134,10 +134,12 @@ namespace osu.Game.Tests.Mods
|
||||
|
||||
var mod = (OsuModDifficultyAdjust)apiMod.ToMod(ruleset);
|
||||
|
||||
// WARNING: this only makes sense for debug builds which have very extended limits
|
||||
// release builds still use sane values
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(mod.CircleSize.Value, Is.GreaterThanOrEqualTo(0).And.LessThanOrEqualTo(11));
|
||||
Assert.That(mod.ApproachRate.Value, Is.GreaterThanOrEqualTo(-10).And.LessThanOrEqualTo(11));
|
||||
Assert.That(mod.CircleSize.Value, Is.GreaterThanOrEqualTo(-250).And.LessThanOrEqualTo(13));
|
||||
Assert.That(mod.ApproachRate.Value, Is.GreaterThanOrEqualTo(-250).And.LessThanOrEqualTo(13));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -738,6 +738,16 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
||||
new object[] { "submitted=99999", false },
|
||||
new object[] { "submitted>=2012-03-05-04", false },
|
||||
new object[] { "submitted>=2012/03.05-04", false },
|
||||
|
||||
new object[] { "created<2012", true },
|
||||
new object[] { "created<2012.03", true },
|
||||
new object[] { "created<2012/03/05", true },
|
||||
new object[] { "created<2012-3-5", true },
|
||||
|
||||
new object[] { "created<0", false },
|
||||
new object[] { "created=99999", false },
|
||||
new object[] { "created>=2012-03-05-04", false },
|
||||
new object[] { "created>=2012/03.05-04", false },
|
||||
};
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.Matchmaking;
|
||||
@@ -29,17 +30,17 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 3, TotalScore = 750 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(8, state.Users[1].Points);
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(1, state.Users[1].Rounds[1].Placement);
|
||||
Assert.AreEqual(8, state.Users.GetOrAdd(1).Points);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(6, state.Users[2].Points);
|
||||
Assert.AreEqual(3, state.Users[2].Placement);
|
||||
Assert.AreEqual(3, state.Users[2].Rounds[1].Placement);
|
||||
Assert.AreEqual(6, state.Users.GetOrAdd(2).Points);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(2).Placement);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(2).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(7, state.Users[3].Points);
|
||||
Assert.AreEqual(2, state.Users[3].Placement);
|
||||
Assert.AreEqual(2, state.Users[3].Rounds[1].Placement);
|
||||
Assert.AreEqual(7, state.Users.GetOrAdd(3).Points);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(3).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(3).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
// 2 -> 1 -> 3
|
||||
|
||||
@@ -51,17 +52,17 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 3, TotalScore = 500 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(15, state.Users[1].Points);
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(2, state.Users[1].Rounds[2].Placement);
|
||||
Assert.AreEqual(15, state.Users.GetOrAdd(1).Points);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(1).Rounds.GetOrAdd(2).Placement);
|
||||
|
||||
Assert.AreEqual(14, state.Users[2].Points);
|
||||
Assert.AreEqual(2, state.Users[2].Placement);
|
||||
Assert.AreEqual(1, state.Users[2].Rounds[2].Placement);
|
||||
Assert.AreEqual(14, state.Users.GetOrAdd(2).Points);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(2).Rounds.GetOrAdd(2).Placement);
|
||||
|
||||
Assert.AreEqual(13, state.Users[3].Points);
|
||||
Assert.AreEqual(3, state.Users[3].Placement);
|
||||
Assert.AreEqual(3, state.Users[3].Rounds[2].Placement);
|
||||
Assert.AreEqual(13, state.Users.GetOrAdd(3).Points);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(3).Placement);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(3).Rounds.GetOrAdd(2).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -80,21 +81,21 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 4, TotalScore = 500 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(7, state.Users[1].Points);
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(2, state.Users[1].Rounds[1].Placement);
|
||||
Assert.AreEqual(7, state.Users.GetOrAdd(1).Points);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(1).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(7, state.Users[2].Points);
|
||||
Assert.AreEqual(2, state.Users[2].Placement);
|
||||
Assert.AreEqual(2, state.Users[2].Rounds[1].Placement);
|
||||
Assert.AreEqual(7, state.Users.GetOrAdd(2).Points);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(5, state.Users[3].Points);
|
||||
Assert.AreEqual(3, state.Users[3].Placement);
|
||||
Assert.AreEqual(4, state.Users[3].Rounds[1].Placement);
|
||||
Assert.AreEqual(5, state.Users.GetOrAdd(3).Points);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(3).Placement);
|
||||
Assert.AreEqual(4, state.Users.GetOrAdd(3).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(5, state.Users[4].Points);
|
||||
Assert.AreEqual(4, state.Users[4].Placement);
|
||||
Assert.AreEqual(4, state.Users[4].Rounds[1].Placement);
|
||||
Assert.AreEqual(5, state.Users.GetOrAdd(4).Points);
|
||||
Assert.AreEqual(4, state.Users.GetOrAdd(4).Placement);
|
||||
Assert.AreEqual(4, state.Users.GetOrAdd(4).Rounds.GetOrAdd(1).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -120,8 +121,8 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 2, TotalScore = 1000 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(2, state.Users[2].Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -142,12 +143,40 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 5, TotalScore = 1000 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(2, state.Users[2].Placement);
|
||||
Assert.AreEqual(3, state.Users[3].Placement);
|
||||
Assert.AreEqual(4, state.Users[4].Placement);
|
||||
Assert.AreEqual(5, state.Users[5].Placement);
|
||||
Assert.AreEqual(6, state.Users[6].Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(3).Placement);
|
||||
Assert.AreEqual(4, state.Users.GetOrAdd(4).Placement);
|
||||
Assert.AreEqual(5, state.Users.GetOrAdd(5).Placement);
|
||||
Assert.AreEqual(6, state.Users.GetOrAdd(6).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AbandonOrder()
|
||||
{
|
||||
var state = new MatchmakingRoomState();
|
||||
|
||||
state.AdvanceRound();
|
||||
state.RecordScores(
|
||||
[
|
||||
new SoloScoreInfo { UserID = 1, TotalScore = 1000 },
|
||||
new SoloScoreInfo { UserID = 2, TotalScore = 500 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
|
||||
state.Users.GetOrAdd(1).AbandonedAt = DateTimeOffset.Now;
|
||||
state.RecordScores([], placement_points);
|
||||
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(2).Placement);
|
||||
|
||||
state.Users.GetOrAdd(2).AbandonedAt = DateTimeOffset.Now - TimeSpan.FromMinutes(1);
|
||||
state.RecordScores([], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace osu.Game.Tests.Online
|
||||
Assert.NotNull(converted);
|
||||
Assert.That(converted, Is.TypeOf(typeof(UnknownMod)));
|
||||
Assert.That(converted.Type, Is.EqualTo(ModType.System));
|
||||
Assert.That(converted.Acronym, Is.EqualTo("WNG??"));
|
||||
Assert.That(converted.Acronym, Is.EqualTo("WNG!"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace osu.Game.Tests.Online
|
||||
public override Live<BeatmapSetInfo>? ImportModel(BeatmapSetInfo item, ArchiveReader? archive = null, ImportParameters parameters = default,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!testBeatmapManager.AllowImport.Wait(TimeSpan.FromSeconds(10), cancellationToken))
|
||||
if (!testBeatmapManager.AllowImport.Wait(TimeSpan.FromSeconds(30), cancellationToken))
|
||||
throw new TimeoutException("Timeout waiting for import to be allowed.");
|
||||
|
||||
return testBeatmapManager.CurrentImport = base.ImportModel(item, archive, parameters, cancellationToken);
|
||||
@@ -257,4 +257,4 @@ namespace osu.Game.Tests.Online
|
||||
protected override string Target => string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -81,6 +81,8 @@ namespace osu.Game.Tests.Skins
|
||||
"Archives/modified-argon-20250809.osk",
|
||||
// Covers "Argon" judgement counter
|
||||
"Archives/modified-argon-20250308.osk",
|
||||
// Covers "Argon" clicks/s counter, longest combo counter, skinnable SR display and beatmap status pill
|
||||
"Archives/modified-argon-20251215-jvnkosu.osk",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -266,7 +266,11 @@ namespace osu.Game.Tests.Visual.Background
|
||||
|
||||
FadeAccessibleResults results = null;
|
||||
|
||||
AddStep("Transition to Results", () => player.Push(results = new FadeAccessibleResults(TestResources.CreateTestScoreInfo())));
|
||||
AddStep("Transition to Results", () =>
|
||||
{
|
||||
player.ValidForResume = false;
|
||||
player.Push(results = new FadeAccessibleResults(TestResources.CreateTestScoreInfo()));
|
||||
});
|
||||
|
||||
AddUntilStep("Wait for results is current", () => results.IsCurrentScreen());
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Beatmaps
|
||||
AddStep("create thumbnail", () =>
|
||||
{
|
||||
var beatmapSet = CreateAPIBeatmapSet(Ruleset.Value);
|
||||
beatmapSet.OnlineID = 241526; // ID hardcoded to ensure that the preview track exists online.
|
||||
beatmapSet.OnlineID = 1; // ID hardcoded to ensure that the preview track exists online.
|
||||
|
||||
Child = thumbnail = new BeatmapCardThumbnail(beatmapSet, beatmapSet)
|
||||
{
|
||||
|
||||
@@ -220,10 +220,13 @@ namespace osu.Game.Tests.Visual.Components
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
if (registerAsOwner)
|
||||
dependencies.CacheAs<IPreviewTrackOwner>(this);
|
||||
return dependencies;
|
||||
{
|
||||
// Automatically handled by interface caching.
|
||||
return base.CreateChildDependencies(parent);
|
||||
}
|
||||
|
||||
return new DependencyContainer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
double lastStarRating = 0;
|
||||
double lastLength = 0;
|
||||
|
||||
AddStep("Add timing point", () => EditorBeatmap.ControlPointInfo.Add(200, new TimingControlPoint { BeatLength = 600 }));
|
||||
AddStep("Add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 600 }));
|
||||
AddStep("Change to placement mode", () => InputManager.Key(Key.Number2));
|
||||
AddStep("Move to playfield", () => InputManager.MoveMouseTo(Game.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("Place single hitcircle", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
setUpEditor(new OsuRuleset().RulesetInfo);
|
||||
AddAssert("is osu! ruleset", () => editorBeatmap.BeatmapInfo.Ruleset.Equals(new OsuRuleset().RulesetInfo));
|
||||
|
||||
AddStep("jump to encoded link", () => Game.HandleLink("osu://edit/00:14:142%20(1)"));
|
||||
AddStep("jump to encoded link", () => Game.HandleLink("jvnkosu://edit/00:14:142%20(1)"));
|
||||
|
||||
AddUntilStep("wait for seek", () => editorClock.SeekingOrStopped.Value);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets;
|
||||
@@ -27,7 +28,12 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new TestBeatmap(ruleset, false);
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private GlobalActionContainer globalActionContainer => this.ChildrenOfType<GlobalActionContainer>().Single();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
@@ -27,7 +28,12 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new TestBeatmap(ruleset, false);
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 500 });
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private TimelineBlueprintContainer blueprintContainer
|
||||
=> Editor.ChildrenOfType<TimelineBlueprintContainer>().First();
|
||||
@@ -80,7 +86,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
InputManager.Key(Key.Number1);
|
||||
blueprint = this.ChildrenOfType<TimelineHitObjectBlueprint>().First();
|
||||
InputManager.MoveMouseTo(blueprint);
|
||||
InputManager.MoveMouseTo(blueprint, new Vector2(-1, 0));
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public partial class TestSceneDrawableGameplayLeaderboardScore : OsuTestScene
|
||||
{
|
||||
private readonly APIUser user = new APIUser { Username = "user" };
|
||||
private readonly BindableLong totalScore = new BindableLong();
|
||||
private readonly Bindable<int?> position = new Bindable<int?>();
|
||||
private readonly BindableBool quit = new BindableBool();
|
||||
private readonly BindableBool expanded = new BindableBool();
|
||||
|
||||
public TestSceneDrawableGameplayLeaderboardScore()
|
||||
{
|
||||
AddSliderStep("total score", 0, 1_000_000, 500_000, s => totalScore.Value = s);
|
||||
AddSliderStep("position", 1, 100, 5, s => position.Value = s);
|
||||
AddToggleStep("toggle quit", q => quit.Value = q);
|
||||
AddToggleStep("toggle expanded", e => expanded.Value = e);
|
||||
}
|
||||
|
||||
private static readonly OsuColour osu_colour = new OsuColour();
|
||||
|
||||
private static readonly object?[][] leaderboard_variants =
|
||||
{
|
||||
new object?[] { false, null },
|
||||
new object?[] { true, null },
|
||||
new object?[] { false, osu_colour.TeamColourRed },
|
||||
new object?[] { true, osu_colour.TeamColourRed },
|
||||
new object?[] { false, osu_colour.TeamColourBlue },
|
||||
new object?[] { true, osu_colour.TeamColourBlue },
|
||||
};
|
||||
|
||||
[TestCaseSource(nameof(leaderboard_variants))]
|
||||
public void TestVariants(bool tracked, Color4? teamColour)
|
||||
{
|
||||
AddStep("show", () =>
|
||||
{
|
||||
GameplayLeaderboardScore score = new GameplayLeaderboardScore(user, tracked, totalScore)
|
||||
{
|
||||
Position = { BindTarget = position },
|
||||
HasQuit = { BindTarget = quit },
|
||||
TeamColour = teamColour,
|
||||
};
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 250,
|
||||
Child = new DrawableGameplayLeaderboardScore(score)
|
||||
{
|
||||
Expanded = { BindTarget = expanded },
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
checkKey(() => counter, 0, false);
|
||||
|
||||
AddStep("press Z", () => InputManager.PressKey(Key.Z));
|
||||
@@ -117,7 +117,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new ManiaRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
checkKey(() => counter, 0, false);
|
||||
|
||||
AddStep("press space", () => InputManager.PressKey(Key.Space));
|
||||
@@ -150,8 +150,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counterX = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter Z", () => counterZ = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter X", () => counterX = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.RightButton));
|
||||
AddStep("get key counter Z", () => counterZ = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter X", () => counterX = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.RightButton));
|
||||
|
||||
AddStep("press Z", () => InputManager.PressKey(Key.Z));
|
||||
AddStep("pause", () => Player.Pause());
|
||||
@@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new ManiaRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
|
||||
AddStep("press space", () => InputManager.PressKey(Key.Space));
|
||||
AddStep("pause", () => Player.Pause());
|
||||
@@ -204,8 +204,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counterX = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter Z", () => counterZ = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter X", () => counterX = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.RightButton));
|
||||
AddStep("get key counter Z", () => counterZ = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter X", () => counterX = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.RightButton));
|
||||
|
||||
AddStep("press Z", () => InputManager.PressKey(Key.Z));
|
||||
AddStep("pause", () => Player.Pause());
|
||||
@@ -247,7 +247,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new ManiaRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<ManiaAction> actionTrigger && actionTrigger.Action == ManiaAction.Key4));
|
||||
|
||||
AddStep("press space", () => InputManager.PressKey(Key.Space));
|
||||
checkKey(() => counter, 1, true);
|
||||
@@ -271,7 +271,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
|
||||
AddStep("pause", () => Player.Pause());
|
||||
AddStep("resume", () => Player.Resume());
|
||||
@@ -297,7 +297,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
KeyCounter counter = null!;
|
||||
|
||||
loadPlayer(() => new OsuRuleset());
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterActionTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
AddStep("get key counter", () => counter = this.ChildrenOfType<KeyCounter>().Single(k => k.Trigger is KeyCounterBindingTrigger<OsuAction> actionTrigger && actionTrigger.Action == OsuAction.LeftButton));
|
||||
|
||||
AddStep("press Z", () => InputManager.PressKey(Key.Z));
|
||||
AddAssert("circle hit", () => Player.ScoreProcessor.HighestCombo.Value, () => Is.EqualTo(1));
|
||||
|
||||
@@ -642,7 +642,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
if (!AllowLoad.Wait(TimeSpan.FromSeconds(10)))
|
||||
if (!AllowLoad.Wait(TimeSpan.FromSeconds(30)))
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
public Drawable OverlayContent => InternalChild;
|
||||
|
||||
public Drawable FadingContent => (OverlayContent as Container)?.Child;
|
||||
public new Drawable FadingContent => (OverlayContent as Container)?.Child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
osu.Game.Tests/Visual/Matchmaking/MatchmakingTestScene.cs
Normal file
34
osu.Game.Tests/Visual/Matchmaking/MatchmakingTestScene.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public abstract partial class MatchmakingTestScene : MultiplayerTestScene
|
||||
{
|
||||
protected override Container<Drawable> Content { get; }
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Plum);
|
||||
|
||||
protected MatchmakingTestScene()
|
||||
{
|
||||
BackgroundScreenStack backgroundStack;
|
||||
|
||||
base.Content.AddRange(new Drawable[]
|
||||
{
|
||||
backgroundStack = new BackgroundScreenStack(),
|
||||
Content = new Container { RelativeSizeAxes = Axes.Both }
|
||||
});
|
||||
|
||||
backgroundStack.Push(new MatchmakingBackgroundScreen(colourProvider));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -13,15 +14,15 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match.BeatmapSelect;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestSceneBeatmapSelectGrid : OnlinePlayTestScene
|
||||
public partial class TestSceneBeatmapSelectGrid : MatchmakingTestScene
|
||||
{
|
||||
private MultiplayerPlaylistItem[] items = null!;
|
||||
private MatchmakingPlaylistItem[] items = null!;
|
||||
|
||||
private BeatmapSelectGrid grid = null!;
|
||||
|
||||
@@ -36,24 +37,44 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
.Take(50)
|
||||
.ToArray();
|
||||
|
||||
IEnumerable<MatchmakingPlaylistItem> playlistItems;
|
||||
|
||||
if (beatmaps.Length > 0)
|
||||
{
|
||||
items = Enumerable.Range(1, 50).Select(i => new MultiplayerPlaylistItem
|
||||
playlistItems = Enumerable.Range(1, 50).Select(i =>
|
||||
{
|
||||
ID = i,
|
||||
BeatmapID = beatmaps[i % beatmaps.Length].OnlineID,
|
||||
StarRating = i / 10.0,
|
||||
}).ToArray();
|
||||
var beatmap = beatmaps[i % beatmaps.Length];
|
||||
|
||||
return new MatchmakingPlaylistItem(
|
||||
new MultiplayerPlaylistItem
|
||||
{
|
||||
ID = i,
|
||||
BeatmapID = beatmap.OnlineID,
|
||||
StarRating = i / 10.0,
|
||||
},
|
||||
CreateAPIBeatmap(beatmap),
|
||||
Array.Empty<Mod>()
|
||||
);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
items = Enumerable.Range(1, 50).Select(i => new MultiplayerPlaylistItem
|
||||
{
|
||||
ID = i,
|
||||
BeatmapID = i,
|
||||
StarRating = i / 10.0,
|
||||
}).ToArray();
|
||||
playlistItems = Enumerable.Range(1, 50).Select(i => new MatchmakingPlaylistItem(
|
||||
new MultiplayerPlaylistItem
|
||||
{
|
||||
ID = i,
|
||||
BeatmapID = i,
|
||||
StarRating = i / 10.0,
|
||||
},
|
||||
CreateAPIBeatmap(),
|
||||
Array.Empty<Mod>()
|
||||
));
|
||||
}
|
||||
|
||||
foreach (var item in playlistItems)
|
||||
item.Beatmap.StarRating = item.PlaylistItem.StarRating;
|
||||
|
||||
items = playlistItems.ToArray();
|
||||
}
|
||||
|
||||
public override void SetUpSteps()
|
||||
@@ -70,8 +91,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
|
||||
AddStep("add items", () =>
|
||||
{
|
||||
foreach (var item in items)
|
||||
grid.AddItem(item);
|
||||
grid.AddItems(items);
|
||||
});
|
||||
|
||||
AddWaitStep("wait for panels", 3);
|
||||
@@ -85,17 +105,17 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
// test scene is weird.
|
||||
});
|
||||
|
||||
AddStep("add selection 1", () => grid.ChildrenOfType<BeatmapSelectPanel>().First().AddUser(new APIUser
|
||||
AddStep("add selection 1", () => grid.ChildrenOfType<MatchmakingSelectPanel>().First().AddUser(new APIUser
|
||||
{
|
||||
Id = DummyAPIAccess.DUMMY_USER_ID,
|
||||
Username = "Maarvin",
|
||||
}));
|
||||
AddStep("add selection 2", () => grid.ChildrenOfType<BeatmapSelectPanel>().Skip(5).First().AddUser(new APIUser
|
||||
AddStep("add selection 2", () => grid.ChildrenOfType<MatchmakingSelectPanel>().Skip(5).First().AddUser(new APIUser
|
||||
{
|
||||
Id = 2,
|
||||
Username = "peppy",
|
||||
}));
|
||||
AddStep("add selection 3", () => grid.ChildrenOfType<BeatmapSelectPanel>().Skip(10).First().AddUser(new APIUser
|
||||
AddStep("add selection 3", () => grid.ChildrenOfType<MatchmakingSelectPanel>().Skip(10).First().AddUser(new APIUser
|
||||
{
|
||||
Id = 1040328,
|
||||
Username = "smoogipoo",
|
||||
@@ -109,7 +129,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
var (candidateItems, finalItem) = pickRandomItems(5);
|
||||
|
||||
grid.RollAndDisplayFinalBeatmap(candidateItems, finalItem);
|
||||
grid.RollAndDisplayFinalBeatmap(candidateItems, finalItem, finalItem);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -138,7 +158,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
grid.ArrangeItemsForRollAnimation(duration: 0, stagger: 0);
|
||||
grid.PlayRollAnimation(finalItem, duration: 0);
|
||||
|
||||
Scheduler.AddDelayed(() => grid.PresentRolledBeatmap(finalItem), 500);
|
||||
Scheduler.AddDelayed(() => grid.PresentRolledBeatmap(finalItem, finalItem), 500);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -153,7 +173,25 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
grid.ArrangeItemsForRollAnimation(duration: 0, stagger: 0);
|
||||
grid.PlayRollAnimation(finalItem, duration: 0);
|
||||
|
||||
Scheduler.AddDelayed(() => grid.PresentUnanimouslyChosenBeatmap(finalItem), 500);
|
||||
Scheduler.AddDelayed(() => grid.PresentUnanimouslyChosenBeatmap(finalItem, finalItem), 500);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPresentRandomItem()
|
||||
{
|
||||
AddStep("present random item panel", () =>
|
||||
{
|
||||
var (candidateItems, finalItem) = pickRandomItems(4);
|
||||
|
||||
grid.TransferCandidatePanelsToRollContainer(candidateItems.Append(-1).ToArray(), duration: 0);
|
||||
grid.ArrangeItemsForRollAnimation(duration: 0, stagger: 0);
|
||||
grid.PlayRollAnimation(-1, duration: 0);
|
||||
|
||||
Scheduler.AddDelayed(() =>
|
||||
{
|
||||
grid.PresentRolledBeatmap(-1, finalItem);
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -180,7 +218,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
|
||||
AddStep("display roll order", () =>
|
||||
{
|
||||
var panels = grid.ChildrenOfType<BeatmapSelectPanel>().ToArray();
|
||||
var panels = grid.ChildrenOfType<MatchmakingSelectPanel>().ToArray();
|
||||
|
||||
for (int i = 0; i < panels.Length; i++)
|
||||
{
|
||||
@@ -197,6 +235,22 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRollAnimationFinalRandom()
|
||||
{
|
||||
AddStep("play animation", () =>
|
||||
{
|
||||
(long[] candidateItems, _) = pickRandomItems(5);
|
||||
|
||||
candidateItems = candidateItems.Append(-1).ToArray();
|
||||
long finalItem = items.First(i => !candidateItems.Contains(i.ID)).ID;
|
||||
|
||||
grid.RollAndDisplayFinalBeatmap(candidateItems, -1, finalItem);
|
||||
});
|
||||
|
||||
AddWaitStep("wait for animation", 10);
|
||||
}
|
||||
|
||||
private (long[] candidateItems, long finalItem) pickRandomItems(int count)
|
||||
{
|
||||
long[] candidateItems = items.Select(it => it.ID).ToArray();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -9,27 +10,45 @@ using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match.BeatmapSelect;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestSceneBeatmapSelectPanel : MultiplayerTestScene
|
||||
public partial class TestSceneBeatmapSelectPanel : MatchmakingTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("join room", () =>
|
||||
{
|
||||
var room = CreateDefaultRoom(MatchType.Matchmaking);
|
||||
room.Playlist = Enumerable.Range(1, 50).Select(i => new PlaylistItem(new MultiplayerPlaylistItem
|
||||
{
|
||||
ID = i,
|
||||
BeatmapID = 0,
|
||||
StarRating = i / 10.0,
|
||||
})).ToArray();
|
||||
|
||||
JoinRoom(room);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBeatmapPanel()
|
||||
{
|
||||
BeatmapSelectPanel? panel = null;
|
||||
MatchmakingSelectPanel? panel = null;
|
||||
|
||||
AddStep("add panel", () =>
|
||||
{
|
||||
Child = new OsuContextMenuContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = panel = new BeatmapSelectPanel(new MultiplayerPlaylistItem())
|
||||
Child = panel = new MatchmakingSelectPanelBeatmap(new MatchmakingPlaylistItem(new MultiplayerPlaylistItem(), CreateAPIBeatmap(), []))
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@@ -56,10 +75,54 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
AddStep("remove peppy", () => panel!.RemoveUser(new APIUser { Id = 2 }));
|
||||
AddStep("remove maarvin", () => panel!.RemoveUser(new APIUser { Id = 6411631 }));
|
||||
|
||||
AddToggleStep("allow selection", value =>
|
||||
AddToggleStep("allow selection", value => panel!.AllowSelection = value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRandomPanel()
|
||||
{
|
||||
MatchmakingSelectPanelRandom? panel = null;
|
||||
|
||||
AddStep("add panel", () =>
|
||||
{
|
||||
if (panel != null)
|
||||
panel.AllowSelection = value;
|
||||
Child = new OsuContextMenuContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = panel = new MatchmakingSelectPanelRandom(new MultiplayerPlaylistItem { ID = -1 })
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
AddToggleStep("allow selection", value => panel!.AllowSelection = value);
|
||||
|
||||
AddStep("reveal beatmap", () => panel!.PresentAsChosenBeatmap(new MatchmakingPlaylistItem(new MultiplayerPlaylistItem(), CreateAPIBeatmap(), [])));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBeatmapWithMods()
|
||||
{
|
||||
AddStep("add panel", () =>
|
||||
{
|
||||
MatchmakingSelectPanel? panel;
|
||||
|
||||
Child = new OsuContextMenuContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = panel = new MatchmakingSelectPanelBeatmap(new MatchmakingPlaylistItem(new MultiplayerPlaylistItem(), CreateAPIBeatmap(), [new OsuModHardRock(), new OsuModDoubleTime()]))
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
};
|
||||
|
||||
panel.AddUser(new APIUser
|
||||
{
|
||||
Id = 2,
|
||||
Username = "peppy",
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestSceneMatchmakingChatDisplay : ScreenTestScene
|
||||
public partial class TestSceneMatchmakingChatDisplay : MatchmakingTestScene
|
||||
{
|
||||
private MatchmakingChatDisplay? chat;
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
Value =
|
||||
[
|
||||
new MatchmakingPool { Id = 0, RulesetId = 0, Name = "osu!" },
|
||||
new MatchmakingPool { Id = 1, RulesetId = 1, Name = "osu!taiko" },
|
||||
new MatchmakingPool { Id = 2, RulesetId = 2, Name = "osu!catch" },
|
||||
new MatchmakingPool { Id = 3, RulesetId = 3, Variant = 4, Name = "osu!mania (4k)" },
|
||||
new MatchmakingPool { Id = 4, RulesetId = 3, Variant = 7, Name = "osu!mania (7k)" },
|
||||
new MatchmakingPool { Id = 0, RulesetId = 0, Name = "Free-for-all" },
|
||||
new MatchmakingPool { Id = 1, RulesetId = 1, Name = "1v1" },
|
||||
new MatchmakingPool { Id = 2, RulesetId = 2, Name = "1v1" },
|
||||
new MatchmakingPool { Id = 3, RulesetId = 3, Variant = 4, Name = "1v1" },
|
||||
new MatchmakingPool { Id = 4, RulesetId = 3, Variant = 7, Name = "1v1" },
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("load screen", () => LoadScreen(new IntroScreen()));
|
||||
AddStep("load screen", () => LoadScreen(new ScreenIntro()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -110,6 +110,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
|
||||
state.CandidateItems = beatmaps.Select(b => b.ID).ToArray();
|
||||
state.CandidateItem = beatmaps[0].ID;
|
||||
state.GameplayItem = beatmaps[0].ID;
|
||||
}, waitTime: 35);
|
||||
|
||||
changeStage(MatchmakingStage.WaitingForClientsBeatmapDownload);
|
||||
@@ -124,11 +125,11 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
|
||||
foreach (var user in MultiplayerClient.ServerRoom!.Users.OrderBy(_ => RNG.Next()))
|
||||
{
|
||||
state.Users[user.UserID].Placement = i++;
|
||||
state.Users[user.UserID].Points = (8 - i) * 7;
|
||||
state.Users[user.UserID].Rounds[1].Placement = 1;
|
||||
state.Users[user.UserID].Rounds[1].TotalScore = 1;
|
||||
state.Users[user.UserID].Rounds[1].Statistics[HitResult.LargeBonus] = 1;
|
||||
state.Users.GetOrAdd(user.UserID).Placement = i++;
|
||||
state.Users.GetOrAdd(user.UserID).Points = (8 - i) * 7;
|
||||
state.Users.GetOrAdd(user.UserID).Rounds.GetOrAdd(1).Placement = 1;
|
||||
state.Users.GetOrAdd(user.UserID).Rounds.GetOrAdd(1).TotalScore = 1;
|
||||
state.Users.GetOrAdd(user.UserID).Rounds.GetOrAdd(1).Statistics[HitResult.LargeBonus] = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match.Results;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestScenePanelRoomAward : MultiplayerTestScene
|
||||
public partial class TestScenePanelRoomAward : MatchmakingTestScene
|
||||
{
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
|
||||
@@ -6,16 +6,16 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match.BeatmapSelect;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestScenePickScreen : MultiplayerTestScene
|
||||
public partial class TestScenePickScreen : MatchmakingTestScene
|
||||
{
|
||||
private readonly IReadOnlyList<APIUser> users = new[]
|
||||
{
|
||||
@@ -104,8 +104,28 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
long[] candidateItems = selectedItems.ToArray();
|
||||
long finalItem = candidateItems[Random.Shared.Next(candidateItems.Length)];
|
||||
|
||||
screen.RollFinalBeatmap(candidateItems, finalItem);
|
||||
screen.RollFinalBeatmap(candidateItems, finalItem, finalItem);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExpiredBeatmapNotShown()
|
||||
{
|
||||
SubScreenBeatmapSelect screen = null!;
|
||||
|
||||
AddStep("add screen with expired items", () =>
|
||||
{
|
||||
MultiplayerClient.ClientRoom!.Playlist =
|
||||
[
|
||||
new MultiplayerPlaylistItem(items[0]) { Expired = true },
|
||||
new MultiplayerPlaylistItem(items[1])
|
||||
];
|
||||
|
||||
Child = new ScreenStack(screen = new SubScreenBeatmapSelect());
|
||||
});
|
||||
|
||||
AddUntilStep("items displayed", () => screen.ChildrenOfType<MatchmakingSelectPanelBeatmap>().Any());
|
||||
AddAssert("expired item not shown", () => screen.ChildrenOfType<MatchmakingSelectPanelBeatmap>().Count(), () => Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,11 @@ using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.Matchmaking;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestScenePlayerPanel : MultiplayerTestScene
|
||||
public partial class TestScenePlayerPanel : MatchmakingTestScene
|
||||
{
|
||||
private PlayerPanel panel = null!;
|
||||
|
||||
@@ -27,7 +26,13 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.Matchmaking)));
|
||||
WaitForJoined();
|
||||
|
||||
AddStep("add panel", () => Child = panel = new PlayerPanel(new MultiplayerRoomUser(1)
|
||||
AddStep("join other player to room", () => MultiplayerClient.AddUser(new APIUser
|
||||
{
|
||||
Id = 2,
|
||||
Username = "peppy",
|
||||
}));
|
||||
|
||||
AddStep("add panel", () => Child = panel = new PlayerPanel(new MultiplayerRoomUser(2)
|
||||
{
|
||||
User = new APIUser
|
||||
{
|
||||
@@ -85,9 +90,9 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
UserDictionary =
|
||||
{
|
||||
{
|
||||
1, new MatchmakingUser
|
||||
2, new MatchmakingUser
|
||||
{
|
||||
UserId = 1,
|
||||
UserId = 2,
|
||||
Placement = 1,
|
||||
Points = ++points
|
||||
}
|
||||
@@ -100,7 +105,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
[Test]
|
||||
public void TestJump()
|
||||
{
|
||||
AddStep("jump", () => MultiplayerClient.SendUserMatchRequest(1, new MatchmakingAvatarActionRequest { Action = MatchmakingAvatarAction.Jump }).WaitSafely());
|
||||
AddStep("jump", () => MultiplayerClient.SendUserMatchRequest(2, new MatchmakingAvatarActionRequest { Action = MatchmakingAvatarAction.Jump }).WaitSafely());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -108,5 +113,14 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
AddToggleStep("toggle quit", quit => panel.HasQuit = quit);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDownloadProgress()
|
||||
{
|
||||
AddStep("set download progress 20%", () => MultiplayerClient.ChangeUserBeatmapAvailability(2, BeatmapAvailability.Downloading(0.2f)));
|
||||
AddStep("set download progress 50%", () => MultiplayerClient.ChangeUserBeatmapAvailability(2, BeatmapAvailability.Downloading(0.5f)));
|
||||
AddStep("set download progress 90%", () => MultiplayerClient.ChangeUserBeatmapAvailability(2, BeatmapAvailability.Downloading(0.9f)));
|
||||
AddStep("set locally available", () => MultiplayerClient.ChangeUserBeatmapAvailability(2, BeatmapAvailability.LocallyAvailable()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,17 +8,18 @@ using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Matchmaking.Events;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.Matchmaking;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestScenePlayerPanelOverlay : MultiplayerTestScene
|
||||
public partial class TestScenePlayerPanelOverlay : MatchmakingTestScene
|
||||
{
|
||||
private PlayerPanelOverlay list = null!;
|
||||
|
||||
@@ -153,10 +154,69 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
MatchmakingRoomState state = new MatchmakingRoomState();
|
||||
|
||||
for (int i = 0; i < room.Users.Count; i++)
|
||||
state.Users[room.Users[i].UserID].Placement = placements[i];
|
||||
state.Users.GetOrAdd(room.Users[i].UserID).Placement = placements[i];
|
||||
|
||||
MultiplayerClient.ChangeMatchRoomState(state).WaitSafely();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InteractionSpam()
|
||||
{
|
||||
AddStep("join users", () =>
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
MultiplayerClient.AddUser(new MultiplayerRoomUser(i)
|
||||
{
|
||||
User = new APIUser
|
||||
{
|
||||
Username = $"User {i}"
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
AddStep("change to grid mode", () => list.DisplayStyle = PanelDisplayStyle.Grid);
|
||||
AddStep("player jump", () => { MultiplayerClient.SendUserMatchRequest(1001, new MatchmakingAvatarActionRequest { Action = MatchmakingAvatarAction.Jump }).WaitSafely(); });
|
||||
AddStep("local jumping", () => jumpSpam(false));
|
||||
AddWaitStep("wait", 25);
|
||||
AddStep("group jumping spam", () => jumpSpam(true));
|
||||
AddWaitStep("wait", 25);
|
||||
|
||||
AddStep("change to split mode", () => list.DisplayStyle = PanelDisplayStyle.Split);
|
||||
AddStep("local jumping", () => jumpSpam(false));
|
||||
AddWaitStep("wait", 25);
|
||||
AddStep("group jumping spam", () => jumpSpam(true));
|
||||
AddWaitStep("wait", 25);
|
||||
|
||||
AddStep("change to hidden mode", () => list.DisplayStyle = PanelDisplayStyle.Hidden);
|
||||
AddStep("local jumping", () => jumpSpam(false));
|
||||
AddWaitStep("wait", 25);
|
||||
AddStep("group jumping spam", () => jumpSpam(true));
|
||||
AddWaitStep("wait", 25);
|
||||
}
|
||||
|
||||
private void jumpSpam(bool everyone)
|
||||
{
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
Scheduler.AddDelayed(() =>
|
||||
{
|
||||
MultiplayerClient.SendUserMatchRequest(1001, new MatchmakingAvatarActionRequest { Action = MatchmakingAvatarAction.Jump }).WaitSafely();
|
||||
}, i * 150 + RNG.NextDouble(0, 140));
|
||||
|
||||
if (!everyone)
|
||||
continue;
|
||||
|
||||
for (int ii = 0; ii < 7; ii++)
|
||||
{
|
||||
int iii = ii;
|
||||
Scheduler.AddDelayed(() =>
|
||||
{
|
||||
MultiplayerClient.SendUserMatchRequest(iii, new MatchmakingAvatarActionRequest { Action = MatchmakingAvatarAction.Jump }).WaitSafely();
|
||||
}, i * 150 + RNG.NextDouble(0, 140));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,11 @@ using osu.Game.Online.Multiplayer.MatchTypes.Matchmaking;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match.Results;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestSceneResultsScreen : MultiplayerTestScene
|
||||
public partial class TestSceneResultsScreen : MatchmakingTestScene
|
||||
{
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
@@ -36,28 +35,28 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
int localUserId = API.LocalUser.Value.OnlineID;
|
||||
|
||||
// Overall state.
|
||||
state.Users[localUserId].Placement = 1;
|
||||
state.Users[localUserId].Points = 8;
|
||||
state.Users.GetOrAdd(localUserId).Placement = 1;
|
||||
state.Users.GetOrAdd(localUserId).Points = 8;
|
||||
for (int round = 1; round <= state.CurrentRound; round++)
|
||||
state.Users[localUserId].Rounds[round].Placement = round;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(round).Placement = round;
|
||||
|
||||
// Highest score.
|
||||
state.Users[localUserId].Rounds[1].TotalScore = 1000;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(1).TotalScore = 1000;
|
||||
|
||||
// Highest accuracy.
|
||||
state.Users[localUserId].Rounds[2].Accuracy = 0.9995;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(2).Accuracy = 0.9995;
|
||||
|
||||
// Highest combo.
|
||||
state.Users[localUserId].Rounds[3].MaxCombo = 100;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(3).MaxCombo = 100;
|
||||
|
||||
// Most bonus score.
|
||||
state.Users[localUserId].Rounds[4].Statistics[HitResult.LargeBonus] = 50;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(4).Statistics[HitResult.LargeBonus] = 50;
|
||||
|
||||
// Smallest score difference.
|
||||
state.Users[localUserId].Rounds[5].TotalScore = 1000;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(5).TotalScore = 1000;
|
||||
|
||||
// Largest score difference.
|
||||
state.Users[localUserId].Rounds[6].TotalScore = 1000;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(6).TotalScore = 1000;
|
||||
|
||||
MultiplayerClient.ChangeMatchRoomState(state).WaitSafely();
|
||||
});
|
||||
@@ -103,36 +102,78 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
int localUserId = API.LocalUser.Value.OnlineID;
|
||||
|
||||
// Overall state.
|
||||
state.Users[localUserId].Placement = 1;
|
||||
state.Users[localUserId].Points = 8;
|
||||
state.Users[invalid_user_id].Placement = 2;
|
||||
state.Users[invalid_user_id].Points = 7;
|
||||
state.Users.GetOrAdd(localUserId).Placement = 1;
|
||||
state.Users.GetOrAdd(localUserId).Points = 8;
|
||||
state.Users.GetOrAdd(invalid_user_id).Placement = 2;
|
||||
state.Users.GetOrAdd(invalid_user_id).Points = 7;
|
||||
for (int round = 1; round <= state.CurrentRound; round++)
|
||||
state.Users[localUserId].Rounds[round].Placement = round;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(round).Placement = round;
|
||||
|
||||
// Highest score.
|
||||
state.Users[localUserId].Rounds[1].TotalScore = 1000;
|
||||
state.Users[invalid_user_id].Rounds[1].TotalScore = 990;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(1).TotalScore = 1000;
|
||||
state.Users.GetOrAdd(invalid_user_id).Rounds.GetOrAdd(1).TotalScore = 990;
|
||||
|
||||
// Highest accuracy.
|
||||
state.Users[localUserId].Rounds[2].Accuracy = 0.9995;
|
||||
state.Users[invalid_user_id].Rounds[2].Accuracy = 0.5;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(2).Accuracy = 0.9995;
|
||||
state.Users.GetOrAdd(invalid_user_id).Rounds.GetOrAdd(2).Accuracy = 0.5;
|
||||
|
||||
// Highest combo.
|
||||
state.Users[localUserId].Rounds[3].MaxCombo = 100;
|
||||
state.Users[invalid_user_id].Rounds[3].MaxCombo = 10;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(3).MaxCombo = 100;
|
||||
state.Users.GetOrAdd(invalid_user_id).Rounds.GetOrAdd(3).MaxCombo = 10;
|
||||
|
||||
// Most bonus score.
|
||||
state.Users[localUserId].Rounds[4].Statistics[HitResult.LargeBonus] = 50;
|
||||
state.Users[invalid_user_id].Rounds[4].Statistics[HitResult.LargeBonus] = 25;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(4).Statistics[HitResult.LargeBonus] = 50;
|
||||
state.Users.GetOrAdd(invalid_user_id).Rounds.GetOrAdd(4).Statistics[HitResult.LargeBonus] = 25;
|
||||
|
||||
// Smallest score difference.
|
||||
state.Users[localUserId].Rounds[5].TotalScore = 1000;
|
||||
state.Users[invalid_user_id].Rounds[5].TotalScore = 999;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(5).TotalScore = 1000;
|
||||
state.Users.GetOrAdd(invalid_user_id).Rounds.GetOrAdd(5).TotalScore = 999;
|
||||
|
||||
// Largest score difference.
|
||||
state.Users[localUserId].Rounds[6].TotalScore = 1000;
|
||||
state.Users[invalid_user_id].Rounds[6].TotalScore = 0;
|
||||
state.Users.GetOrAdd(localUserId).Rounds.GetOrAdd(6).TotalScore = 1000;
|
||||
state.Users.GetOrAdd(invalid_user_id).Rounds.GetOrAdd(6).TotalScore = 0;
|
||||
|
||||
MultiplayerClient.ChangeMatchRoomState(state).WaitSafely();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoUsers()
|
||||
{
|
||||
AddStep("show results with no users", () =>
|
||||
{
|
||||
var state = new MatchmakingRoomState
|
||||
{
|
||||
CurrentRound = 6,
|
||||
Stage = MatchmakingStage.Ended
|
||||
};
|
||||
|
||||
MultiplayerClient.ChangeMatchRoomState(state).WaitSafely();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserWithNoScore()
|
||||
{
|
||||
AddStep("join another user", () => MultiplayerClient.AddUser(new MultiplayerRoomUser(2)
|
||||
{
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 2,
|
||||
Username = "Other user"
|
||||
}
|
||||
}));
|
||||
|
||||
AddStep("show results with no score", () =>
|
||||
{
|
||||
var state = new MatchmakingRoomState
|
||||
{
|
||||
CurrentRound = 6,
|
||||
Stage = MatchmakingStage.Ended
|
||||
};
|
||||
|
||||
state.Users.GetOrAdd(API.LocalUser.Value.OnlineID).Rounds.GetOrAdd(1).Placement = 1;
|
||||
state.Users.GetOrAdd(2);
|
||||
|
||||
MultiplayerClient.ChangeMatchRoomState(state).WaitSafely();
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Utils;
|
||||
@@ -14,12 +15,11 @@ using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Match.RoundResults;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
public partial class TestSceneRoundResultsScreen : MultiplayerTestScene
|
||||
public partial class TestSceneRoundResultsScreen : MatchmakingTestScene
|
||||
{
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
@@ -27,8 +27,15 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.Matchmaking)));
|
||||
WaitForJoined();
|
||||
}
|
||||
|
||||
setupRequestHandler();
|
||||
[TestCase(2)]
|
||||
[TestCase(4)]
|
||||
[TestCase(8)]
|
||||
[TestCase(16)]
|
||||
public void TestDisplayScores(int scoreCount)
|
||||
{
|
||||
setupRequestHandler(scoreCount);
|
||||
|
||||
AddStep("load screen", () =>
|
||||
{
|
||||
@@ -41,7 +48,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
});
|
||||
}
|
||||
|
||||
private void setupRequestHandler()
|
||||
private void setupRequestHandler(int scoreCount)
|
||||
{
|
||||
AddStep("setup request handler", () =>
|
||||
{
|
||||
@@ -72,7 +79,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
case IndexPlaylistScoresRequest index:
|
||||
var result = new IndexedMultiplayerScores();
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
for (int i = 0; i < scoreCount; ++i)
|
||||
{
|
||||
result.Scores.Add(new MultiplayerScore
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user