Compare commits
161 Commits
fb7ccba4ba
...
testing
| Author | SHA1 | Date | |
|---|---|---|---|
| de58aec23e | |||
|
|
734c6f933d | ||
|
|
ac213c90cb | ||
|
|
74ca87c252 | ||
|
|
032912e62b | ||
|
|
1e79c56240 | ||
| 86f0159e65 | |||
| ae5a64ba81 | |||
|
|
82256ae2de | ||
|
|
1142be45ec | ||
|
|
dcb6d71287 | ||
|
|
881a35b382 | ||
|
|
89d8b402af | ||
|
|
1d351002df | ||
| e3a7ae30cd | |||
| b6f845d99c | |||
|
|
2606f3a0b5 | ||
|
|
1c463aa060 | ||
|
|
7853abe8aa | ||
|
|
1aff418981 | ||
|
|
62e92bb242 | ||
|
|
79151ae5b4 | ||
| a1d6bda63e | |||
| 547d22a4b5 | |||
|
|
c17db2cdd0 | ||
|
|
bbdd70c843 | ||
|
|
4250a54245 | ||
|
|
40fdb8662e | ||
|
|
6ce8b0a4bc | ||
|
|
b30047def6 | ||
|
|
0ffb86262f | ||
|
|
f71eb4b980 | ||
|
|
1faf02e860 | ||
|
|
d700375e55 | ||
|
|
095a67c24e | ||
|
|
86054497d0 | ||
|
|
c4f7dee82b | ||
|
|
22825f6509 | ||
|
|
691e8bcd05 | ||
|
|
e68bab4f4b | ||
|
|
9430a62af4 | ||
| b4c530ac04 | |||
| 5af05d2479 | |||
| 43ab18ffea | |||
| 9f59259a40 | |||
| 82b3015fcc | |||
| 68f92ab57c | |||
| d76d4d9a35 | |||
|
|
bb7417c099 | ||
|
|
066e093987 | ||
|
|
56e0c3e65d | ||
|
|
89d7726903 | ||
|
|
36f1bfef07 | ||
|
|
118f07878a | ||
|
|
e144968893 | ||
|
|
d2ffea41c6 | ||
|
|
a8be9b1381 | ||
|
|
bdac75e542 | ||
|
|
5c2df50714 | ||
|
|
887d280bfa | ||
|
|
84db289779 | ||
|
|
4c0522b795 | ||
|
|
07ea9fe2a4 | ||
| 490a6fd724 | |||
|
|
f73307876e | ||
|
|
4e4aa44a02 | ||
| 237e1828f8 | |||
| 3413f722f7 | |||
| 9f779dac03 | |||
| 0727c53cdc | |||
| a57ff24191 | |||
|
|
a6c001244f | ||
|
|
107098314a | ||
|
|
d1d76a76ba | ||
|
|
2a7e71d7fd | ||
| bdb3418b67 | |||
|
|
0b4f96efc8 | ||
|
|
78c6973298 | ||
|
|
d8d7c80832 | ||
|
|
ae33690632 | ||
|
|
9e2ea63e70 | ||
|
|
79bfe7880a | ||
| 936640edeb | |||
| 1187d03333 | |||
| 3bd996ee43 | |||
| 37b9f91d42 | |||
| 1a5a5606dc | |||
| 87ff1051e9 | |||
|
|
80fbcd5fbd | ||
|
|
9c2319b989 | ||
|
|
a040143825 | ||
| 2e4b0ff197 | |||
| 499f410c94 | |||
| 616c0d8ecd | |||
| ed889138a0 | |||
| 18075bef29 | |||
| bc7780a870 | |||
| 8930b8fadb | |||
| 2d457f4305 | |||
| a784734f94 | |||
| ecfd4764e7 | |||
| f5ca5083d6 | |||
| 1d7c77d8d6 | |||
| 774e52fbd6 | |||
| a9d7a9d5d5 | |||
| f7069b1009 | |||
| c3ce5dc787 | |||
| 98076e2092 | |||
| b7d1092f90 | |||
| 08db90c278 | |||
| b7e36164c3 | |||
| 0f5f13858d | |||
| 89a0c75156 | |||
| ab7e5c94f1 | |||
| 8dc9ea4553 | |||
| dcf553c252 | |||
| 43f3a506ea | |||
| ab51579c27 | |||
| d8e977c05f | |||
| c023767df9 | |||
|
|
1867aad1a6 | ||
|
|
b1bc5cae87 | ||
| d47e26f1ae | |||
| b0e5ae1109 | |||
| 47b859ab17 | |||
| 5e523eb0b1 | |||
|
|
d912f8c3b9 | ||
| 65f275106e | |||
| 6e374762fd | |||
| 80646a166c | |||
| 8f0510d903 | |||
| 02e7000ee4 | |||
| 081355864e | |||
| 6435a835d1 | |||
|
|
038bf3fdda | ||
|
|
61c3aad537 | ||
|
|
3aad0868af | ||
|
|
973c4c8319 | ||
|
|
ac21f8b960 | ||
| 628181a883 | |||
| 835329efd3 | |||
| 5399943118 | |||
| d07f82f6f4 | |||
| 5b186bb740 | |||
| 6cb99c13c2 | |||
| 96008e06ab | |||
| 590b0a8028 | |||
| 70f7f09a83 | |||
| 490137405f | |||
| f3c6f53f70 | |||
| 8cb5c682b4 | |||
| c3d79295d3 | |||
| f31d310135 | |||
| 26029de27d | |||
| c37f72f567 | |||
|
|
0b3b6468a5 | ||
|
|
7d1c54f045 | ||
|
|
fd504e5641 | ||
|
|
93ed0483b6 | ||
|
|
4dd0672aa5 | ||
|
|
66eff14d2b |
@@ -21,7 +21,7 @@
|
||||
]
|
||||
},
|
||||
"ppy.localisationanalyser.tools": {
|
||||
"version": "2024.802.0",
|
||||
"version": "2025.1208.0",
|
||||
"commands": [
|
||||
"localisation"
|
||||
]
|
||||
|
||||
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
@@ -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
@@ -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
@@ -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 }}
|
||||
|
||||
3
.gitignore
vendored
@@ -19,6 +19,7 @@ bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Pp]ub/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
@@ -343,4 +344,4 @@ inspectcode
|
||||
FodyWeavers.xsd
|
||||
|
||||
.idea/.idea.osu.Desktop/.idea/misc.xml
|
||||
.idea/.idea.osu.Android/.idea/deploymentTargetDropDown.xml
|
||||
.idea/.idea.osu.Android/.idea/deploymentTargetDropDown.xml
|
||||
36
.vscode/launch.json
vendored
@@ -7,9 +7,9 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/net8.0/osu!.dll"
|
||||
"${workspaceFolder}/osu.Desktop/bin/Debug/net8.0/osu!.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
@@ -19,9 +19,9 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Release/net8.0/osu!.dll"
|
||||
"${workspaceFolder}/osu.Desktop/bin/Release/net8.0/osu!.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
@@ -31,9 +31,9 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/net8.0/osu.Game.Tests.dll"
|
||||
"${workspaceFolder}/osu.Game.Tests/bin/Debug/net8.0/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build tests (Debug)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
@@ -43,9 +43,9 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Release/net8.0/osu.Game.Tests.dll"
|
||||
"${workspaceFolder}/osu.Game.Tests/bin/Release/net8.0/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build tests (Release)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
@@ -55,10 +55,10 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/net8.0/osu!.dll",
|
||||
"${workspaceFolder}/osu.Desktop/bin/Debug/net8.0/osu!.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
@@ -68,10 +68,10 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Release/net8.0/osu!.dll",
|
||||
"${workspaceFolder}/osu.Desktop/bin/Release/net8.0/osu!.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
@@ -81,10 +81,10 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll",
|
||||
"${workspaceFolder}/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build tournament tests (Debug)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
@@ -94,10 +94,10 @@
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll",
|
||||
"${workspaceFolder}/osu.Game.Tournament.Tests/bin/Debug/net8.0/osu.Game.Tournament.Tests.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build tournament tests (Release)",
|
||||
"console": "internalConsole"
|
||||
},
|
||||
@@ -105,12 +105,12 @@
|
||||
"name": "Benchmark",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/osu.Game.Benchmarks/bin/Release/net8.0/osu.Game.Benchmarks.dll",
|
||||
"program": "${workspaceFolder}/osu.Game.Benchmarks/bin/Release/net8.0/osu.Game.Benchmarks.dll",
|
||||
"args": [
|
||||
"--filter",
|
||||
"*"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"preLaunchTask": "Build benchmarks",
|
||||
"console": "internalConsole"
|
||||
}
|
||||
|
||||
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"dotnet.defaultSolution": "osu.Desktop.slnf"
|
||||
}
|
||||
@@ -49,7 +49,7 @@
|
||||
<PackageProjectUrl>https://github.com/ppy/osu</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/ppy/osu</RepositoryUrl>
|
||||
<PackageReleaseNotes>Automated release.</PackageReleaseNotes>
|
||||
<Company>ppy Pty Ltd</Company>
|
||||
<Company>ppy Pty Ltd, jvnkosu! team</Company>
|
||||
<Copyright>Copyright (c) 2025 ppy Pty Ltd</Copyright>
|
||||
<PackageTags>osu game</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
19
MakeInstaller.ps1
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env powershell
|
||||
param (
|
||||
[string]$Version,
|
||||
[string]$BuildConfig = "Release"
|
||||
)
|
||||
|
||||
if ($Version -eq "") {
|
||||
Write-Host "Usage: .\MakeInstaller.ps1 <VERSION_NUMBER> [-BuildConfig <BUILD_CONFIG>]"
|
||||
Write-Host "Example: .\MakeInstaller.ps1 2025.823.0 -BuildConfig Debug"
|
||||
exit
|
||||
}
|
||||
|
||||
$tmpPub = ".\pub"
|
||||
if (-not (Test-Path -Path $tmpPub)) {
|
||||
New-Item -ItemType Directory -path $tmpPub
|
||||
}
|
||||
|
||||
dotnet publish -c $BuildConfig osu.Desktop --self-contained -r win-x64 -o $tmpPub -verbosity:m /p:Version=$Version
|
||||
vpk pack --packId jvnkosu.Client --packTitle "jvnkosu!lazer" --packVersion $Version --packDir ./pub --mainExe="osu!.exe"
|
||||
149
README.md
@@ -1,147 +1,40 @@
|
||||
<p align="center">
|
||||
<img width="500" alt="osu! logo" src="assets/lazer.png">
|
||||
</p>
|
||||
# jvnkosu! client
|
||||
|
||||
# osu!
|
||||
A free-to-win rhythm game based on osu!(lazer). Click is just a *rhythm* away!
|
||||
|
||||
[](https://github.com/ppy/osu/actions/workflows/ci.yml)
|
||||
[](https://github.com/ppy/osu/releases/latest)
|
||||
[](https://www.codefactor.io/repository/github/ppy/osu)
|
||||
[](https://discord.gg/ppy)
|
||||
[](https://crowdin.com/project/osu-web)
|
||||
## Disclaimer
|
||||
|
||||
A free-to-win rhythm game. Rhythm is just a *click* away!
|
||||
*osu!* is a registered trademark of ppy Pty Ltd.
|
||||
jvnkosu! is not affiliated with, or endorsed by ppy Pty Ltd., but makes use of its open-source components and resources.
|
||||
|
||||
This is the future – and final – iteration of the [osu!](https://osu.ppy.sh) game client which marks the beginning of an open era! Currently known by and released under the release codename "*lazer*". As in sharper than cutting-edge.
|
||||
## License
|
||||
Client source code is licensed under the MIT license, see the [LICENCE](LICENCE) file in repository root for more info.
|
||||
|
||||
## Status
|
||||
Game assets are included as a NuGet package and licensed under the CC BY-NC 4.0, which prohibits commercial use. See [ppy/osu-resources](https://github.com/ppy/osu-resources) for more info.
|
||||
|
||||
This project is under constant development, but we do our best to keep things in a stable state. Players are encouraged to install from a release alongside their stable *osu!* client. This project will continue to evolve until we eventually reach the point where most users prefer it over the previous "osu!stable" release.
|
||||
Registered trademarks "osu!" and "ppy" are property of ppy Pty Ltd., and protected by trademark law.
|
||||
|
||||
A few resources are available as starting points to getting involved and understanding the project:
|
||||
## Compiling from source
|
||||
Building jvnkosu! from source is pretty much possible (and welcome here).
|
||||
|
||||
- Detailed release changelogs are available on the [official osu! site](https://osu.ppy.sh/home/changelog/lazer).
|
||||
- You can learn more about our approach to [project management](https://github.com/ppy/osu/wiki/Project-management).
|
||||
- Track our current efforts [towards improving the game](https://github.com/orgs/ppy/projects/7/views/6).
|
||||
First, you must have a desktop platform with [.NET Core SDK 8](https://dotnet.microsoft.com/download) installed. Windows, Linux, macOS should work well. You can check if you have the SDK installed by running `dotnet --version` in your command prompt/terminal.
|
||||
|
||||
## Running osu!
|
||||
|
||||
If you are just looking to give the game a whirl, you can grab the latest release for your platform:
|
||||
|
||||
### Latest release:
|
||||
|
||||
| [Windows 10+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 12+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) |
|
||||
|--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------- | ------------- | ------------- |
|
||||
|
||||
You can also generally download a version for your current device from the [osu! site](https://osu.ppy.sh/home/download).
|
||||
|
||||
If your platform is unsupported or not listed above, there is still a chance you can run the release or manually build it by following the instructions below.
|
||||
|
||||
**For iOS/iPadOS users**: The iOS testflight link fills up very fast (Apple has a hard limit of 10,000 users). We reset it occasionally. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements. Our goal is to get the game on mobile app stores very soon so we don't have to live with this limitation.
|
||||
|
||||
## Developing a custom ruleset
|
||||
|
||||
osu! is designed to allow user-created gameplay variations, called "rulesets". Building one of these allows a developer to harness the power of the osu! beatmap library, game engine, and general UX for a new style of gameplay. To get started working on a ruleset, we have some templates available [here](https://github.com/ppy/osu/tree/master/Templates).
|
||||
|
||||
You can see some examples of custom rulesets by visiting the [custom ruleset directory](https://github.com/ppy/osu/discussions/13096).
|
||||
|
||||
## Developing osu!
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Please make sure you have the following prerequisites:
|
||||
|
||||
- A desktop platform with the [.NET 8.0 SDK](https://dotnet.microsoft.com/download) installed.
|
||||
|
||||
When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as the latest version of [Visual Studio](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/), or [Visual Studio Code](https://code.visualstudio.com/) with the [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) and [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) plugin installed.
|
||||
|
||||
### Downloading the source code
|
||||
|
||||
Clone the repository:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/ppy/osu
|
||||
cd osu
|
||||
Then, download the source code. You may download it as an archive and unzip it, but using [Git](https://git-scm.com/) instead is recommended:
|
||||
```
|
||||
git clone https://gitea.jvnko.boats/jvnkosu/client
|
||||
```
|
||||
|
||||
To update the source code to the latest commit, run the following command inside the `osu` directory:
|
||||
|
||||
```shell
|
||||
git pull
|
||||
To **run** the project, switch to project's directory and run the following:
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
#### From an IDE
|
||||
|
||||
You should load the solution via one of the platform-specific `.slnf` files, rather than the main `.sln`. This will reduce dependencies and hide platforms that you don't care about. Valid `.slnf` files are:
|
||||
|
||||
- `osu.Desktop.slnf` (most common)
|
||||
- `osu.Android.slnf`
|
||||
- `osu.iOS.slnf`
|
||||
|
||||
Run configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `osu! (Tests)` project/configuration. More information on this is provided [below](#contributing).
|
||||
|
||||
To build for mobile platforms, you will likely need to run `sudo dotnet workload restore` if you haven't done so previously. This will install Android/iOS tooling required to complete the build.
|
||||
|
||||
#### From CLI
|
||||
|
||||
You can also build and run *osu!* from the command-line with a single command:
|
||||
|
||||
```shell
|
||||
dotnet run --project osu.Desktop
|
||||
```
|
||||
|
||||
When running locally to do any kind of performance testing, make sure to add `-c Release` to the build command, as the overhead of running with the default `Debug` configuration can be large (especially when testing with local framework modifications as below).
|
||||
|
||||
If the build fails, try to restore NuGet packages with `dotnet restore`.
|
||||
|
||||
### Testing with resource/framework modifications
|
||||
|
||||
Sometimes it may be necessary to cross-test changes in [osu-resources](https://github.com/ppy/osu-resources) or [osu-framework](https://github.com/ppy/osu-framework). This can be quickly achieved using included commands:
|
||||
|
||||
Windows:
|
||||
|
||||
```ps
|
||||
UseLocalFramework.ps1
|
||||
UseLocalResources.ps1
|
||||
To **compile**:
|
||||
```
|
||||
dotnet build osu.Desktop
|
||||
```
|
||||
|
||||
macOS / Linux:
|
||||
To reduce performance overhead in custom builds, it's recommended to build with the `-c Release` flag, that will use the release profile and remove possibly unneeded debugging code.
|
||||
|
||||
```ps
|
||||
UseLocalFramework.sh
|
||||
UseLocalResources.sh
|
||||
```
|
||||
|
||||
Note that these commands assume you have the relevant project(s) checked out in adjacent directories:
|
||||
|
||||
```
|
||||
|- osu // this repository
|
||||
|- osu-framework
|
||||
|- osu-resources
|
||||
```
|
||||
|
||||
### Code analysis
|
||||
|
||||
Before committing your code, please run a code formatter. This can be achieved by running `dotnet format` in the command line, or using the `Format code` command in your IDE.
|
||||
|
||||
We have adopted some cross-platform, compiler integrated analyzers. They can provide warnings when you are editing, building inside IDE or from command line, as-if they are provided by the compiler itself.
|
||||
|
||||
JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it from PowerShell with `.\InspectCode.ps1`. Alternatively, you can install ReSharper or use Rider to get inline support in your IDE of choice.
|
||||
|
||||
## Contributing
|
||||
|
||||
When it comes to contributing to the project, the two main things you can do to help out are reporting issues and submitting pull requests. Please refer to the [contributing guidelines](CONTRIBUTING.md) to understand how to help in the most effective way possible.
|
||||
|
||||
If you wish to help with localisation efforts, head over to [crowdin](https://crowdin.com/project/osu-web).
|
||||
|
||||
We love to reward quality contributions. If you have made a large contribution, or are a regular contributor, you are welcome to [submit an expense via opencollective](https://opencollective.com/ppy/expenses/new). If you have any questions, feel free to [reach out to peppy](mailto:pe@ppy.sh) before doing so.
|
||||
|
||||
## Licence
|
||||
|
||||
*osu!*'s code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source.
|
||||
|
||||
Please note that this *does not cover* the usage of the "osu!" or "ppy" branding in any software, resources, advertising or promotion, as this is protected by trademark law.
|
||||
|
||||
Please also note that game resources are covered by a separate licence. Please see the [ppy/osu-resources](https://github.com/ppy/osu-resources) repository for clarifications.
|
||||
### See the [original readme](README.original.md) for more info.
|
||||
147
README.original.md
Normal file
@@ -0,0 +1,147 @@
|
||||
<p align="center">
|
||||
<img width="500" alt="osu! logo" src="assets/lazer.png">
|
||||
</p>
|
||||
|
||||
# osu!
|
||||
|
||||
[](https://github.com/ppy/osu/actions/workflows/ci.yml)
|
||||
[](https://github.com/ppy/osu/releases/latest)
|
||||
[](https://www.codefactor.io/repository/github/ppy/osu)
|
||||
[](https://discord.gg/ppy)
|
||||
[](https://crowdin.com/project/osu-web)
|
||||
|
||||
A free-to-win rhythm game. Rhythm is just a *click* away!
|
||||
|
||||
This is the future – and final – iteration of the [osu!](https://osu.ppy.sh) game client which marks the beginning of an open era! Currently known by and released under the release codename "*lazer*". As in sharper than cutting-edge.
|
||||
|
||||
## Status
|
||||
|
||||
This project is under constant development, but we do our best to keep things in a stable state. Players are encouraged to install from a release alongside their stable *osu!* client. This project will continue to evolve until we eventually reach the point where most users prefer it over the previous "osu!stable" release.
|
||||
|
||||
A few resources are available as starting points to getting involved and understanding the project:
|
||||
|
||||
- Detailed release changelogs are available on the [official osu! site](https://osu.ppy.sh/home/changelog/lazer).
|
||||
- You can learn more about our approach to [project management](https://github.com/ppy/osu/wiki/Project-management).
|
||||
- Track our current efforts [towards improving the game](https://github.com/orgs/ppy/projects/7/views/6).
|
||||
|
||||
## Running osu!
|
||||
|
||||
If you are just looking to give the game a whirl, you can grab the latest release for your platform:
|
||||
|
||||
### Latest release:
|
||||
|
||||
| [Windows 10+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 12+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) |
|
||||
|--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ------------- | ------------- | ------------- |
|
||||
|
||||
You can also generally download a version for your current device from the [osu! site](https://osu.ppy.sh/home/download).
|
||||
|
||||
If your platform is unsupported or not listed above, there is still a chance you can run the release or manually build it by following the instructions below.
|
||||
|
||||
**For iOS/iPadOS users**: The iOS testflight link fills up very fast (Apple has a hard limit of 10,000 users). We reset it occasionally. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements. Our goal is to get the game on mobile app stores very soon so we don't have to live with this limitation.
|
||||
|
||||
## Developing a custom ruleset
|
||||
|
||||
osu! is designed to allow user-created gameplay variations, called "rulesets". Building one of these allows a developer to harness the power of the osu! beatmap library, game engine, and general UX for a new style of gameplay. To get started working on a ruleset, we have some templates available [here](https://github.com/ppy/osu/tree/master/Templates).
|
||||
|
||||
You can see some examples of custom rulesets by visiting the [custom ruleset directory](https://github.com/ppy/osu/discussions/13096).
|
||||
|
||||
## Developing osu!
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Please make sure you have the following prerequisites:
|
||||
|
||||
- A desktop platform with the [.NET 8.0 SDK](https://dotnet.microsoft.com/download) installed.
|
||||
|
||||
When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as the latest version of [Visual Studio](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/), or [Visual Studio Code](https://code.visualstudio.com/) with the [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) and [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) plugin installed.
|
||||
|
||||
### Downloading the source code
|
||||
|
||||
Clone the repository:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/ppy/osu
|
||||
cd osu
|
||||
```
|
||||
|
||||
To update the source code to the latest commit, run the following command inside the `osu` directory:
|
||||
|
||||
```shell
|
||||
git pull
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
#### From an IDE
|
||||
|
||||
You should load the solution via one of the platform-specific `.slnf` files, rather than the main `.sln`. This will reduce dependencies and hide platforms that you don't care about. Valid `.slnf` files are:
|
||||
|
||||
- `osu.Desktop.slnf` (most common)
|
||||
- `osu.Android.slnf`
|
||||
- `osu.iOS.slnf`
|
||||
|
||||
Run configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `osu! (Tests)` project/configuration. More information on this is provided [below](#contributing).
|
||||
|
||||
To build for mobile platforms, you will likely need to run `sudo dotnet workload restore` if you haven't done so previously. This will install Android/iOS tooling required to complete the build.
|
||||
|
||||
#### From CLI
|
||||
|
||||
You can also build and run *osu!* from the command-line with a single command:
|
||||
|
||||
```shell
|
||||
dotnet run --project osu.Desktop
|
||||
```
|
||||
|
||||
When running locally to do any kind of performance testing, make sure to add `-c Release` to the build command, as the overhead of running with the default `Debug` configuration can be large (especially when testing with local framework modifications as below).
|
||||
|
||||
If the build fails, try to restore NuGet packages with `dotnet restore`.
|
||||
|
||||
### Testing with resource/framework modifications
|
||||
|
||||
Sometimes it may be necessary to cross-test changes in [osu-resources](https://github.com/ppy/osu-resources) or [osu-framework](https://github.com/ppy/osu-framework). This can be quickly achieved using included commands:
|
||||
|
||||
Windows:
|
||||
|
||||
```ps
|
||||
UseLocalFramework.ps1
|
||||
UseLocalResources.ps1
|
||||
```
|
||||
|
||||
macOS / Linux:
|
||||
|
||||
```ps
|
||||
UseLocalFramework.sh
|
||||
UseLocalResources.sh
|
||||
```
|
||||
|
||||
Note that these commands assume you have the relevant project(s) checked out in adjacent directories:
|
||||
|
||||
```
|
||||
|- osu // this repository
|
||||
|- osu-framework
|
||||
|- osu-resources
|
||||
```
|
||||
|
||||
### Code analysis
|
||||
|
||||
Before committing your code, please run a code formatter. This can be achieved by running `dotnet format` in the command line, or using the `Format code` command in your IDE.
|
||||
|
||||
We have adopted some cross-platform, compiler integrated analyzers. They can provide warnings when you are editing, building inside IDE or from command line, as-if they are provided by the compiler itself.
|
||||
|
||||
JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it from PowerShell with `.\InspectCode.ps1`. Alternatively, you can install ReSharper or use Rider to get inline support in your IDE of choice.
|
||||
|
||||
## Contributing
|
||||
|
||||
When it comes to contributing to the project, the two main things you can do to help out are reporting issues and submitting pull requests. Please refer to the [contributing guidelines](CONTRIBUTING.md) to understand how to help in the most effective way possible.
|
||||
|
||||
If you wish to help with localisation efforts, head over to [crowdin](https://crowdin.com/project/osu-web).
|
||||
|
||||
We love to reward quality contributions. If you have made a large contribution, or are a regular contributor, you are welcome to [submit an expense via opencollective](https://opencollective.com/ppy/expenses/new). If you have any questions, feel free to [reach out to peppy](mailto:pe@ppy.sh) before doing so.
|
||||
|
||||
## Licence
|
||||
|
||||
*osu!*'s code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source.
|
||||
|
||||
Please note that this *does not cover* the usage of the "osu!" or "ppy" branding in any software, resources, advertising or promotion, as this is protected by trademark law.
|
||||
|
||||
Please also note that game resources are covered by a separate licence. Please see the [ppy/osu-resources](https://github.com/ppy/osu-resources) repository for clarifications.
|
||||
@@ -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>
|
||||
|
||||
@@ -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!;
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace osu.Desktop
|
||||
if (IsPackageManaged)
|
||||
return new NoActionUpdateManager();
|
||||
|
||||
return new VelopackUpdateManager();
|
||||
return new VelopackUpdateManager(); // yay
|
||||
}
|
||||
|
||||
public override bool RestartAppWhenExited()
|
||||
@@ -148,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;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ namespace osu.Desktop
|
||||
public static class Program
|
||||
{
|
||||
#if DEBUG
|
||||
private const string base_game_name = @"osu-development";
|
||||
private const string base_game_name = @"jvnkosu-development";
|
||||
#else
|
||||
private const string base_game_name = @"osu";
|
||||
private const string base_game_name = @"jvnkosu";
|
||||
#endif
|
||||
|
||||
private static LegacyTcpIpcProvider? legacyIpc;
|
||||
@@ -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>
|
||||
|
||||
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 401 KiB |
@@ -3,11 +3,11 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
||||
<Description>A free-to-win rhythm game based on osu!(lazer). Click is just a *rhythm* away!</Description>
|
||||
<AssemblyName>osu!</AssemblyName>
|
||||
<AssemblyTitle>osu!(lazer)</AssemblyTitle>
|
||||
<Title>osu!</Title>
|
||||
<Product>osu!(lazer)</Product>
|
||||
<AssemblyTitle>jvnkosu!</AssemblyTitle>
|
||||
<Title>jvnkosu!</Title>
|
||||
<Product>jvnkosu!</Product>
|
||||
<ApplicationIcon>lazer.ico</ApplicationIcon>
|
||||
<Version>0.0.0</Version>
|
||||
<FileVersion>0.0.0</FileVersion>
|
||||
|
||||
@@ -3,16 +3,19 @@
|
||||
<metadata>
|
||||
<id>osulazer</id>
|
||||
<version>0.0.0</version>
|
||||
<title>osu!</title>
|
||||
<authors>ppy Pty Ltd</authors>
|
||||
<title>jvnkosu!</title>
|
||||
<authors>ppy Pty Ltd., jvnkosu! team</authors>
|
||||
<owners>Dean Herbert</owners>
|
||||
<projectUrl>https://osu.ppy.sh/</projectUrl>
|
||||
<projectUrl>https://osu.jvnko.boats/</projectUrl>
|
||||
<iconUrl>https://github.com/ppy/osu/blob/master/assets/lazer-nuget.png?raw=true</iconUrl>
|
||||
<icon>icon.png</icon>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>A free-to-win rhythm game. Rhythm is just a *click* away!</description>
|
||||
<description>A free-to-win rhythm game based on osu!(lazer). Click is just a *rhythm* away!</description>
|
||||
<releaseNotes>testing</releaseNotes>
|
||||
<copyright>Copyright (c) 2025 ppy Pty Ltd</copyright>
|
||||
<copyright>
|
||||
Copyright (c) 2025 ppy Pty Ltd
|
||||
Copyright (c) 2025 jvnkosu! team
|
||||
</copyright>
|
||||
<language>en-AU</language>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
leaderboard.Origin = Anchor.CentreLeft;
|
||||
leaderboard.X = 10;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
Children = new Drawable[]
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -13,8 +13,13 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
MinValue = 0,
|
||||
MaxValue = 10,
|
||||
// Use larger extended limits for mania to include OD values that occur with EZ or HR enabled
|
||||
#if !DEBUG
|
||||
ExtendedMaxValue = 15,
|
||||
ExtendedMinValue = -15,
|
||||
#else
|
||||
ExtendedMinValue = -250,
|
||||
ExtendedMaxValue = 50,
|
||||
#endif
|
||||
ReadCurrentFromDifficulty = diff => diff.OverallDifficulty,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -57,6 +57,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
|
||||
if (spectatorList != null)
|
||||
spectatorList.Position = new Vector2(36, -66);
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
new DrawableGameplayLeaderboard(),
|
||||
|
||||
@@ -122,6 +122,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
leaderboard.Origin = Anchor.CentreLeft;
|
||||
leaderboard.X = 10;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
new LegacyManiaComboCounter(),
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public partial class TestSceneGameplayCursorSizeChange : PlayerTestScene
|
||||
{
|
||||
private const float initial_cursor_size = 1f;
|
||||
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
|
||||
|
||||
[Resolved]
|
||||
private SkinManager? skins { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
if (skins != null) skins.CurrentSkinInfo.Value = skins.DefaultClassicSkin.SkinInfo;
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("Set gameplay cursor size: 1", () => LocalConfig.SetValue(OsuSetting.GameplayCursorSize, initial_cursor_size));
|
||||
AddStep("resume player", () => Player.GameplayClockContainer.Start());
|
||||
AddUntilStep("clock running", () => Player.GameplayClockContainer.IsRunning);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPausedChangeCursorSize()
|
||||
{
|
||||
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move cursor to top left", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft));
|
||||
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move cursor to top right", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopRight));
|
||||
AddStep("press escape", () => InputManager.Key(Key.Escape));
|
||||
|
||||
AddSliderStep("cursor size", 0.1f, 2f, 1f, v => LocalConfig.SetValue(OsuSetting.GameplayCursorSize, v));
|
||||
}
|
||||
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, false);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,13 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModMagnetised), typeof(OsuModRepel), typeof(OsuModAutopilot), typeof(OsuModSpunOut), typeof(OsuModAlternate), typeof(OsuModSingleTap) }).ToArray();
|
||||
|
||||
#if !DEBUG
|
||||
private string username = "Autoplay";
|
||||
#else
|
||||
private string username = "Chicony";
|
||||
#endif
|
||||
|
||||
public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||
=> new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedUser { Username = "Autoplay" });
|
||||
=> new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedUser { Username = username });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,19 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public partial class OsuModDifficultyAdjust : ModDifficultyAdjust
|
||||
{
|
||||
|
||||
[SettingSource("Circle Size", "Override a beatmap's set CS.", FIRST_SETTING_ORDER - 1, SettingControlType = typeof(DifficultyAdjustSettingsControl))]
|
||||
public DifficultyBindable CircleSize { get; } = new DifficultyBindable
|
||||
{
|
||||
Precision = 0.1f,
|
||||
MinValue = 0,
|
||||
MaxValue = 10,
|
||||
#if !DEBUG
|
||||
ExtendedMaxValue = 11,
|
||||
#else
|
||||
ExtendedMinValue = -250,
|
||||
ExtendedMaxValue = 13,
|
||||
#endif
|
||||
ReadCurrentFromDifficulty = diff => diff.CircleSize,
|
||||
};
|
||||
|
||||
@@ -32,8 +38,13 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
Precision = 0.1f,
|
||||
MinValue = 0,
|
||||
MaxValue = 10,
|
||||
#if !DEBUG
|
||||
ExtendedMinValue = -10,
|
||||
ExtendedMaxValue = 11,
|
||||
#else
|
||||
ExtendedMinValue = -250,
|
||||
ExtendedMaxValue = 13,
|
||||
#endif
|
||||
ReadCurrentFromDifficulty = diff => diff.ApproachRate,
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -103,6 +103,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
leaderboard.Origin = Anchor.BottomLeft;
|
||||
leaderboard.Position = pos;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
Children = new Drawable[]
|
||||
|
||||
@@ -49,6 +49,18 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
/// </summary>
|
||||
protected bool AllowPartRotation { get; set; }
|
||||
|
||||
private Vector2 cursorScale;
|
||||
|
||||
public Vector2 CursorScale
|
||||
{
|
||||
get => cursorScale;
|
||||
set
|
||||
{
|
||||
cursorScale = value;
|
||||
Invalidate(Invalidation.DrawNode);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The trail part texture origin.
|
||||
/// </summary>
|
||||
@@ -233,6 +245,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
private float time;
|
||||
private float fadeExponent;
|
||||
private float angle;
|
||||
private Vector2 cursorScale;
|
||||
|
||||
private readonly TrailPart[] parts = new TrailPart[max_sprites];
|
||||
private Vector2 originPosition;
|
||||
@@ -253,6 +266,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
time = Source.time;
|
||||
fadeExponent = Source.FadeExponent;
|
||||
angle = Source.AllowPartRotation ? float.DegreesToRadians(Source.PartRotation) : 0;
|
||||
cursorScale = Source.cursorScale;
|
||||
|
||||
originPosition = Vector2.Zero;
|
||||
|
||||
@@ -307,7 +321,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y),
|
||||
new Vector2(
|
||||
part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X * cursorScale.X,
|
||||
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y * cursorScale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.BottomLeft,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
@@ -318,8 +334,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X,
|
||||
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y), part.Position, sin, cos),
|
||||
new Vector2(
|
||||
part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X * cursorScale.X,
|
||||
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y * cursorScale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.BottomRight,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
Colour = DrawColourInfo.Colour.BottomRight.Linear,
|
||||
@@ -329,7 +347,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
|
||||
new Vector2(
|
||||
part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X * cursorScale.X,
|
||||
part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y * cursorScale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.TopRight,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
@@ -340,7 +360,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
|
||||
new Vector2(
|
||||
part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X * cursorScale.X,
|
||||
part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y * cursorScale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.TopLeft,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
|
||||
@@ -64,8 +64,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
var newScale = new Vector2(e.NewValue);
|
||||
|
||||
rippleVisualiser.CursorScale = newScale;
|
||||
cursorTrail.Scale = newScale;
|
||||
updateTrailScale();
|
||||
}, true);
|
||||
cursorTrail.OnSkinChanged += updateTrailScale;
|
||||
}
|
||||
|
||||
private void updateTrailScale()
|
||||
{
|
||||
if (cursorTrail.Drawable is CursorTrail trail) trail.CursorScale = new Vector2(ActiveCursor.CursorScale.Value);
|
||||
}
|
||||
|
||||
private int downCount;
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -51,6 +51,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon
|
||||
spectatorList.Anchor = Anchor.BottomLeft;
|
||||
spectatorList.Origin = Anchor.TopLeft;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
|
||||
@@ -51,6 +51,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default
|
||||
spectatorList.Origin = Anchor.TopLeft;
|
||||
spectatorList.Position = new Vector2(320, -280);
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
|
||||
@@ -79,6 +79,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
spectatorList.Origin = Anchor.TopLeft;
|
||||
spectatorList.Position = pos;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
new LegacyDefaultComboCounter(),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -16,6 +16,7 @@ using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.IO.Archives;
|
||||
@@ -206,7 +207,7 @@ namespace osu.Game.Tests.Online
|
||||
{
|
||||
}
|
||||
|
||||
protected override BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm)
|
||||
protected override BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm, OsuConfigManager? config = null)
|
||||
{
|
||||
return new TestBeatmapImporter(this, storage, realm);
|
||||
}
|
||||
@@ -216,7 +217,7 @@ namespace osu.Game.Tests.Online
|
||||
private readonly TestBeatmapManager testBeatmapManager;
|
||||
|
||||
public TestBeatmapImporter(TestBeatmapManager testBeatmapManager, Storage storage, RealmAccess databaseAccess)
|
||||
: base(storage, databaseAccess)
|
||||
: base(storage, databaseAccess, null)
|
||||
{
|
||||
this.testBeatmapManager = testBeatmapManager;
|
||||
}
|
||||
@@ -224,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);
|
||||
|
||||
BIN
osu.Game.Tests/Resources/Archives/modified-classic-20250827.osk
Normal file
BIN
osu.Game.Tests/Resources/special-skin/score-0@2x.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-1@2x.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-2@2x.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-3@2x.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-4@2x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-5@2x.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-6@2x.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-7@2x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-8@2x.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-9@2x.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-comma@2x.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-dot@2x.png
Normal file
|
After Width: | Height: | Size: 930 B |
BIN
osu.Game.Tests/Resources/special-skin/score-percent@2x.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-pp@2x.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
osu.Game.Tests/Resources/special-skin/score-x@2x.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
@@ -79,8 +79,12 @@ namespace osu.Game.Tests.Skins
|
||||
"Archives/modified-argon-20250424.osk",
|
||||
// Covers "Argon" unstable rate counter
|
||||
"Archives/modified-argon-20250809.osk",
|
||||
// Covers legacy style performance points counter
|
||||
"Archives/modified-classic-20250827.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>
|
||||
|
||||
@@ -1,209 +1,209 @@
|
||||
// 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.
|
||||
// // 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.
|
||||
|
||||
#nullable disable
|
||||
// #nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Rendering;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using NUnit.Framework;
|
||||
// using osu.Framework.Allocation;
|
||||
// using osu.Framework.Graphics;
|
||||
// using osu.Framework.Graphics.Containers;
|
||||
// using osu.Framework.Graphics.Rendering;
|
||||
// using osu.Framework.Graphics.Textures;
|
||||
// using osu.Game.Configuration;
|
||||
// using osu.Game.Graphics.Backgrounds;
|
||||
// using osu.Game.Online.API;
|
||||
// using osu.Game.Online.API.Requests;
|
||||
// using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Background
|
||||
{
|
||||
public partial class TestSceneSeasonalBackgroundLoader : ScreenTestScene
|
||||
{
|
||||
[Resolved]
|
||||
private OsuConfigManager config { get; set; }
|
||||
// namespace osu.Game.Tests.Visual.Background
|
||||
// {
|
||||
// public partial class TestSceneSeasonalBackgroundLoader : ScreenTestScene
|
||||
// {
|
||||
// [Resolved]
|
||||
// private OsuConfigManager config { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private SessionStatics statics { get; set; }
|
||||
// [Resolved]
|
||||
// private SessionStatics statics { get; set; }
|
||||
|
||||
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
|
||||
// private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
|
||||
|
||||
private LookupLoggingTextureStore textureStore;
|
||||
private SeasonalBackgroundLoader backgroundLoader;
|
||||
private Container backgroundContainer;
|
||||
// private LookupLoggingTextureStore textureStore;
|
||||
// private SeasonalBackgroundLoader backgroundLoader;
|
||||
// private Container backgroundContainer;
|
||||
|
||||
// in real usages these would be online URLs, but correct execution of this test
|
||||
// shouldn't be coupled to existence of online assets.
|
||||
private static readonly List<string> seasonal_background_urls = new List<string>
|
||||
{
|
||||
"Backgrounds/bg2",
|
||||
"Backgrounds/bg4",
|
||||
"Backgrounds/bg3"
|
||||
};
|
||||
// // in real usages these would be online URLs, but correct execution of this test
|
||||
// // shouldn't be coupled to existence of online assets.
|
||||
// private static readonly List<string> seasonal_background_urls = new List<string>
|
||||
// {
|
||||
// "Backgrounds/bg2",
|
||||
// "Backgrounds/bg4",
|
||||
// "Backgrounds/bg3"
|
||||
// };
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
// protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
// {
|
||||
// var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
|
||||
textureStore = new LookupLoggingTextureStore(dependencies.Get<IRenderer>());
|
||||
dependencies.CacheAs(typeof(LargeTextureStore), textureStore);
|
||||
// textureStore = new LookupLoggingTextureStore(dependencies.Get<IRenderer>());
|
||||
// dependencies.CacheAs(typeof(LargeTextureStore), textureStore);
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
// return dependencies;
|
||||
// }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LargeTextureStore wrappedStore)
|
||||
{
|
||||
textureStore.AddStore(wrappedStore);
|
||||
// [BackgroundDependencyLoader]
|
||||
// private void load(LargeTextureStore wrappedStore)
|
||||
// {
|
||||
// textureStore.AddStore(wrappedStore);
|
||||
|
||||
Child = new DependencyProvidingContainer
|
||||
{
|
||||
CachedDependencies = new (Type, object)[]
|
||||
{
|
||||
(typeof(LargeTextureStore), textureStore)
|
||||
},
|
||||
Child = backgroundContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
};
|
||||
}
|
||||
// Child = new DependencyProvidingContainer
|
||||
// {
|
||||
// CachedDependencies = new (Type, object)[]
|
||||
// {
|
||||
// (typeof(LargeTextureStore), textureStore)
|
||||
// },
|
||||
// Child = backgroundContainer = new Container
|
||||
// {
|
||||
// RelativeSizeAxes = Axes.Both
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
// reset API response in statics to avoid test crosstalk.
|
||||
statics.SetValue<APISeasonalBackgrounds>(Static.SeasonalBackgrounds, null);
|
||||
textureStore.PerformedLookups.Clear();
|
||||
dummyAPI.SetState(APIState.Online);
|
||||
// [SetUp]
|
||||
// public void SetUp() => Schedule(() =>
|
||||
// {
|
||||
// // reset API response in statics to avoid test crosstalk.
|
||||
// statics.SetValue<APISeasonalBackgrounds>(Static.SeasonalBackgrounds, null);
|
||||
// textureStore.PerformedLookups.Clear();
|
||||
// dummyAPI.SetState(APIState.Online);
|
||||
|
||||
backgroundContainer.Clear();
|
||||
});
|
||||
// backgroundContainer.Clear();
|
||||
// });
|
||||
|
||||
[TestCase(-5)]
|
||||
[TestCase(5)]
|
||||
public void TestAlwaysSeasonal(int daysOffset)
|
||||
{
|
||||
registerBackgroundsResponse(DateTimeOffset.Now.AddDays(daysOffset));
|
||||
setSeasonalBackgroundMode(SeasonalBackgroundMode.Always);
|
||||
// [TestCase(-5)]
|
||||
// [TestCase(5)]
|
||||
// public void TestAlwaysSeasonal(int daysOffset)
|
||||
// {
|
||||
// registerBackgroundsResponse(DateTimeOffset.Now.AddDays(daysOffset));
|
||||
// setSeasonalBackgroundMode(SeasonalBackgroundMode.Always);
|
||||
|
||||
createLoader();
|
||||
// createLoader();
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
loadNextBackground();
|
||||
// for (int i = 0; i < 4; ++i)
|
||||
// loadNextBackground();
|
||||
|
||||
AddAssert("all backgrounds cycled", () => new HashSet<string>(textureStore.PerformedLookups).SetEquals(seasonal_background_urls));
|
||||
}
|
||||
// AddAssert("all backgrounds cycled", () => new HashSet<string>(textureStore.PerformedLookups).SetEquals(seasonal_background_urls));
|
||||
// }
|
||||
|
||||
[TestCase(-5)]
|
||||
[TestCase(5)]
|
||||
public void TestNeverSeasonal(int daysOffset)
|
||||
{
|
||||
registerBackgroundsResponse(DateTimeOffset.Now.AddDays(daysOffset));
|
||||
setSeasonalBackgroundMode(SeasonalBackgroundMode.Never);
|
||||
// [TestCase(-5)]
|
||||
// [TestCase(5)]
|
||||
// public void TestNeverSeasonal(int daysOffset)
|
||||
// {
|
||||
// registerBackgroundsResponse(DateTimeOffset.Now.AddDays(daysOffset));
|
||||
// setSeasonalBackgroundMode(SeasonalBackgroundMode.Never);
|
||||
|
||||
createLoader();
|
||||
// createLoader();
|
||||
|
||||
assertNoBackgrounds();
|
||||
}
|
||||
// assertNoBackgrounds();
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void TestSometimesInSeason()
|
||||
{
|
||||
registerBackgroundsResponse(DateTimeOffset.Now.AddDays(5));
|
||||
setSeasonalBackgroundMode(SeasonalBackgroundMode.Sometimes);
|
||||
// [Test]
|
||||
// public void TestSometimesInSeason()
|
||||
// {
|
||||
// registerBackgroundsResponse(DateTimeOffset.Now.AddDays(5));
|
||||
// setSeasonalBackgroundMode(SeasonalBackgroundMode.Sometimes);
|
||||
|
||||
createLoader();
|
||||
// createLoader();
|
||||
|
||||
assertAnyBackground();
|
||||
}
|
||||
// assertAnyBackground();
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void TestSometimesOutOfSeason()
|
||||
{
|
||||
registerBackgroundsResponse(DateTimeOffset.Now.AddDays(-10));
|
||||
setSeasonalBackgroundMode(SeasonalBackgroundMode.Sometimes);
|
||||
// [Test]
|
||||
// public void TestSometimesOutOfSeason()
|
||||
// {
|
||||
// registerBackgroundsResponse(DateTimeOffset.Now.AddDays(-10));
|
||||
// setSeasonalBackgroundMode(SeasonalBackgroundMode.Sometimes);
|
||||
|
||||
createLoader();
|
||||
// createLoader();
|
||||
|
||||
assertNoBackgrounds();
|
||||
}
|
||||
// assertNoBackgrounds();
|
||||
// }
|
||||
|
||||
private void registerBackgroundsResponse(DateTimeOffset endDate)
|
||||
=> AddStep("setup request handler", () =>
|
||||
{
|
||||
dummyAPI.HandleRequest = request =>
|
||||
{
|
||||
if (dummyAPI.State.Value != APIState.Online || !(request is GetSeasonalBackgroundsRequest backgroundsRequest))
|
||||
return false;
|
||||
// private void registerBackgroundsResponse(DateTimeOffset endDate)
|
||||
// => AddStep("setup request handler", () =>
|
||||
// {
|
||||
// dummyAPI.HandleRequest = request =>
|
||||
// {
|
||||
// if (dummyAPI.State.Value != APIState.Online || !(request is GetSeasonalBackgroundsRequest backgroundsRequest))
|
||||
// return false;
|
||||
|
||||
backgroundsRequest.TriggerSuccess(new APISeasonalBackgrounds
|
||||
{
|
||||
Backgrounds = seasonal_background_urls.Select(url => new APISeasonalBackground { Url = url }).ToList(),
|
||||
EndDate = endDate
|
||||
});
|
||||
// backgroundsRequest.TriggerSuccess(new APISeasonalBackgrounds
|
||||
// {
|
||||
// Backgrounds = seasonal_background_urls.Select(url => new APISeasonalBackground { Url = url }).ToList(),
|
||||
// EndDate = endDate
|
||||
// });
|
||||
|
||||
return true;
|
||||
};
|
||||
});
|
||||
// return true;
|
||||
// };
|
||||
// });
|
||||
|
||||
private void setSeasonalBackgroundMode(SeasonalBackgroundMode mode)
|
||||
=> AddStep($"set seasonal mode to {mode}", () => config.SetValue(OsuSetting.SeasonalBackgroundMode, mode));
|
||||
// private void setSeasonalBackgroundMode(SeasonalBackgroundMode mode)
|
||||
// => AddStep($"set seasonal mode to {mode}", () => config.SetValue(OsuSetting.SeasonalBackgroundMode, mode));
|
||||
|
||||
private void createLoader()
|
||||
=> AddStep("create loader", () =>
|
||||
{
|
||||
if (backgroundLoader != null)
|
||||
Remove(backgroundLoader, true);
|
||||
// private void createLoader()
|
||||
// => AddStep("create loader", () =>
|
||||
// {
|
||||
// if (backgroundLoader != null)
|
||||
// Remove(backgroundLoader, true);
|
||||
|
||||
Add(backgroundLoader = new SeasonalBackgroundLoader());
|
||||
});
|
||||
// Add(backgroundLoader = new SeasonalBackgroundLoader());
|
||||
// });
|
||||
|
||||
private void loadNextBackground()
|
||||
{
|
||||
SeasonalBackground previousBackground = null;
|
||||
SeasonalBackground background = null;
|
||||
// private void loadNextBackground()
|
||||
// {
|
||||
// SeasonalBackground previousBackground = null;
|
||||
// SeasonalBackground background = null;
|
||||
|
||||
AddStep("create next background", () =>
|
||||
{
|
||||
previousBackground = (SeasonalBackground)backgroundContainer.SingleOrDefault();
|
||||
background = backgroundLoader.LoadNextBackground();
|
||||
if (background != null)
|
||||
LoadComponentAsync(background, bg => backgroundContainer.Child = bg);
|
||||
});
|
||||
// AddStep("create next background", () =>
|
||||
// {
|
||||
// previousBackground = (SeasonalBackground)backgroundContainer.SingleOrDefault();
|
||||
// background = backgroundLoader.LoadNextBackground();
|
||||
// if (background != null)
|
||||
// LoadComponentAsync(background, bg => backgroundContainer.Child = bg);
|
||||
// });
|
||||
|
||||
AddUntilStep("background loaded", () => background.IsLoaded);
|
||||
AddAssert("background is different", () => !background.Equals(previousBackground));
|
||||
}
|
||||
// AddUntilStep("background loaded", () => background.IsLoaded);
|
||||
// AddAssert("background is different", () => !background.Equals(previousBackground));
|
||||
// }
|
||||
|
||||
private void assertAnyBackground()
|
||||
{
|
||||
loadNextBackground();
|
||||
AddAssert("background looked up", () => textureStore.PerformedLookups.Any());
|
||||
}
|
||||
// private void assertAnyBackground()
|
||||
// {
|
||||
// loadNextBackground();
|
||||
// AddAssert("background looked up", () => textureStore.PerformedLookups.Any());
|
||||
// }
|
||||
|
||||
private void assertNoBackgrounds()
|
||||
{
|
||||
AddAssert("no background available", () => backgroundLoader.LoadNextBackground() == null);
|
||||
AddAssert("no lookups performed", () => !textureStore.PerformedLookups.Any());
|
||||
}
|
||||
// private void assertNoBackgrounds()
|
||||
// {
|
||||
// AddAssert("no background available", () => backgroundLoader.LoadNextBackground() == null);
|
||||
// AddAssert("no lookups performed", () => !textureStore.PerformedLookups.Any());
|
||||
// }
|
||||
|
||||
private class LookupLoggingTextureStore : LargeTextureStore
|
||||
{
|
||||
public List<string> PerformedLookups { get; } = new List<string>();
|
||||
// private class LookupLoggingTextureStore : LargeTextureStore
|
||||
// {
|
||||
// public List<string> PerformedLookups { get; } = new List<string>();
|
||||
|
||||
public LookupLoggingTextureStore(IRenderer renderer)
|
||||
: base(renderer)
|
||||
{
|
||||
}
|
||||
// public LookupLoggingTextureStore(IRenderer renderer)
|
||||
// : base(renderer)
|
||||
// {
|
||||
// }
|
||||
|
||||
public override Texture Get(string name, WrapMode wrapModeS, WrapMode wrapModeT)
|
||||
{
|
||||
PerformedLookups.Add(name);
|
||||
return base.Get(name, wrapModeS, wrapModeT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// public override Texture Get(string name, WrapMode wrapModeS, WrapMode wrapModeT)
|
||||
// {
|
||||
// PerformedLookups.Add(name);
|
||||
// return base.Get(name, wrapModeS, wrapModeT);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -50,6 +50,34 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Texture == null)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSpriteFadeOverflowBehaviour()
|
||||
{
|
||||
AddStep("create sprite", () => SetContents(_ =>
|
||||
{
|
||||
var layer = storyboard.GetLayer("Background");
|
||||
|
||||
var sprite = new StoryboardSprite(lookup_name, Anchor.TopLeft, new Vector2(256, 192));
|
||||
sprite.Commands.AddAlpha(Easing.None, Time.Current, Time.Current + 2000, 0, 2);
|
||||
|
||||
layer.Elements.Clear();
|
||||
layer.Add(sprite);
|
||||
|
||||
return new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
storyboard.CreateDrawable()
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
AddUntilStep("sprite reached high opacity once", () => sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Alpha > 0.8f)));
|
||||
AddUntilStep("sprite reset to low opacity", () => sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Alpha < 0.2f)));
|
||||
AddUntilStep("sprite reached high opacity twice", () => sprites.All(sprite => sprite.ChildrenOfType<Sprite>().All(s => s.Alpha > 0.8f)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLookupFromStoryboard()
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -18,6 +18,7 @@ using osu.Game.Rulesets.Osu.Scoring;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Skinning.Triangles;
|
||||
using osu.Game.Tests.Gameplay;
|
||||
|
||||
@@ -35,7 +36,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
protected override Drawable CreateDefaultImplementation() => new TrianglesPerformancePointsCounter();
|
||||
protected override Drawable CreateArgonImplementation() => new ArgonPerformancePointsCounter();
|
||||
protected override Drawable CreateLegacyImplementation() => Empty();
|
||||
protected override Drawable CreateLegacyImplementation() => new LegacyPerformancePointsCounter();
|
||||
|
||||
private Bindable<JudgementResult> lastJudgementResult => (Bindable<JudgementResult>)gameplayState.LastJudgementResult;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
@@ -378,6 +379,23 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
() => Is.EqualTo(3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCopyPasteIdempotency()
|
||||
{
|
||||
string state = null!;
|
||||
AddStep("select everything", () => InputManager.Keys(PlatformAction.SelectAll));
|
||||
AddStep("dump state", () =>
|
||||
{
|
||||
state = JsonConvert.SerializeObject(skinEditor.SelectedComponents.Cast<Drawable>().Select(s => s.CreateSerialisedInfo()).ToArray());
|
||||
});
|
||||
AddStep("copy", () => InputManager.Keys(PlatformAction.Copy));
|
||||
AddStep("delete", () => InputManager.Keys(PlatformAction.Delete));
|
||||
AddStep("paste", () => InputManager.Keys(PlatformAction.Paste));
|
||||
AddAssert("pasted state equals dumped",
|
||||
() => JsonConvert.SerializeObject(skinEditor.SelectedComponents.Cast<Drawable>().Select(s => s.CreateSerialisedInfo()).ToArray()),
|
||||
() => Is.EqualTo(state));
|
||||
}
|
||||
|
||||
private SkinnableContainer globalHUDTarget => Player.ChildrenOfType<SkinnableContainer>()
|
||||
.Single(c => c.Lookup.Lookup == GlobalSkinnableContainers.MainHUDComponents && c.Lookup.Ruleset == null);
|
||||
|
||||
|
||||
29
osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Screens.Menu;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Menus
|
||||
{
|
||||
public partial class TestSceneDisclaimer : ScreenTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddStep("load disclaimer", () => LoadScreen(new Disclaimer()));
|
||||
|
||||
AddStep("toggle support", () =>
|
||||
{
|
||||
((DummyAPIAccess)API).LocalUser.Value = new APIUser
|
||||
{
|
||||
Username = API.LocalUser.Value.Username,
|
||||
Id = API.LocalUser.Value.Id + 1,
|
||||
IsSupporter = !API.LocalUser.Value.IsSupporter,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,7 +159,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("check request received", () =>
|
||||
{
|
||||
multiplayerClient.Verify(m => m.SendMatchRequest(It.Is<StartMatchCountdownRequest>(req =>
|
||||
req.Duration == TimeSpan.FromSeconds(10)
|
||||
req.Duration == TimeSpan.FromSeconds(30)
|
||||
)), Times.Once);
|
||||
});
|
||||
}
|
||||
@@ -181,7 +181,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("check request received", () =>
|
||||
{
|
||||
multiplayerClient.Verify(m => m.SendMatchRequest(It.Is<StartMatchCountdownRequest>(req =>
|
||||
req.Duration == TimeSpan.FromSeconds(10)
|
||||
req.Duration == TimeSpan.FromSeconds(30)
|
||||
)), Times.Once);
|
||||
});
|
||||
|
||||
|
||||
@@ -305,6 +305,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
new APIMod(new OsuModDoubleTime { SpeedChange = { Value = 2.0 } }),
|
||||
new APIMod(new OsuModStrictTracking()),
|
||||
new APIMod(new OsuModAutoplay()), // THIS IS PURELY TO ENABLE UNRANKED BADGE AND LET TEST PASS
|
||||
// I AM NOT PROUD OF THIS
|
||||
},
|
||||
AllowedMods = new[]
|
||||
{
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
// Importantly, this occurs before base.load().
|
||||
if (!loader.AllowLoad.Wait(TimeSpan.FromSeconds(10)))
|
||||
if (!loader.AllowLoad.Wait(TimeSpan.FromSeconds(30)))
|
||||
throw new TimeoutException();
|
||||
|
||||
return base.CreateChildDependencies(parent);
|
||||
|
||||
@@ -24,6 +24,7 @@ using osu.Game.Configuration;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics.Carousel;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Notifications.WebSocket;
|
||||
@@ -33,6 +34,7 @@ using osu.Game.Overlays.BeatmapListing;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Overlays.Toolbar;
|
||||
using osu.Game.Overlays.Volume;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
@@ -920,8 +922,12 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Explicit("Featured Artist dialog is never displayed as the filter is disabled by default.")]
|
||||
public void TestFeaturedArtistDisclaimerDialog()
|
||||
{
|
||||
// NO-OP: FA dialog is not displayed ever
|
||||
|
||||
/*
|
||||
BeatmapListingOverlay getBeatmapListingOverlay() => Game.ChildrenOfType<BeatmapListingOverlay>().FirstOrDefault();
|
||||
|
||||
AddStep("Wait for notifications to load", () => Game.SearchBeatmapSet(string.Empty));
|
||||
@@ -939,6 +945,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("dialog dismissed", () => Game.ChildrenOfType<DialogOverlay>().Single().CurrentDialog == null);
|
||||
|
||||
AddUntilStep("featured artist filter is off", () => !getBeatmapListingOverlay().ChildrenOfType<BeatmapSearchGeneralFilterRow>().First().Current.Contains(SearchGeneral.FeaturedArtists));
|
||||
*/
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -1331,6 +1338,34 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("still nothing selected", () => Game.Beatmap.IsDefault);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVolumeMeterDragDoesNotDismissFocusedOverlay()
|
||||
{
|
||||
AddStep("show beatmap overlay", () => Game.ShowBeatmapSet(1));
|
||||
AddUntilStep("beatmap overlay still visible",
|
||||
() => Game.ChildrenOfType<BeatmapSetOverlay>().SingleOrDefault()?.State.Value,
|
||||
() => Is.EqualTo(Visibility.Visible));
|
||||
AddStep("set game volume to max", () => Game.Dependencies.Get<FrameworkConfigManager>().SetValue(FrameworkSetting.VolumeUniversal, 1d));
|
||||
AddStep("move to centre", () => InputManager.MoveMouseTo(Game));
|
||||
AddStep("alt-scroll down", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.ScrollVerticalBy(-1);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
AddUntilStep("wait for volume overlay to show", () => Game.ChildrenOfType<VolumeOverlay>().SingleOrDefault()?.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
AddStep("start dragging meter", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(Game.ChildrenOfType<VolumeMeter>().First().ChildrenOfType<OsuSpriteText>().First());
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
});
|
||||
AddStep("drag away", () => InputManager.MoveMouseTo(Game.ChildrenOfType<VolumeMeter>().First().ChildrenOfType<OsuSpriteText>().First(), new Vector2(0, -100)));
|
||||
AddStep("release mouse", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
AddAssert("beatmap overlay still visible",
|
||||
() => Game.ChildrenOfType<BeatmapSetOverlay>().SingleOrDefault()?.State.Value,
|
||||
() => Is.EqualTo(Visibility.Visible));
|
||||
}
|
||||
|
||||
private Func<Player> playToResults()
|
||||
{
|
||||
var player = playToCompletion();
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
private const int requested_beatmap_id = 75;
|
||||
private const int requested_beatmap_set_id = 1;
|
||||
|
||||
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"osu://b/{requested_beatmap_id}" });
|
||||
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"jvnkosu://b/{requested_beatmap_id}" });
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
private const int requested_beatmap_set_id = 1;
|
||||
|
||||
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"osu://s/{requested_beatmap_set_id}" });
|
||||
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"jvnkosu://s/{requested_beatmap_set_id}" });
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
|
||||
@@ -84,9 +84,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
public void TestFeaturedArtistFilter()
|
||||
{
|
||||
AddAssert("is visible", () => overlay.State.Value == Visibility.Visible);
|
||||
AddAssert("featured artist filter is on", () => overlay.ChildrenOfType<BeatmapSearchGeneralFilterRow>().First().Current.Contains(SearchGeneral.FeaturedArtists));
|
||||
AddStep("toggle featured artist filter", () => overlay.ChildrenOfType<FilterTabItem<SearchGeneral>>().First(i => i.Value == SearchGeneral.FeaturedArtists).TriggerClick());
|
||||
AddAssert("featured artist filter is off", () => !overlay.ChildrenOfType<BeatmapSearchGeneralFilterRow>().First().Current.Contains(SearchGeneral.FeaturedArtists));
|
||||
AddStep("toggle featured artist filter", () => overlay.ChildrenOfType<FilterTabItem<SearchGeneral>>().First(i => i.Value == SearchGeneral.FeaturedArtists).TriggerClick());
|
||||
AddAssert("featured artist filter is on", () => overlay.ChildrenOfType<BeatmapSearchGeneralFilterRow>().First().Current.Contains(SearchGeneral.FeaturedArtists));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -55,31 +55,31 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
|
||||
[TestCase("test!")]
|
||||
[TestCase("dev.ppy.sh!")]
|
||||
[TestCase("https://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("http://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("forgothttps://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("forgothttp://dev.ppy.sh!", LinkAction.External)]
|
||||
[TestCase("osu.jvnko.boats!")]
|
||||
[TestCase("https://osu.jvnko.boats!", LinkAction.External)]
|
||||
[TestCase("http://osu.jvnko.boats!", LinkAction.External)]
|
||||
[TestCase("forgothttps://osu.jvnko.boats!", LinkAction.External)]
|
||||
[TestCase("forgothttp://osu.jvnko.boats!", LinkAction.External)]
|
||||
[TestCase("00:12:345 - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase("00:12:345 (1,2) - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}edit/00:12:345 - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}edit/00:12:345 (1,2) - Test?", LinkAction.OpenEditorTimestamp)]
|
||||
[TestCase($"{OsuGameBase.OSU_PROTOCOL}00:12:345 - not an editor timestamp", LinkAction.External)]
|
||||
[TestCase("Wiki link for tasty [[Performance Points]]", LinkAction.OpenWiki)]
|
||||
[TestCase("(osu forums)[https://dev.ppy.sh/forum] (old link format)", LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home New site] (new link format)", LinkAction.External)]
|
||||
[TestCase("[osu forums](https://dev.ppy.sh/forum) (new link format 2)", LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", LinkAction.External)]
|
||||
[TestCase("Let's (try)[https://dev.ppy.sh/home] [https://dev.ppy.sh/b/252238 multiple links] https://dev.ppy.sh/home", LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External)]
|
||||
[TestCase("[https://dev.ppy.sh/home New link format with escaped [and \\[ paired] braces]", LinkAction.External)]
|
||||
[TestCase("[Markdown link format with escaped [and \\[ paired] braces](https://dev.ppy.sh/home)", LinkAction.External)]
|
||||
[TestCase("(Old link format with escaped (and \\( paired) parentheses)[https://dev.ppy.sh/home] and [[also a rogue wiki link]]", LinkAction.External, LinkAction.OpenWiki)]
|
||||
[TestCase("(osu forums)[https://osu.jvnko.boats/forum] (old link format)", LinkAction.External)]
|
||||
[TestCase("[https://osu.jvnko.boats/home New site] (new link format)", LinkAction.External)]
|
||||
[TestCase("[osu forums](https://osu.jvnko.boats/forum) (new link format 2)", LinkAction.External)]
|
||||
[TestCase("[https://osu.jvnko.boats/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", LinkAction.External)]
|
||||
[TestCase("Let's (try)[https://osu.jvnko.boats/home] [https://osu.jvnko.boats/b/252238 multiple links] https://osu.jvnko.boats/home", LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External)]
|
||||
[TestCase("[https://osu.jvnko.boats/home New link format with escaped [and \\[ paired] braces]", LinkAction.External)]
|
||||
[TestCase("[Markdown link format with escaped [and \\[ paired] braces](https://osu.jvnko.boats/home)", LinkAction.External)]
|
||||
[TestCase("(Old link format with escaped (and \\( paired) parentheses)[https://osu.jvnko.boats/home] and [[also a rogue wiki link]]", LinkAction.External, LinkAction.OpenWiki)]
|
||||
[TestCase("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present).")] // note that there's 0 links here (they get removed if a channel is not found)
|
||||
[TestCase("Join my multiplayer game osu://room/12346.", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer gameosu://room/12346.", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my [multiplayer game](osu://room/12346).", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer game http://dev.ppy.sh/multiplayer/rooms/12346", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my [multiplayer game](http://dev.ppy.sh/multiplayer/rooms/12346).", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer game jvnkosu://room/12346.", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer gamejvnkosu://room/12346.", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my [multiplayer game](jvnkosu://room/12346).", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my multiplayer game http://osu.jvnko.boats/multiplayer/rooms/12346", LinkAction.JoinRoom)]
|
||||
[TestCase("Join my [multiplayer game](http://osu.jvnko.boats/multiplayer/rooms/12346).", LinkAction.JoinRoom)]
|
||||
[TestCase($"Join my [#english]({OsuGameBase.OSU_PROTOCOL}chan/#english).", LinkAction.OpenChannel)]
|
||||
[TestCase($"Join my {OsuGameBase.OSU_PROTOCOL}chan/#english.", LinkAction.OpenChannel)]
|
||||
[TestCase($"Join my{OsuGameBase.OSU_PROTOCOL}chan/#english.", LinkAction.OpenChannel)]
|
||||
@@ -91,11 +91,11 @@ namespace osu.Game.Tests.Visual.Online
|
||||
addMessageWithChecks(text, expectedActions: actions);
|
||||
}
|
||||
|
||||
[TestCase("is now listening to [https://dev.ppy.sh/s/93523 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmapSet)]
|
||||
[TestCase("is now playing [https://dev.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmap)]
|
||||
[TestCase("is now listening to [https://osu.jvnko.boats/s/93523 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmapSet)]
|
||||
[TestCase("is now playing [https://osu.jvnko.boats/b/252238 IMAGE -MATERIAL- <Version 0>]", true, false, LinkAction.OpenBeatmap)]
|
||||
[TestCase("I am important!", false, true)]
|
||||
[TestCase("feels important", true, true)]
|
||||
[TestCase("likes to post this [https://dev.ppy.sh/home link].", true, true, LinkAction.External)]
|
||||
[TestCase("likes to post this [https://osu.jvnko.boats/home link].", true, true, LinkAction.External)]
|
||||
public void TestActionAndImportantLinks(string text, bool isAction, bool isImportant, params LinkAction[] expectedActions)
|
||||
{
|
||||
addMessageWithChecks(text, isAction, isImportant, expectedActions);
|
||||
@@ -135,9 +135,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
int messageIndex = 0;
|
||||
|
||||
addEchoWithWait("sent!", "received!");
|
||||
addEchoWithWait("https://dev.ppy.sh/home", null, 500);
|
||||
addEchoWithWait("[https://dev.ppy.sh/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://dev.ppy.sh/home]", null, 5000);
|
||||
addEchoWithWait("https://osu.jvnko.boats/home", null, 500);
|
||||
addEchoWithWait("[https://osu.jvnko.boats/forum let's try multiple words too!]");
|
||||
addEchoWithWait("(long loading times! clickable while loading?)[https://osu.jvnko.boats/home]", null, 5000);
|
||||
|
||||
void addEchoWithWait(string text, string? completeText = null, double delay = 250)
|
||||
{
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
AddStep("show example score", () =>
|
||||
{
|
||||
var score = TestResources.CreateTestScoreInfo(createTestBeatmap(new RealmUser()));
|
||||
score.Mods = score.Mods.Append(new OsuModDifficultyAdjust()).ToArray();
|
||||
score.Mods = score.Mods.Append(new OsuModAutoplay()).ToArray();
|
||||
showPanel(score);
|
||||
});
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private void testInfoLabels(int expectedCount)
|
||||
{
|
||||
AddAssert("check info labels exists", () => infoWedge.Info.ChildrenOfType<BeatmapInfoWedge.WedgeInfoText.InfoLabel>().Any());
|
||||
AddAssert("check info labels count", () => infoWedge.Info.ChildrenOfType<BeatmapInfoWedge.WedgeInfoText.InfoLabel>().Count() == expectedCount);
|
||||
AddAssert("check info labels count", () => infoWedge.Info.ChildrenOfType<BeatmapInfoWedge.WedgeInfoText.InfoLabel>().Count() >= expectedCount);
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
|
||||
@@ -214,7 +214,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
assertGroup(results, 3, "Pending", pendingBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 4, "Graveyard", graveyardBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 5, "Local", localBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 6, "Unknown", noneBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 6, "Offline", noneBeatmap.Beatmaps, ref total);
|
||||
assertGroup(results, 7, "Loved", lovedBeatmap.Beatmaps, ref total);
|
||||
assertTotal(results, total);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
[Test]
|
||||
public void TestUnrankedBadge()
|
||||
{
|
||||
AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModDeflate() }));
|
||||
AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModAutoplay() }));
|
||||
AddUntilStep("Unranked badge shown", () => footerButtonMods.ChildrenOfType<FooterButtonMods.UnrankedBadge>().Single().Alpha == 1);
|
||||
AddStep(@"Clear selected mod", () => changeMods(Array.Empty<Mod>()));
|
||||
AddUntilStep("Unranked badge not shown", () => footerButtonMods.ChildrenOfType<FooterButtonMods.UnrankedBadge>().Single().Alpha == 0);
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
[Test]
|
||||
public void TestUnrankedBadge()
|
||||
{
|
||||
AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModDeflate() }));
|
||||
AddStep(@"Add unranked mod", () => changeMods(new[] { new OsuModAutoplay() }));
|
||||
AddAssert("Unranked badge shown", () => footerButtonMods.UnrankedBadge.Alpha == 1);
|
||||
AddStep(@"Clear selected mod", () => changeMods(Array.Empty<Mod>()));
|
||||
AddAssert("Unranked badge not shown", () => footerButtonMods.UnrankedBadge.Alpha == 0);
|
||||
|
||||
@@ -129,8 +129,9 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
setSliderValue("Circle Size", 99);
|
||||
|
||||
checkSliderAtValue("Circle Size", 11);
|
||||
checkBindableAtValue("Circle Size", 11);
|
||||
// debug build maximum value
|
||||
checkSliderAtValue("Circle Size", 13);
|
||||
checkBindableAtValue("Circle Size", 13);
|
||||
|
||||
setSliderValue("Approach Rate", -5);
|
||||
|
||||
|
||||
@@ -207,23 +207,23 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
AddUntilStep("any column dimmed", () => this.ChildrenOfType<ModColumn>().Any(column => !column.Active.Value));
|
||||
|
||||
ModSelectColumn lastColumn = null!;
|
||||
ModSelectColumn secondColumn = null!;
|
||||
|
||||
AddAssert("last column dimmed", () => !this.ChildrenOfType<ModColumn>().Last().Active.Value);
|
||||
AddStep("request scroll to last column", () =>
|
||||
AddAssert("second column dimmed", () => !this.ChildrenOfType<ModColumn>().ElementAt(2).Active.Value);
|
||||
AddStep("request scroll to second column", () =>
|
||||
{
|
||||
var lastDimContainer = this.ChildrenOfType<ModSelectOverlay.ColumnDimContainer>().Last();
|
||||
lastColumn = lastDimContainer.Column;
|
||||
lastDimContainer.RequestScroll?.Invoke(lastDimContainer);
|
||||
var secondDimContainer = this.ChildrenOfType<ModSelectOverlay.ColumnDimContainer>().ElementAt(2);
|
||||
secondColumn = secondDimContainer.Column;
|
||||
secondDimContainer.RequestScroll?.Invoke(secondDimContainer);
|
||||
});
|
||||
AddUntilStep("column undimmed", () => lastColumn.Active.Value);
|
||||
AddUntilStep("column undimmed", () => secondColumn.Active.Value);
|
||||
|
||||
AddStep("click panel", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(lastColumn.ChildrenOfType<ModPanel>().First());
|
||||
InputManager.MoveMouseTo(secondColumn.ChildrenOfType<ModPanel>().First());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddUntilStep("panel selected", () => lastColumn.ChildrenOfType<ModPanel>().First().Active.Value);
|
||||
AddUntilStep("panel selected", () => secondColumn.ChildrenOfType<ModPanel>().First().Active.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -810,7 +810,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddAssert("two columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 2);
|
||||
|
||||
AddStep("unset filter", () => modSelectOverlay.IsValidMod = _ => true);
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
|
||||
AddStep("filter out everything", () => modSelectOverlay.IsValidMod = _ => false);
|
||||
AddAssert("no columns visible", () => this.ChildrenOfType<ModColumn>().All(col => !col.IsPresent));
|
||||
@@ -839,7 +839,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
waitForColumnLoad();
|
||||
changeRuleset(0);
|
||||
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
|
||||
AddStep("set search", () => modSelectOverlay.SearchTerm = "HD");
|
||||
AddAssert("two columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 2);
|
||||
@@ -848,7 +848,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddAssert("no columns visible", () => this.ChildrenOfType<ModColumn>().All(col => !col.IsPresent));
|
||||
|
||||
AddStep("clear search bar", () => modSelectOverlay.SearchTerm = "");
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -863,7 +863,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
waitForColumnLoad();
|
||||
changeRuleset(0);
|
||||
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
|
||||
AddStep("set search", () => modSelectOverlay.SearchTerm = "fail");
|
||||
AddAssert("one column visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 1);
|
||||
@@ -871,7 +871,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("hide", () => modSelectOverlay.Hide());
|
||||
AddStep("show", () => modSelectOverlay.Show());
|
||||
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().All(col => col.IsPresent));
|
||||
AddAssert("all columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 4);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -880,13 +880,13 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
createScreen();
|
||||
|
||||
changeRuleset(0);
|
||||
AddAssert("5 columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 5);
|
||||
AddAssert("5 or more columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 5);
|
||||
|
||||
AddStep("change to ruleset without all mod types", () => Ruleset.Value = TestCustomisableModRuleset.CreateTestRulesetInfo());
|
||||
AddUntilStep("1 column visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 1);
|
||||
|
||||
changeRuleset(0);
|
||||
AddAssert("5 columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) == 5);
|
||||
AddAssert("5 or more columns visible", () => this.ChildrenOfType<ModColumn>().Count(col => col.IsPresent) >= 5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace osu.Game.Audio
|
||||
Logger.Log($"A {nameof(PreviewTrack)} was created without a containing {nameof(IPreviewTrackOwner)}. An owner should be added for correct behaviour.");
|
||||
}
|
||||
|
||||
protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo.OnlineID}.mp3");
|
||||
protected override Track GetTrack() => trackManager.Get($"https://osu.jvnko.boats/uploads/preview/{beatmapSetInfo.OnlineID}.mp3");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Collections;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
@@ -36,8 +37,8 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public ProcessBeatmapDelegate? ProcessBeatmap { private get; set; }
|
||||
|
||||
public BeatmapImporter(Storage storage, RealmAccess realm)
|
||||
: base(storage, realm)
|
||||
public BeatmapImporter(Storage storage, RealmAccess realm, OsuConfigManager? config = null)
|
||||
: base(storage, realm, config)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ using osu.Framework.IO.Stores;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.IO.Archives;
|
||||
@@ -59,7 +60,7 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
|
||||
public BeatmapManager(Storage storage, RealmAccess realm, IAPIProvider? api, AudioManager audioManager, IResourceStore<byte[]> gameResources, GameHost? host = null,
|
||||
WorkingBeatmap? defaultBeatmap = null, BeatmapDifficultyCache? difficultyCache = null, bool performOnlineLookups = false)
|
||||
WorkingBeatmap? defaultBeatmap = null, BeatmapDifficultyCache? difficultyCache = null, bool performOnlineLookups = false, OsuConfigManager? config = null)
|
||||
: base(storage, realm)
|
||||
{
|
||||
if (performOnlineLookups)
|
||||
@@ -75,7 +76,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
BeatmapTrackStore = audioManager.GetTrackStore(userResources);
|
||||
|
||||
beatmapImporter = CreateBeatmapImporter(storage, realm);
|
||||
beatmapImporter = CreateBeatmapImporter(storage, realm, config);
|
||||
beatmapImporter.ProcessBeatmap = (beatmapSet, scope) => ProcessBeatmap?.Invoke(beatmapSet, scope);
|
||||
beatmapImporter.PostNotification = obj => PostNotification?.Invoke(obj);
|
||||
|
||||
@@ -98,7 +99,7 @@ namespace osu.Game.Beatmaps
|
||||
return new WorkingBeatmapCache(BeatmapTrackStore, audioManager, resources, storage, defaultBeatmap, host);
|
||||
}
|
||||
|
||||
protected virtual BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm) => new BeatmapImporter(storage, realm);
|
||||
protected virtual BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm, OsuConfigManager? config = null) => new BeatmapImporter(storage, realm, config);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new beatmap set, backed by a <see cref="BeatmapSetInfo"/> model,
|
||||
|
||||