mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 10:33:30 +08:00
Merge branch 'master' into mod-accuracy-challenge
This commit is contained in:
commit
70cb23bbc9
@ -3,7 +3,7 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"jetbrains.resharper.globaltools": {
|
"jetbrains.resharper.globaltools": {
|
||||||
"version": "2022.1.1",
|
"version": "2022.2.3",
|
||||||
"commands": [
|
"commands": [
|
||||||
"jb"
|
"jb"
|
||||||
]
|
]
|
||||||
@ -21,7 +21,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ppy.localisationanalyser.tools": {
|
"ppy.localisationanalyser.tools": {
|
||||||
"version": "2022.417.0",
|
"version": "2022.809.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"localisation"
|
"localisation"
|
||||||
]
|
]
|
||||||
|
@ -1,2 +1,8 @@
|
|||||||
# Normalize all the line endings
|
# Normalize all the line endings
|
||||||
32a74f95a5c80a0ed18e693f13a47522099df5c3
|
32a74f95a5c80a0ed18e693f13a47522099df5c3
|
||||||
|
# Partial everything
|
||||||
|
7bc8908ca9c026fed1d831eb6e58df7624a8d614
|
||||||
|
# Add a few more missing partial specs
|
||||||
|
212d78865a6b5f091173a347bad5686834d1d5fe
|
||||||
|
# Add partial specs in mobile projects too
|
||||||
|
00c11b2b4e389e48f3995d63484a6bc66a7afbdb
|
||||||
|
3
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
3
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
@ -58,7 +58,8 @@ body:
|
|||||||
|
|
||||||
The default places to find the logs on desktop platforms are as follows:
|
The default places to find the logs on desktop platforms are as follows:
|
||||||
- `%AppData%/osu/logs` *on Windows*
|
- `%AppData%/osu/logs` *on Windows*
|
||||||
- `~/.local/share/osu/logs` *on Linux & macOS*
|
- `~/.local/share/osu/logs` *on Linux*
|
||||||
|
- `~/Library/Application Support/osu/logs` *on macOS*
|
||||||
|
|
||||||
If you have selected a custom location for the game files, you can find the `logs` folder there.
|
If you have selected a custom location for the game files, you can find the `logs` folder there.
|
||||||
|
|
||||||
|
50
.github/workflows/ci.yml
vendored
50
.github/workflows/ci.yml
vendored
@ -1,5 +1,11 @@
|
|||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
name: Continuous Integration
|
name: Continuous Integration
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
inspect-code:
|
inspect-code:
|
||||||
@ -25,13 +31,13 @@ jobs:
|
|||||||
run: dotnet tool restore
|
run: dotnet tool restore
|
||||||
|
|
||||||
- name: Restore Packages
|
- name: Restore Packages
|
||||||
run: dotnet restore
|
run: dotnet restore osu.Desktop.slnf
|
||||||
|
|
||||||
- name: Restore inspectcode cache
|
- name: Restore inspectcode cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/inspectcode
|
path: ${{ github.workspace }}/inspectcode
|
||||||
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', '.editorconfig', '.globalconfig', 'CodeAnalysis/*') }}
|
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', 'osu*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }}
|
||||||
|
|
||||||
- name: Dotnet code style
|
- 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 -p:EnforceCodeStyleInBuild=true
|
||||||
@ -82,7 +88,7 @@ jobs:
|
|||||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: dotnet test $pwd/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
|
run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" -- NUnit.ConsoleOut=0
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
# Attempt to upload results even if test fails.
|
# Attempt to upload results even if test fails.
|
||||||
@ -96,45 +102,47 @@ jobs:
|
|||||||
|
|
||||||
build-only-android:
|
build-only-android:
|
||||||
name: Build only (Android)
|
name: Build only (Android)
|
||||||
runs-on: macos-latest
|
runs-on: windows-latest
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
# Pin Xamarin.Android version to 11.2 for now to avoid build failures caused by a Xamarin-side regression.
|
|
||||||
# See: https://github.com/xamarin/xamarin-android/issues/6284
|
|
||||||
# This can be removed/reverted when the fix makes it to upstream and is deployed on github runners.
|
|
||||||
- name: Set default Xamarin SDK version
|
|
||||||
run: |
|
|
||||||
$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.2
|
|
||||||
|
|
||||||
- name: Install .NET 6.0.x
|
- name: Install .NET 6.0.x
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "6.0.x"
|
dotnet-version: "6.0.x"
|
||||||
|
|
||||||
# Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
|
- name: Install .NET workloads
|
||||||
# cannot accept .sln(f) files as arguments.
|
run: dotnet workload install maui-android
|
||||||
# Build just the main game for now.
|
|
||||||
- name: Build
|
- name: Compile
|
||||||
run: msbuild osu.Android/osu.Android.csproj /restore /p:Configuration=Debug
|
run: dotnet build -c Debug osu.Android.slnf
|
||||||
|
|
||||||
build-only-ios:
|
build-only-ios:
|
||||||
name: Build only (iOS)
|
name: Build only (iOS)
|
||||||
runs-on: macos-latest
|
# change to macos-latest once GitHub finishes migrating all repositories to macOS 12.
|
||||||
|
runs-on: macos-12
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# see https://github.com/actions/runner-images/issues/6771#issuecomment-1354713617
|
||||||
|
# remove once all workflow VMs use Xcode 14.1
|
||||||
|
- name: Set Xcode Version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo xcode-select -s "/Applications/Xcode_14.1.app"
|
||||||
|
echo "MD_APPLE_SDK_ROOT=/Applications/Xcode_14.1.app" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Install .NET 6.0.x
|
- name: Install .NET 6.0.x
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "6.0.x"
|
dotnet-version: "6.0.x"
|
||||||
|
|
||||||
# Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
|
- name: Install .NET Workloads
|
||||||
# cannot accept .sln(f) files as arguments.
|
run: dotnet workload install maui-ios
|
||||||
# Build just the main game for now.
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: msbuild osu.iOS/osu.iOS.csproj /restore /p:Configuration=Debug
|
run: dotnet build -c Debug osu.iOS
|
||||||
|
6
.github/workflows/report-nunit.yml
vendored
6
.github/workflows/report-nunit.yml
vendored
@ -8,8 +8,12 @@ on:
|
|||||||
workflows: ["Continuous Integration"]
|
workflows: ["Continuous Integration"]
|
||||||
types:
|
types:
|
||||||
- completed
|
- completed
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
annotate:
|
annotate:
|
||||||
|
permissions:
|
||||||
|
checks: write # to create checks (dorny/test-reporter)
|
||||||
|
|
||||||
name: Annotate CI run with test results
|
name: Annotate CI run with test results
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event.workflow_run.conclusion != 'cancelled' }}
|
if: ${{ github.event.workflow_run.conclusion != 'cancelled' }}
|
||||||
@ -24,7 +28,7 @@ jobs:
|
|||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- name: Annotate CI run with test results
|
- name: Annotate CI run with test results
|
||||||
uses: dorny/test-reporter@v1.4.2
|
uses: dorny/test-reporter@v1.6.0
|
||||||
with:
|
with:
|
||||||
artifact: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
|
artifact: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
|
||||||
name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}})
|
name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}})
|
||||||
|
3
.github/workflows/sentry-release.yml
vendored
3
.github/workflows/sentry-release.yml
vendored
@ -5,6 +5,9 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- '*'
|
- '*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # to fetch code (actions/checkout)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
sentry_release:
|
sentry_release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -53,3 +53,7 @@ dotnet_diagnostic.CA2225.severity = none
|
|||||||
|
|
||||||
# Banned APIs
|
# Banned APIs
|
||||||
dotnet_diagnostic.RS0030.severity = error
|
dotnet_diagnostic.RS0030.severity = error
|
||||||
|
|
||||||
|
# Temporarily disable analysing CanBeNull = true in NRT contexts due to mobile issues.
|
||||||
|
# See: https://github.com/ppy/osu/pull/19677
|
||||||
|
dotnet_diagnostic.OSUF001.severity = none
|
155
CONTRIBUTING.md
155
CONTRIBUTING.md
@ -2,136 +2,87 @@
|
|||||||
|
|
||||||
Thank you for showing interest in the development of osu!. We aim to provide a good collaborating environment for everyone involved, and as such have decided to list some of the most important things to keep in mind in the process. The guidelines below have been chosen based on past experience.
|
Thank you for showing interest in the development of osu!. We aim to provide a good collaborating environment for everyone involved, and as such have decided to list some of the most important things to keep in mind in the process. The guidelines below have been chosen based on past experience.
|
||||||
|
|
||||||
These are not "official rules" *per se*, but following them will help everyone deal with things in the most efficient manner.
|
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
1. [I would like to submit an issue!](#i-would-like-to-submit-an-issue)
|
1. [Reporting bugs](#reporting-bugs)
|
||||||
2. [I would like to submit a pull request!](#i-would-like-to-submit-a-pull-request)
|
2. [Providing general feedback](#providing-general-feedback)
|
||||||
|
3. [Issue or discussion?](#issue-or-discussion)
|
||||||
|
4. [Submitting pull requests](#submitting-pull-requests)
|
||||||
|
5. [Resources](#resources)
|
||||||
|
|
||||||
## I would like to submit an issue!
|
## Reporting bugs
|
||||||
|
|
||||||
Issues, bug reports and feature suggestions are welcomed, though please keep in mind that at any point in time, hundreds of issues are open, which vary in severity and the amount of time needed to address them. As such it's not uncommon for issues to remain unresolved for a long time or even closed outright if they are deemed not important enough to fix in the foreseeable future. Issues that are required to "go live" or otherwise achieve parity with stable are prioritised the most.
|
A **bug** is a situation in which there is something clearly *and objectively* wrong with the game. Examples of applicable bug reports are:
|
||||||
|
|
||||||
* **Before submitting an issue, try searching existing issues first.**
|
- The game crashes to desktop when I start a beatmap
|
||||||
|
- Friends appear twice in the friend listing
|
||||||
|
- The game slows down a lot when I play this specific map
|
||||||
|
- A piece of text is overlapping another piece of text on the screen
|
||||||
|
|
||||||
For housekeeping purposes, we close issues that overlap with or duplicate other pre-existing issues - you can help us not to have to do that by searching existing issues yourself first. The issue search box, as well as the issue tag system, are tools you can use to check if an issue has been reported before.
|
To track bug reports, we primarily use GitHub **issues**. When opening an issue, please keep in mind the following:
|
||||||
|
|
||||||
* **When submitting a bug report, please try to include as much detail as possible.**
|
- Before opening the issue, please search for any similar existing issues using the text search bar and the issue labels. This includes both open and closed issues (we may have already fixed something, but the fix hasn't yet been released).
|
||||||
|
- When opening the issue, please fill out as much of the issue template as you can. In particular, please make sure to include logs and screenshots as much as possible. The instructions on how to find the log files are included in the issue template.
|
||||||
|
- We may ask you for follow-up information to reproduce or debug the problem. Please look out for this and provide follow-up info if we request it.
|
||||||
|
|
||||||
Bugs are not equal - some of them will be reproducible every time on pretty much all hardware, while others will be hard to track down due to being specific to particular hardware or even somewhat random in nature. As such, providing as much detail as possible when reporting a bug is hugely appreciated. A good starting set of information consists of:
|
If we cannot reproduce the issue, it is deemed low priority, or it is deemed to be specific to your setup in some way, the issue may be downgraded to a discussion. This will be done by a maintainer for you.
|
||||||
|
|
||||||
* the in-game logs, which are located at:
|
## Providing general feedback
|
||||||
* `%AppData%/osu/logs` (on Windows),
|
|
||||||
* `~/.local/share/osu/logs` (on Linux and macOS),
|
|
||||||
* `Android/data/sh.ppy.osulazer/files/logs` (on Android),
|
|
||||||
* on iOS they can be obtained by connecting your device to your desktop and [copying the `logs` directory from the app's own document storage using iTunes](https://support.apple.com/en-us/HT201301#copy-to-computer),
|
|
||||||
* your system specifications (including the operating system and platform you are playing on),
|
|
||||||
* a reproduction scenario (list of steps you have performed leading up to the occurrence of the bug),
|
|
||||||
* a video or picture of the bug, if at all possible.
|
|
||||||
|
|
||||||
* **Provide more information when asked to do so.**
|
If you wish to:
|
||||||
|
|
||||||
Sometimes when a bug is more elusive or complicated, none of the information listed above will pinpoint a concrete cause of the problem. In this case we will most likely ask you for additional info, such as a Windows Event Log dump or a copy of your local osu! database (`client.db`). Providing that information is beneficial to both parties - we can track down the problem better, and hopefully fix it for you at some point once we know where it is!
|
- provide *subjective* feedback on the game (about how the UI looks, about how the default skin works, about game mechanics, about how the PP and scoring systems work, etc.),
|
||||||
|
- suggest a new feature to be added to the game,
|
||||||
|
- report a non-specific problem with the game that you think may be connected to your hardware or operating system specifically,
|
||||||
|
|
||||||
* **When submitting a feature proposal, please describe it in the most understandable way you can.**
|
then it is generally best to start with a **discussion** first. Discussions are a good avenue to group subjective feedback on a single topic, or gauge interest in a particular feature request.
|
||||||
|
|
||||||
Communicating your idea for a feature can often be hard, and we would like to avoid any misunderstandings. As such, please try to explain your idea in a short, but understandable manner - it's best to avoid jargon or terms and references that could be considered obscure. A mock-up picture (doesn't have to be good!) of the feature can also go a long way in explaining.
|
When opening a discussion, please keep in mind the following:
|
||||||
|
|
||||||
* **Refrain from posting "+1" comments.**
|
- Use the search function to see if your idea has been proposed before, or if there is already a thread about a particular issue you wish to raise.
|
||||||
|
- If proposing a feature, please try to explain the feature in as much detail as possible.
|
||||||
|
- If you're reporting a non-specific problem, please provide applicable logs, screenshots, or video that illustrate the issue.
|
||||||
|
|
||||||
If an issue has already been created, saying that you also experience it without providing any additional details doesn't really help us in any way. To express support for a proposal or indicate that you are also affected by a particular bug, you can use comment reactions instead.
|
If a discussion gathers enough traction, then it may be converted into an issue. This will be done by a maintainer for you.
|
||||||
|
|
||||||
* **Refrain from asking if an issue has been resolved yet.**
|
## Issue or discussion?
|
||||||
|
|
||||||
As mentioned above, the issue tracker has hundreds of issues open at any given time. Currently the game is being worked on by two members of the core team, and a handful of outside contributors who offer their free time to help out. As such, it can happen that an issue gets placed on the backburner due to being less important; generally posting a comment demanding its resolution some months or years after it is reported is not very likely to increase its priority.
|
We realise that the line between an issue and a discussion may be fuzzy, so while we ask you to use your best judgement based on the description above, please don't think about it too hard either. Feedback in a slightly wrong place is better than no feedback at all.
|
||||||
|
|
||||||
* **Avoid long discussions about non-development topics.**
|
When in doubt, it's probably best to start with a discussion first. We will escalate to issues as needed.
|
||||||
|
|
||||||
GitHub is mostly a developer space, and as such isn't really fit for lengthened discussions about gameplay mechanics (which might not even be in any way confirmed for the final release) and similar non-technical matters. Such matters are probably best addressed at the osu! forums.
|
## Submitting pull requests
|
||||||
|
|
||||||
## I would like to submit a pull request!
|
While pull requests from unaffiliated contributors are welcome, please note that due to significant community interest and limited review throughput, the core team's primary focus is on the issues which are currently [on the roadmap](https://github.com/orgs/ppy/projects/7/views/6). Reviewing PRs that fall outside of the scope of the roadmap is done on a best-effort basis, so please be aware that it may take a while before a core maintainer gets around to review your change.
|
||||||
|
|
||||||
We also welcome pull requests from unaffiliated contributors. The [issue tracker](https://github.com/ppy/osu/issues) should provide plenty of issues that you can work on; we also mark issues that we think would be good for newcomers with the [`good-first-issue`](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue) label.
|
The [issue tracker](https://github.com/ppy/osu/issues) should provide plenty of issues to start with. We also have a [`good-first-issue`](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue) label, although from experience it is not used very often, as it is relatively rare that we can spot an issue that will definitively be a good first issue for a new contributor regardless of their programming experience.
|
||||||
|
|
||||||
However, do keep in mind that the core team is committed to bringing osu!(lazer) up to par with osu!(stable) first and foremost, so depending on what your contribution concerns, it might not be merged and released right away. Our approach to managing issues and their priorities is described [in the wiki](https://github.com/ppy/osu/wiki/Project-management).
|
In the case of simple issues, a direct PR is okay. However, if you decide to work on an existing issue which doesn't seem trivial, **please ask us first**. This way we can try to estimate if it is a good fit for you and provide the correct direction on how to address it. In addition, note that while we do not rule out external contributors from working on roadmapped issues, we will generally prefer to handle them ourselves unless they're not very time sensitive.
|
||||||
|
|
||||||
Here are some key things to note before jumping in:
|
If you'd like to propose a subjective change to one of the visual aspects of the game, or there is a bigger task you'd like to work on, but there is no corresponding issue or discussion thread yet for it, **please open a discussion or issue first** to avoid wasted effort. This in particular applies if you want to work on [one of the available designs from the osu! public Figma library](https://www.figma.com/file/6m10GiGEncVFWmgOoSyakH/osu!-Figma-Library).
|
||||||
|
|
||||||
* **Make sure you are comfortable with C\# and your development environment.**
|
Aside from the above, below is a brief checklist of things to watch out when you're preparing your code changes:
|
||||||
|
|
||||||
While we are accepting of all kinds of contributions, we also have a certain quality standard we'd like to uphold and limited time to review your code. Therefore, we would like to avoid providing entry-level advice, and as such if you're not very familiar with C\# as a programming language, we'd recommend that you start off with a few personal projects to get acquainted with the language's syntax, toolchain and principles of object-oriented programming first.
|
- Make sure you're comfortable with the principles of object-oriented programming, the syntax of C\# and your development environment.
|
||||||
|
- Make sure you are familiar with [git](https://git-scm.com/) and [the pull request workflow](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests).
|
||||||
|
- Please do not make code changes via the GitHub web interface.
|
||||||
|
- Please add tests for your changes. We expect most new features and bugfixes to have test coverage, unless the effort of adding them is prohibitive. The visual testing methodology we use is described in more detail [here](https://github.com/ppy/osu-framework/wiki/Development-and-Testing).
|
||||||
|
- Please run tests and code style analysis (via `InspectCode.{ps1,sh}` scripts in the root of this repository) before opening the PR. This is particularly important if you're a first-time contributor, as CI will not run for your PR until we allow it to do so.
|
||||||
|
|
||||||
In addition, please take the time to take a look at and get acquainted with the [development and testing](https://github.com/ppy/osu-framework/wiki/Development-and-Testing) procedure we have set up.
|
After you're done with your changes and you wish to open the PR, please observe the following recommendations:
|
||||||
|
|
||||||
* **Make sure you are familiar with git and the pull request workflow.**
|
- Please submit the pull request from a [topic branch](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#_topic_branch) (not `master`), and keep the *Allow edits from maintainers* check box selected, so that we can push fixes to your PR if necessary.
|
||||||
|
- Please avoid pushing untested or incomplete code.
|
||||||
|
- Please do not force-push or rebase unless we ask you to.
|
||||||
|
- Please do not merge `master` continually if there are no conflicts to resolve. We will do this for you when the change is ready for merge.
|
||||||
|
|
||||||
[git](https://git-scm.com/) is a distributed version control system that might not be very intuitive at the beginning if you're not familiar with version control. In particular, projects using git have a particular workflow for submitting code changes, which is called the pull request workflow.
|
We are highly committed to quality when it comes to the osu! project. This means that contributions from less experienced community members can take multiple rounds of review to get to a mergeable state. We try our utmost best to never conflate a person with the code they authored, and to keep the discussion focused on the code at all times. Please consider our comments and requests a learning experience.
|
||||||
|
|
||||||
To make things run more smoothly, we recommend that you look up some online resources to familiarise yourself with the git vocabulary and commands, and practice working with forks and submitting pull requests at your own pace. A high-level overview of the process can be found in [this article by GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests).
|
If you're uncertain about some part of the codebase or some inner workings of the game and framework, please reach out either by leaving a comment in the relevant issue, discussion, or PR thread, or by posting a message in the [development Discord server](https://discord.gg/ppy). We will try to help you as much as we can.
|
||||||
|
|
||||||
* **Double-check designs before starting work on new functionality.**
|
## Resources
|
||||||
|
|
||||||
When implementing new features, keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention of having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time to ensure no effort is wasted.
|
- [Development roadmap](https://github.com/orgs/ppy/projects/7/views/6): What the core team is currently working on
|
||||||
|
- [`ppy/osu-framework` wiki](https://github.com/ppy/osu-framework/wiki): Contains introductory information about osu!framework, the bespoke 2D game framework we use for the game
|
||||||
* **Make sure to submit pull requests off of a topic branch.**
|
- [`ppy/osu` wiki](https://github.com/ppy/osu/wiki): Contains articles about various technical aspects of the game
|
||||||
|
- [Public Figma library](https://www.figma.com/file/6m10GiGEncVFWmgOoSyakH/osu!-Figma-Library): Contains finished and draft designs for osu!
|
||||||
As described in the article linked in the previous point, topic branches help you parallelise your work and separate it from the main `master` branch, and additionally are easier for maintainers to work with. Working with multiple `master` branches across many remotes is difficult to keep track of, and it's easy to make a mistake and push to the wrong `master` branch by accident.
|
|
||||||
|
|
||||||
* **Refrain from making changes through the GitHub web interface.**
|
|
||||||
|
|
||||||
Even though GitHub provides an option to edit code or replace files in the repository using the web interface, we strongly discourage using it in most scenarios. Editing files this way is inefficient and likely to introduce whitespace or file encoding changes that make it more difficult to review the code.
|
|
||||||
|
|
||||||
Code written through the web interface will also very likely be questioned outright by the reviewers, as it is likely that it has not been properly tested or that it will fail continuous integration checks. We strongly encourage using an IDE like [Visual Studio](https://visualstudio.microsoft.com/), [Visual Studio Code](https://code.visualstudio.com/) or [JetBrains Rider](https://www.jetbrains.com/rider/) instead.
|
|
||||||
|
|
||||||
* **Add tests for your code whenever possible.**
|
|
||||||
|
|
||||||
Automated tests are an essential part of a quality and reliable codebase. They help to make the code more maintainable by ensuring it is safe to reorganise (or refactor) the code in various ways, and also prevent regressions - bugs that resurface after having been fixed at some point in the past. If it is viable, please put in the time to add tests, so that the changes you make can last for a (hopefully) very long time.
|
|
||||||
|
|
||||||
* **Run tests before opening a pull request.**
|
|
||||||
|
|
||||||
Tying into the previous point, sometimes changes in one part of the codebase can result in unpredictable changes in behaviour in other pieces of the code. This is why it is best to always try to run tests before opening a PR.
|
|
||||||
|
|
||||||
Continuous integration will always run the tests for you (and us), too, but it is best not to rely on it, as there might be many builds queued at any time. Running tests on your own will help you be more certain that at the point of clicking the "Create pull request" button, your changes are as ready as can be.
|
|
||||||
|
|
||||||
* **Run code style analysis before opening a pull request.**
|
|
||||||
|
|
||||||
As part of continuous integration, we also run code style analysis, which is supposed to make sure that your code is formatted the same way as all the pre-existing code in the repository. The reason we enforce a particular code style everywhere is to make sure the codebase is consistent in that regard - having one whitespace convention in one place and another one elsewhere causes disorganisation.
|
|
||||||
|
|
||||||
* **Make sure that the pull request is complete before opening it.**
|
|
||||||
|
|
||||||
Whether it's fixing a bug or implementing new functionality, it's best that you make sure that the change you want to submit as a pull request is as complete as it can be before clicking the *Create pull request* button. Having to track if a pull request is ready for review or not places additional burden on reviewers.
|
|
||||||
|
|
||||||
Draft pull requests are an option, but use them sparingly and within reason. They are best suited to discuss code changes that cannot be easily described in natural language or have a potential large impact on the future direction of the project. When in doubt, don't open drafts unless a maintainer asks you to do so.
|
|
||||||
|
|
||||||
* **Only push code when it's ready.**
|
|
||||||
|
|
||||||
As an extension of the above, when making changes to an already-open PR, please try to only push changes you are reasonably certain of. Pushing after every commit causes the continuous integration build queue to grow in size, slowing down work and taking up time that could be spent verifying other changes.
|
|
||||||
|
|
||||||
* **Make sure to keep the *Allow edits from maintainers* check box checked.**
|
|
||||||
|
|
||||||
To speed up the merging process, collaborators and team members will sometimes want to push changes to your branch themselves, to make minor code style adjustments or to otherwise refactor the code without having to describe how they'd like the code to look like in painstaking detail. Having the *Allow edits from maintainers* check box checked lets them do that; without it they are forced to report issues back to you and wait for you to address them.
|
|
||||||
|
|
||||||
* **Refrain from continually merging the master branch back to the PR.**
|
|
||||||
|
|
||||||
Unless there are merge conflicts that need resolution, there is no need to keep merging `master` back to a branch over and over again. One of the maintainers will merge `master` themselves before merging the PR itself anyway, and continual merge commits can cause CI to get overwhelmed due to queueing up too many builds.
|
|
||||||
|
|
||||||
* **Refrain from force-pushing to the PR branch.**
|
|
||||||
|
|
||||||
Force-pushing should be avoided, as it can lead to accidentally overwriting a maintainer's changes or CI building wrong commits. We value all history in the project, so there is no need to squash or amend commits in most cases.
|
|
||||||
|
|
||||||
The cases in which force-pushing is warranted are very rare (such as accidentally leaking sensitive info in one of the files committed, adding unrelated files, or mis-merging a dependent PR).
|
|
||||||
|
|
||||||
* **Be patient when waiting for the code to be reviewed and merged.**
|
|
||||||
|
|
||||||
As much as we'd like to review all contributions as fast as possible, our time is limited, as team members have to work on their own tasks in addition to reviewing code. As such, work needs to be prioritised, and it can unfortunately take weeks or months for your PR to be merged, depending on how important it is deemed to be.
|
|
||||||
|
|
||||||
* **Don't mistake criticism of code for criticism of your person.**
|
|
||||||
|
|
||||||
As mentioned before, we are highly committed to quality when it comes to the osu! project. This means that contributions from less experienced community members can take multiple rounds of review to get to a mergeable state. We try our utmost best to never conflate a person with the code they authored, and to keep the discussion focused on the code at all times. Please consider our comments and requests a learning experience, and don't treat it as a personal attack.
|
|
||||||
|
|
||||||
* **Feel free to reach out for help.**
|
|
||||||
|
|
||||||
If you're uncertain about some part of the codebase or some inner workings of the game and framework, please reach out either by leaving a comment in the relevant issue or PR thread, or by posting a message in the [development Discord server](https://discord.gg/ppy). We will try to help you as much as we can.
|
|
||||||
|
|
||||||
When it comes to which form of communication is best, GitHub generally lends better to longer-form discussions, while Discord is better for snappy call-and-response answers. Use your best discretion when deciding, and try to keep a single discussion in one place instead of moving back and forth.
|
|
||||||
|
@ -6,8 +6,6 @@ T:System.IComparable;Don't use non-generic IComparable. Use generic version inst
|
|||||||
T:SixLabors.ImageSharp.IDeepCloneable`1;Use osu.Game.Utils.IDeepCloneable<T> instead.
|
T:SixLabors.ImageSharp.IDeepCloneable`1;Use osu.Game.Utils.IDeepCloneable<T> instead.
|
||||||
M:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText.
|
M:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText.
|
||||||
M:osu.Framework.Bindables.IBindableList`1.GetBoundCopy();Fails on iOS. Use manual ctor + BindTo instead. (see https://github.com/mono/mono/issues/19900)
|
M:osu.Framework.Bindables.IBindableList`1.GetBoundCopy();Fails on iOS. Use manual ctor + BindTo instead. (see https://github.com/mono/mono/issues/19900)
|
||||||
T:Microsoft.EntityFrameworkCore.Internal.EnumerableExtensions;Don't use internal extension methods.
|
|
||||||
T:Microsoft.EntityFrameworkCore.Internal.TypeExtensions;Don't use internal extension methods.
|
|
||||||
T:NuGet.Packaging.CollectionExtensions;Don't use internal extension methods.
|
T:NuGet.Packaging.CollectionExtensions;Don't use internal extension methods.
|
||||||
M:System.Enum.HasFlag(System.Enum);Use osu.Framework.Extensions.EnumExtensions.HasFlagFast<T>() instead.
|
M:System.Enum.HasFlag(System.Enum);Use osu.Framework.Extensions.EnumExtensions.HasFlagFast<T>() instead.
|
||||||
M:Realms.IRealmCollection`1.SubscribeForNotifications`1(Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IRealmCollection<T>,NotificationCallbackDelegate<T>) instead.
|
M:Realms.IRealmCollection`1.SubscribeForNotifications`1(Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IRealmCollection<T>,NotificationCallbackDelegate<T>) instead.
|
||||||
@ -16,3 +14,12 @@ M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Linq.IQueryable
|
|||||||
M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Generic.IList{``0},Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IList<T>,NotificationCallbackDelegate<T>) instead.
|
M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Generic.IList{``0},Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IList<T>,NotificationCallbackDelegate<T>) instead.
|
||||||
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
|
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
|
||||||
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
|
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
|
||||||
|
M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever.
|
||||||
|
M:System.Char.ToLower(System.Char);char.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
|
||||||
|
M:System.Char.ToUpper(System.Char);char.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
|
||||||
|
M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
||||||
|
M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
||||||
|
M:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead.
|
||||||
|
M:Humanizer.InflectorExtensions.Camelize(System.String);Humanizer's .Camelize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToCamelCase() instead.
|
||||||
|
M:Humanizer.InflectorExtensions.Underscore(System.String);Humanizer's .Underscore() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToSnakeCase() instead.
|
||||||
|
M:Humanizer.InflectorExtensions.Kebaberize(System.String);Humanizer's .Kebaberize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToKebabCase() instead.
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<!-- Contains required properties for osu!framework projects. -->
|
<!-- Contains required properties for osu!framework projects. -->
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup Label="C#">
|
<PropertyGroup Label="C#">
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>9.0</LangVersion>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest>
|
<ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest>
|
||||||
|
86
Gemfile.lock
86
Gemfile.lock
@ -3,25 +3,25 @@ GEM
|
|||||||
specs:
|
specs:
|
||||||
CFPropertyList (3.0.5)
|
CFPropertyList (3.0.5)
|
||||||
rexml
|
rexml
|
||||||
addressable (2.8.0)
|
addressable (2.8.1)
|
||||||
public_suffix (>= 2.0.2, < 5.0)
|
public_suffix (>= 2.0.2, < 6.0)
|
||||||
artifactory (3.0.15)
|
artifactory (3.0.15)
|
||||||
atomos (0.1.3)
|
atomos (0.1.3)
|
||||||
aws-eventstream (1.2.0)
|
aws-eventstream (1.2.0)
|
||||||
aws-partitions (1.570.0)
|
aws-partitions (1.653.0)
|
||||||
aws-sdk-core (3.130.0)
|
aws-sdk-core (3.166.0)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
aws-partitions (~> 1, >= 1.525.0)
|
aws-partitions (~> 1, >= 1.651.0)
|
||||||
|
aws-sigv4 (~> 1.5)
|
||||||
|
jmespath (~> 1, >= 1.6.1)
|
||||||
|
aws-sdk-kms (1.59.0)
|
||||||
|
aws-sdk-core (~> 3, >= 3.165.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
jmespath (~> 1.0)
|
aws-sdk-s3 (1.117.1)
|
||||||
aws-sdk-kms (1.55.0)
|
aws-sdk-core (~> 3, >= 3.165.0)
|
||||||
aws-sdk-core (~> 3, >= 3.127.0)
|
|
||||||
aws-sigv4 (~> 1.1)
|
|
||||||
aws-sdk-s3 (1.113.0)
|
|
||||||
aws-sdk-core (~> 3, >= 3.127.0)
|
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.4)
|
aws-sigv4 (~> 1.4)
|
||||||
aws-sigv4 (1.4.0)
|
aws-sigv4 (1.5.2)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
babosa (1.0.4)
|
babosa (1.0.4)
|
||||||
claide (1.1.0)
|
claide (1.1.0)
|
||||||
@ -34,10 +34,10 @@ GEM
|
|||||||
rake (>= 12.0.0, < 14.0.0)
|
rake (>= 12.0.0, < 14.0.0)
|
||||||
domain_name (0.5.20190701)
|
domain_name (0.5.20190701)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
dotenv (2.7.6)
|
dotenv (2.8.1)
|
||||||
emoji_regex (3.2.3)
|
emoji_regex (3.2.3)
|
||||||
excon (0.92.1)
|
excon (0.93.1)
|
||||||
faraday (1.10.0)
|
faraday (1.10.2)
|
||||||
faraday-em_http (~> 1.0)
|
faraday-em_http (~> 1.0)
|
||||||
faraday-em_synchrony (~> 1.0)
|
faraday-em_synchrony (~> 1.0)
|
||||||
faraday-excon (~> 1.1)
|
faraday-excon (~> 1.1)
|
||||||
@ -56,8 +56,8 @@ GEM
|
|||||||
faraday-em_synchrony (1.0.0)
|
faraday-em_synchrony (1.0.0)
|
||||||
faraday-excon (1.1.0)
|
faraday-excon (1.1.0)
|
||||||
faraday-httpclient (1.0.1)
|
faraday-httpclient (1.0.1)
|
||||||
faraday-multipart (1.0.3)
|
faraday-multipart (1.0.4)
|
||||||
multipart-post (>= 1.2, < 3)
|
multipart-post (~> 2)
|
||||||
faraday-net_http (1.0.1)
|
faraday-net_http (1.0.1)
|
||||||
faraday-net_http_persistent (1.2.0)
|
faraday-net_http_persistent (1.2.0)
|
||||||
faraday-patron (1.0.0)
|
faraday-patron (1.0.0)
|
||||||
@ -66,7 +66,7 @@ GEM
|
|||||||
faraday_middleware (1.2.0)
|
faraday_middleware (1.2.0)
|
||||||
faraday (~> 1.0)
|
faraday (~> 1.0)
|
||||||
fastimage (2.2.6)
|
fastimage (2.2.6)
|
||||||
fastlane (2.205.1)
|
fastlane (2.210.1)
|
||||||
CFPropertyList (>= 2.3, < 4.0.0)
|
CFPropertyList (>= 2.3, < 4.0.0)
|
||||||
addressable (>= 2.8, < 3.0.0)
|
addressable (>= 2.8, < 3.0.0)
|
||||||
artifactory (~> 3.0)
|
artifactory (~> 3.0)
|
||||||
@ -110,9 +110,9 @@ GEM
|
|||||||
souyuz (= 0.11.1)
|
souyuz (= 0.11.1)
|
||||||
fastlane-plugin-xamarin (0.6.3)
|
fastlane-plugin-xamarin (0.6.3)
|
||||||
gh_inspector (1.1.3)
|
gh_inspector (1.1.3)
|
||||||
google-apis-androidpublisher_v3 (0.16.0)
|
google-apis-androidpublisher_v3 (0.29.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.9.0, < 2.a)
|
||||||
google-apis-core (0.4.2)
|
google-apis-core (0.9.1)
|
||||||
addressable (~> 2.5, >= 2.5.1)
|
addressable (~> 2.5, >= 2.5.1)
|
||||||
googleauth (>= 0.16.2, < 2.a)
|
googleauth (>= 0.16.2, < 2.a)
|
||||||
httpclient (>= 2.8.1, < 3.a)
|
httpclient (>= 2.8.1, < 3.a)
|
||||||
@ -121,27 +121,27 @@ GEM
|
|||||||
retriable (>= 2.0, < 4.a)
|
retriable (>= 2.0, < 4.a)
|
||||||
rexml
|
rexml
|
||||||
webrick
|
webrick
|
||||||
google-apis-iamcredentials_v1 (0.10.0)
|
google-apis-iamcredentials_v1 (0.15.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.9.0, < 2.a)
|
||||||
google-apis-playcustomapp_v1 (0.7.0)
|
google-apis-playcustomapp_v1 (0.12.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.9.1, < 2.a)
|
||||||
google-apis-storage_v1 (0.11.0)
|
google-apis-storage_v1 (0.19.0)
|
||||||
google-apis-core (>= 0.4, < 2.a)
|
google-apis-core (>= 0.9.0, < 2.a)
|
||||||
google-cloud-core (1.6.0)
|
google-cloud-core (1.6.0)
|
||||||
google-cloud-env (~> 1.0)
|
google-cloud-env (~> 1.0)
|
||||||
google-cloud-errors (~> 1.0)
|
google-cloud-errors (~> 1.0)
|
||||||
google-cloud-env (1.6.0)
|
google-cloud-env (1.6.0)
|
||||||
faraday (>= 0.17.3, < 3.0)
|
faraday (>= 0.17.3, < 3.0)
|
||||||
google-cloud-errors (1.2.0)
|
google-cloud-errors (1.3.0)
|
||||||
google-cloud-storage (1.36.1)
|
google-cloud-storage (1.43.0)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
digest-crc (~> 0.4)
|
digest-crc (~> 0.4)
|
||||||
google-apis-iamcredentials_v1 (~> 0.1)
|
google-apis-iamcredentials_v1 (~> 0.1)
|
||||||
google-apis-storage_v1 (~> 0.1)
|
google-apis-storage_v1 (~> 0.19.0)
|
||||||
google-cloud-core (~> 1.6)
|
google-cloud-core (~> 1.6)
|
||||||
googleauth (>= 0.16.2, < 2.a)
|
googleauth (>= 0.16.2, < 2.a)
|
||||||
mini_mime (~> 1.0)
|
mini_mime (~> 1.0)
|
||||||
googleauth (1.1.2)
|
googleauth (1.3.0)
|
||||||
faraday (>= 0.17.3, < 3.a)
|
faraday (>= 0.17.3, < 3.a)
|
||||||
jwt (>= 1.4, < 3.0)
|
jwt (>= 1.4, < 3.0)
|
||||||
memoist (~> 0.16)
|
memoist (~> 0.16)
|
||||||
@ -149,30 +149,30 @@ GEM
|
|||||||
os (>= 0.9, < 2.0)
|
os (>= 0.9, < 2.0)
|
||||||
signet (>= 0.16, < 2.a)
|
signet (>= 0.16, < 2.a)
|
||||||
highline (2.0.3)
|
highline (2.0.3)
|
||||||
http-cookie (1.0.4)
|
http-cookie (1.0.5)
|
||||||
domain_name (~> 0.5)
|
domain_name (~> 0.5)
|
||||||
httpclient (2.8.3)
|
httpclient (2.8.3)
|
||||||
jmespath (1.6.1)
|
jmespath (1.6.1)
|
||||||
json (2.6.1)
|
json (2.6.2)
|
||||||
jwt (2.3.0)
|
jwt (2.5.0)
|
||||||
memoist (0.16.2)
|
memoist (0.16.2)
|
||||||
mini_magick (4.11.0)
|
mini_magick (4.11.0)
|
||||||
mini_mime (1.1.2)
|
mini_mime (1.1.2)
|
||||||
mini_portile2 (2.7.1)
|
mini_portile2 (2.8.0)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
multipart-post (2.0.0)
|
multipart-post (2.0.0)
|
||||||
nanaimo (0.3.0)
|
nanaimo (0.3.0)
|
||||||
naturally (2.2.1)
|
naturally (2.2.1)
|
||||||
nokogiri (1.13.1)
|
nokogiri (1.13.9)
|
||||||
mini_portile2 (~> 2.7.0)
|
mini_portile2 (~> 2.8.0)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
optparse (0.1.1)
|
optparse (0.1.1)
|
||||||
os (1.1.4)
|
os (1.1.4)
|
||||||
plist (3.6.0)
|
plist (3.6.0)
|
||||||
public_suffix (4.0.6)
|
public_suffix (5.0.0)
|
||||||
racc (1.6.0)
|
racc (1.6.0)
|
||||||
rake (13.0.6)
|
rake (13.0.6)
|
||||||
representable (3.1.1)
|
representable (3.2.0)
|
||||||
declarative (< 0.1.0)
|
declarative (< 0.1.0)
|
||||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||||
uber (< 0.2.0)
|
uber (< 0.2.0)
|
||||||
@ -182,9 +182,9 @@ GEM
|
|||||||
ruby2_keywords (0.0.5)
|
ruby2_keywords (0.0.5)
|
||||||
rubyzip (2.3.2)
|
rubyzip (2.3.2)
|
||||||
security (0.1.3)
|
security (0.1.3)
|
||||||
signet (0.16.1)
|
signet (0.17.0)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
faraday (>= 0.17.5, < 3.0)
|
faraday (>= 0.17.5, < 3.a)
|
||||||
jwt (>= 1.5, < 3.0)
|
jwt (>= 1.5, < 3.0)
|
||||||
multi_json (~> 1.10)
|
multi_json (~> 1.10)
|
||||||
simctl (1.6.8)
|
simctl (1.6.8)
|
||||||
@ -205,11 +205,11 @@ GEM
|
|||||||
uber (0.1.0)
|
uber (0.1.0)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.8.1)
|
unf_ext (0.0.8.2)
|
||||||
unicode-display_width (1.8.0)
|
unicode-display_width (1.8.0)
|
||||||
webrick (1.7.0)
|
webrick (1.7.0)
|
||||||
word_wrap (1.0.0)
|
word_wrap (1.0.0)
|
||||||
xcodeproj (1.21.0)
|
xcodeproj (1.22.0)
|
||||||
CFPropertyList (>= 2.3.3, < 4.0)
|
CFPropertyList (>= 2.3.3, < 4.0)
|
||||||
atomos (~> 0.1.3)
|
atomos (~> 0.1.3)
|
||||||
claide (>= 1.0.2, < 2.0)
|
claide (>= 1.0.2, < 2.0)
|
||||||
|
@ -32,7 +32,7 @@ If you are looking to install or test osu! without setting up a development envi
|
|||||||
|
|
||||||
**Latest build:**
|
**Latest build:**
|
||||||
|
|
||||||
| [Windows 8.1+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 10.15+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 10+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) |
|
| [Windows 8.1+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 10.15+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) |
|
||||||
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||||
|
|
||||||
- The iOS testflight link may fill up (Apple has a hard limit of 10,000 users). We reset it occasionally when this happens. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements of link resets.
|
- The iOS testflight link may fill up (Apple has a hard limit of 10,000 users). We reset it occasionally when this happens. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements of link resets.
|
||||||
@ -101,9 +101,7 @@ JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it
|
|||||||
|
|
||||||
## Contributing
|
## 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. Based on past experiences, we have prepared a [list of contributing guidelines](CONTRIBUTING.md) that should hopefully ease you into our collaboration process and answer the most frequently-asked questions.
|
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.
|
||||||
|
|
||||||
Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured, with any libraries we are using, or with any processes involved with contributing, *please* bring it up. We welcome all feedback so we can make contributing to this project as painless as possible.
|
|
||||||
|
|
||||||
If you wish to help with localisation efforts, head over to [crowdin](https://crowdin.com/project/osu-web).
|
If you wish to help with localisation efforts, head over to [crowdin](https://crowdin.com/project/osu-web).
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyFreeform.Tests
|
namespace osu.Game.Rulesets.EmptyFreeform.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneOsuGame : OsuTestScene
|
public partial class TestSceneOsuGame : OsuTestScene
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Tests.Visual;
|
|||||||
namespace osu.Game.Rulesets.EmptyFreeform.Tests
|
namespace osu.Game.Rulesets.EmptyFreeform.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneOsuPlayer : PlayerTestScene
|
public partial class TestSceneOsuPlayer : PlayerTestScene
|
||||||
{
|
{
|
||||||
protected override Ruleset CreatePlayerRuleset() => new EmptyFreeformRuleset();
|
protected override Ruleset CreatePlayerRuleset() => new EmptyFreeformRuleset();
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,9 @@
|
|||||||
<GenerateProgramFile>false</GenerateProgramFile>
|
<GenerateProgramFile>false</GenerateProgramFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
|
||||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.EmptyFreeform\osu.Game.Rulesets.EmptyFreeform.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.EmptyFreeform\osu.Game.Rulesets.EmptyFreeform.csproj" />
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyFreeform
|
namespace osu.Game.Rulesets.EmptyFreeform
|
||||||
{
|
{
|
||||||
public class EmptyFreeformInputManager : RulesetInputManager<EmptyFreeformAction>
|
public partial class EmptyFreeformInputManager : RulesetInputManager<EmptyFreeformAction>
|
||||||
{
|
{
|
||||||
public EmptyFreeformInputManager(RulesetInfo ruleset)
|
public EmptyFreeformInputManager(RulesetInfo ruleset)
|
||||||
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -20,7 +21,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyFreeform
|
namespace osu.Game.Rulesets.EmptyFreeform
|
||||||
{
|
{
|
||||||
public class EmptyFreeformRuleset : Ruleset
|
public partial class EmptyFreeformRuleset : Ruleset
|
||||||
{
|
{
|
||||||
public override string Description => "a very emptyfreeformruleset ruleset";
|
public override string Description => "a very emptyfreeformruleset ruleset";
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ namespace osu.Game.Rulesets.EmptyFreeform
|
|||||||
return new[] { new EmptyFreeformModAutoplay() };
|
return new[] { new EmptyFreeformModAutoplay() };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return new Mod[] { null };
|
return Array.Empty<Mod>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.EmptyFreeform
|
|||||||
|
|
||||||
public override Drawable CreateIcon() => new Icon(ShortName[0]);
|
public override Drawable CreateIcon() => new Icon(ShortName[0]);
|
||||||
|
|
||||||
public class Icon : CompositeDrawable
|
public partial class Icon : CompositeDrawable
|
||||||
{
|
{
|
||||||
public Icon(char c)
|
public Icon(char c)
|
||||||
{
|
{
|
||||||
@ -76,5 +77,8 @@ namespace osu.Game.Rulesets.EmptyFreeform
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Leave this line intact. It will bake the correct version into the ruleset on each build/release.
|
||||||
|
public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyFreeform.Objects.Drawables
|
namespace osu.Game.Rulesets.EmptyFreeform.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableEmptyFreeformHitObject : DrawableHitObject<EmptyFreeformHitObject>
|
public partial class DrawableEmptyFreeformHitObject : DrawableHitObject<EmptyFreeformHitObject>
|
||||||
{
|
{
|
||||||
public DrawableEmptyFreeformHitObject(EmptyFreeformHitObject hitObject)
|
public DrawableEmptyFreeformHitObject(EmptyFreeformHitObject hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
|
@ -17,7 +17,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
namespace osu.Game.Rulesets.EmptyFreeform.UI
|
namespace osu.Game.Rulesets.EmptyFreeform.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class DrawableEmptyFreeformRuleset : DrawableRuleset<EmptyFreeformHitObject>
|
public partial class DrawableEmptyFreeformRuleset : DrawableRuleset<EmptyFreeformHitObject>
|
||||||
{
|
{
|
||||||
public DrawableEmptyFreeformRuleset(EmptyFreeformRuleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
public DrawableEmptyFreeformRuleset(EmptyFreeformRuleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
|
@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
namespace osu.Game.Rulesets.EmptyFreeform.UI
|
namespace osu.Game.Rulesets.EmptyFreeform.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class EmptyFreeformPlayfield : Playfield
|
public partial class EmptyFreeformPlayfield : Playfield
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyTitle>osu.Game.Rulesets.EmptyFreeform</AssemblyTitle>
|
<AssemblyTitle>osu.Game.Rulesets.EmptyFreeform</AssemblyTitle>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
@ -12,4 +12,4 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\..\osu.Game\osu.Game.csproj" />
|
<ProjectReference Include="..\..\..\..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -9,7 +9,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.Tests
|
namespace osu.Game.Rulesets.Pippidon.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneOsuGame : OsuTestScene
|
public partial class TestSceneOsuGame : OsuTestScene
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Tests.Visual;
|
|||||||
namespace osu.Game.Rulesets.Pippidon.Tests
|
namespace osu.Game.Rulesets.Pippidon.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneOsuPlayer : PlayerTestScene
|
public partial class TestSceneOsuPlayer : PlayerTestScene
|
||||||
{
|
{
|
||||||
protected override Ruleset CreatePlayerRuleset() => new PippidonRuleset();
|
protected override Ruleset CreatePlayerRuleset() => new PippidonRuleset();
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,9 @@
|
|||||||
<GenerateProgramFile>false</GenerateProgramFile>
|
<GenerateProgramFile>false</GenerateProgramFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
|
||||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
||||||
|
@ -16,7 +16,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.Objects.Drawables
|
namespace osu.Game.Rulesets.Pippidon.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawablePippidonHitObject : DrawableHitObject<PippidonHitObject>
|
public partial class DrawablePippidonHitObject : DrawableHitObject<PippidonHitObject>
|
||||||
{
|
{
|
||||||
private const double time_preempt = 600;
|
private const double time_preempt = 600;
|
||||||
private const double time_fadein = 400;
|
private const double time_fadein = 400;
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon
|
namespace osu.Game.Rulesets.Pippidon
|
||||||
{
|
{
|
||||||
public class PippidonInputManager : RulesetInputManager<PippidonAction>
|
public partial class PippidonInputManager : RulesetInputManager<PippidonAction>
|
||||||
{
|
{
|
||||||
public PippidonInputManager(RulesetInfo ruleset)
|
public PippidonInputManager(RulesetInfo ruleset)
|
||||||
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Graphics.Textures;
|
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
@ -37,7 +36,7 @@ namespace osu.Game.Rulesets.Pippidon
|
|||||||
return new[] { new PippidonModAutoplay() };
|
return new[] { new PippidonModAutoplay() };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return new Mod[] { null };
|
return Array.Empty<Mod>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,9 +48,9 @@ namespace osu.Game.Rulesets.Pippidon
|
|||||||
new KeyBinding(InputKey.X, PippidonAction.Button2),
|
new KeyBinding(InputKey.X, PippidonAction.Button2),
|
||||||
};
|
};
|
||||||
|
|
||||||
public override Drawable CreateIcon() => new Sprite
|
public override Drawable CreateIcon() => new PippidonRulesetIcon(this);
|
||||||
{
|
|
||||||
Texture = new TextureStore(new TextureLoaderStore(CreateResourceStore()), false).Get("Textures/coin"),
|
// Leave this line intact. It will bake the correct version into the ruleset on each build/release.
|
||||||
};
|
public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.Rendering;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Pippidon
|
||||||
|
{
|
||||||
|
public partial class PippidonRulesetIcon : Sprite
|
||||||
|
{
|
||||||
|
private readonly Ruleset ruleset;
|
||||||
|
|
||||||
|
public PippidonRulesetIcon(Ruleset ruleset)
|
||||||
|
{
|
||||||
|
this.ruleset = ruleset;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IRenderer renderer)
|
||||||
|
{
|
||||||
|
Texture = new TextureStore(renderer, new TextureLoaderStore(ruleset.CreateResourceStore()), false).Get("Textures/coin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
namespace osu.Game.Rulesets.Pippidon.UI
|
namespace osu.Game.Rulesets.Pippidon.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class DrawablePippidonRuleset : DrawableRuleset<PippidonHitObject>
|
public partial class DrawablePippidonRuleset : DrawableRuleset<PippidonHitObject>
|
||||||
{
|
{
|
||||||
public DrawablePippidonRuleset(PippidonRuleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
public DrawablePippidonRuleset(PippidonRuleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
|
@ -10,7 +10,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.UI
|
namespace osu.Game.Rulesets.Pippidon.UI
|
||||||
{
|
{
|
||||||
public class PippidonCursorContainer : GameplayCursorContainer
|
public partial class PippidonCursorContainer : GameplayCursorContainer
|
||||||
{
|
{
|
||||||
private Sprite cursorSprite;
|
private Sprite cursorSprite;
|
||||||
private Texture cursorTexture;
|
private Texture cursorTexture;
|
||||||
|
@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
namespace osu.Game.Rulesets.Pippidon.UI
|
namespace osu.Game.Rulesets.Pippidon.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class PippidonPlayfield : Playfield
|
public partial class PippidonPlayfield : Playfield
|
||||||
{
|
{
|
||||||
protected override GameplayCursorContainer CreateCursor() => new PippidonCursorContainer();
|
protected override GameplayCursorContainer CreateCursor() => new PippidonCursorContainer();
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.UI
|
namespace osu.Game.Rulesets.Pippidon.UI
|
||||||
{
|
{
|
||||||
public class PippidonPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
|
public partial class PippidonPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer
|
||||||
{
|
{
|
||||||
public PippidonPlayfieldAdjustmentContainer()
|
public PippidonPlayfieldAdjustmentContainer()
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyTitle>osu.Game.Rulesets.Pippidon</AssemblyTitle>
|
<AssemblyTitle>osu.Game.Rulesets.Pippidon</AssemblyTitle>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
@ -12,4 +12,4 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\..\osu.Game\osu.Game.csproj" />
|
<ProjectReference Include="..\..\..\..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -9,7 +9,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyScrolling.Tests
|
namespace osu.Game.Rulesets.EmptyScrolling.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneOsuGame : OsuTestScene
|
public partial class TestSceneOsuGame : OsuTestScene
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Tests.Visual;
|
|||||||
namespace osu.Game.Rulesets.EmptyScrolling.Tests
|
namespace osu.Game.Rulesets.EmptyScrolling.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneOsuPlayer : PlayerTestScene
|
public partial class TestSceneOsuPlayer : PlayerTestScene
|
||||||
{
|
{
|
||||||
protected override Ruleset CreatePlayerRuleset() => new EmptyScrollingRuleset();
|
protected override Ruleset CreatePlayerRuleset() => new EmptyScrollingRuleset();
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,9 @@
|
|||||||
<GenerateProgramFile>false</GenerateProgramFile>
|
<GenerateProgramFile>false</GenerateProgramFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
|
||||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.EmptyScrolling\osu.Game.Rulesets.EmptyScrolling.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.EmptyScrolling\osu.Game.Rulesets.EmptyScrolling.csproj" />
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyScrolling
|
namespace osu.Game.Rulesets.EmptyScrolling
|
||||||
{
|
{
|
||||||
public class EmptyScrollingInputManager : RulesetInputManager<EmptyScrollingAction>
|
public partial class EmptyScrollingInputManager : RulesetInputManager<EmptyScrollingAction>
|
||||||
{
|
{
|
||||||
public EmptyScrollingInputManager(RulesetInfo ruleset)
|
public EmptyScrollingInputManager(RulesetInfo ruleset)
|
||||||
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.EmptyScrolling
|
|||||||
return new[] { new EmptyScrollingModAutoplay() };
|
return new[] { new EmptyScrollingModAutoplay() };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return new Mod[] { null };
|
return Array.Empty<Mod>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,5 +54,8 @@ namespace osu.Game.Rulesets.EmptyScrolling
|
|||||||
Text = ShortName[0].ToString(),
|
Text = ShortName[0].ToString(),
|
||||||
Font = OsuFont.Default.With(size: 18),
|
Font = OsuFont.Default.With(size: 18),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Leave this line intact. It will bake the correct version into the ruleset on each build/release.
|
||||||
|
public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyScrolling.Objects.Drawables
|
namespace osu.Game.Rulesets.EmptyScrolling.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableEmptyScrollingHitObject : DrawableHitObject<EmptyScrollingHitObject>
|
public partial class DrawableEmptyScrollingHitObject : DrawableHitObject<EmptyScrollingHitObject>
|
||||||
{
|
{
|
||||||
public DrawableEmptyScrollingHitObject(EmptyScrollingHitObject hitObject)
|
public DrawableEmptyScrollingHitObject(EmptyScrollingHitObject hitObject)
|
||||||
: base(hitObject)
|
: base(hitObject)
|
||||||
|
@ -18,7 +18,7 @@ using osu.Game.Rulesets.UI.Scrolling;
|
|||||||
namespace osu.Game.Rulesets.EmptyScrolling.UI
|
namespace osu.Game.Rulesets.EmptyScrolling.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class DrawableEmptyScrollingRuleset : DrawableScrollingRuleset<EmptyScrollingHitObject>
|
public partial class DrawableEmptyScrollingRuleset : DrawableScrollingRuleset<EmptyScrollingHitObject>
|
||||||
{
|
{
|
||||||
public DrawableEmptyScrollingRuleset(EmptyScrollingRuleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
public DrawableEmptyScrollingRuleset(EmptyScrollingRuleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
|
@ -8,7 +8,7 @@ using osu.Game.Rulesets.UI.Scrolling;
|
|||||||
namespace osu.Game.Rulesets.EmptyScrolling.UI
|
namespace osu.Game.Rulesets.EmptyScrolling.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class EmptyScrollingPlayfield : ScrollingPlayfield
|
public partial class EmptyScrollingPlayfield : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyTitle>osu.Game.Rulesets.EmptyScrolling</AssemblyTitle>
|
<AssemblyTitle>osu.Game.Rulesets.EmptyScrolling</AssemblyTitle>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
@ -12,4 +12,4 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\..\osu.Game\osu.Game.csproj" />
|
<ProjectReference Include="..\..\..\..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -9,7 +9,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.Tests
|
namespace osu.Game.Rulesets.Pippidon.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneOsuGame : OsuTestScene
|
public partial class TestSceneOsuGame : OsuTestScene
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Tests.Visual;
|
|||||||
namespace osu.Game.Rulesets.Pippidon.Tests
|
namespace osu.Game.Rulesets.Pippidon.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneOsuPlayer : PlayerTestScene
|
public partial class TestSceneOsuPlayer : PlayerTestScene
|
||||||
{
|
{
|
||||||
protected override Ruleset CreatePlayerRuleset() => new PippidonRuleset();
|
protected override Ruleset CreatePlayerRuleset() => new PippidonRuleset();
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,9 @@
|
|||||||
<GenerateProgramFile>false</GenerateProgramFile>
|
<GenerateProgramFile>false</GenerateProgramFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
|
||||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Pippidon\osu.Game.Rulesets.Pippidon.csproj" />
|
||||||
|
@ -21,8 +21,11 @@ namespace osu.Game.Rulesets.Pippidon.Beatmaps
|
|||||||
public PippidonBeatmapConverter(IBeatmap beatmap, Ruleset ruleset)
|
public PippidonBeatmapConverter(IBeatmap beatmap, Ruleset ruleset)
|
||||||
: base(beatmap, ruleset)
|
: base(beatmap, ruleset)
|
||||||
{
|
{
|
||||||
minPosition = beatmap.HitObjects.Min(getUsablePosition);
|
if (beatmap.HitObjects.Any())
|
||||||
maxPosition = beatmap.HitObjects.Max(getUsablePosition);
|
{
|
||||||
|
minPosition = beatmap.HitObjects.Min(getUsablePosition);
|
||||||
|
maxPosition = beatmap.HitObjects.Max(getUsablePosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanConvert() => Beatmap.HitObjects.All(h => h is IHasXPosition && h is IHasYPosition);
|
public override bool CanConvert() => Beatmap.HitObjects.All(h => h is IHasXPosition && h is IHasYPosition);
|
||||||
|
@ -17,7 +17,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.Objects.Drawables
|
namespace osu.Game.Rulesets.Pippidon.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawablePippidonHitObject : DrawableHitObject<PippidonHitObject>
|
public partial class DrawablePippidonHitObject : DrawableHitObject<PippidonHitObject>
|
||||||
{
|
{
|
||||||
private BindableNumber<int> currentLane;
|
private BindableNumber<int> currentLane;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ using osu.Game.Rulesets.UI;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon
|
namespace osu.Game.Rulesets.Pippidon
|
||||||
{
|
{
|
||||||
public class PippidonInputManager : RulesetInputManager<PippidonAction>
|
public partial class PippidonInputManager : RulesetInputManager<PippidonAction>
|
||||||
{
|
{
|
||||||
public PippidonInputManager(RulesetInfo ruleset)
|
public PippidonInputManager(RulesetInfo ruleset)
|
||||||
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
: base(ruleset, 0, SimultaneousBindingMode.Unique)
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Graphics.Textures;
|
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
@ -34,7 +33,7 @@ namespace osu.Game.Rulesets.Pippidon
|
|||||||
return new[] { new PippidonModAutoplay() };
|
return new[] { new PippidonModAutoplay() };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return new Mod[] { null };
|
return Array.Empty<Mod>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,10 +45,9 @@ namespace osu.Game.Rulesets.Pippidon
|
|||||||
new KeyBinding(InputKey.S, PippidonAction.MoveDown),
|
new KeyBinding(InputKey.S, PippidonAction.MoveDown),
|
||||||
};
|
};
|
||||||
|
|
||||||
public override Drawable CreateIcon() => new Sprite
|
public override Drawable CreateIcon() => new PippidonRulesetIcon(this);
|
||||||
{
|
|
||||||
Margin = new MarginPadding { Top = 3 },
|
// Leave this line intact. It will bake the correct version into the ruleset on each build/release.
|
||||||
Texture = new TextureStore(new TextureLoaderStore(CreateResourceStore()), false).Get("Textures/coin"),
|
public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Rendering;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Pippidon
|
||||||
|
{
|
||||||
|
public partial class PippidonRulesetIcon : Sprite
|
||||||
|
{
|
||||||
|
private readonly Ruleset ruleset;
|
||||||
|
|
||||||
|
public PippidonRulesetIcon(Ruleset ruleset)
|
||||||
|
{
|
||||||
|
this.ruleset = ruleset;
|
||||||
|
|
||||||
|
Margin = new MarginPadding { Top = 3 };
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IRenderer renderer)
|
||||||
|
{
|
||||||
|
Texture = new TextureStore(renderer, new TextureLoaderStore(ruleset.CreateResourceStore()), false).Get("Textures/coin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ using osu.Game.Rulesets.UI.Scrolling;
|
|||||||
namespace osu.Game.Rulesets.Pippidon.UI
|
namespace osu.Game.Rulesets.Pippidon.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class DrawablePippidonRuleset : DrawableScrollingRuleset<PippidonHitObject>
|
public partial class DrawablePippidonRuleset : DrawableScrollingRuleset<PippidonHitObject>
|
||||||
{
|
{
|
||||||
public DrawablePippidonRuleset(PippidonRuleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
public DrawablePippidonRuleset(PippidonRuleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
|
@ -15,7 +15,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.UI
|
namespace osu.Game.Rulesets.Pippidon.UI
|
||||||
{
|
{
|
||||||
public class PippidonCharacter : BeatSyncedContainer, IKeyBindingHandler<PippidonAction>
|
public partial class PippidonCharacter : BeatSyncedContainer, IKeyBindingHandler<PippidonAction>
|
||||||
{
|
{
|
||||||
public readonly BindableInt LanePosition = new BindableInt
|
public readonly BindableInt LanePosition = new BindableInt
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ using osuTK.Graphics;
|
|||||||
namespace osu.Game.Rulesets.Pippidon.UI
|
namespace osu.Game.Rulesets.Pippidon.UI
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
public class PippidonPlayfield : ScrollingPlayfield
|
public partial class PippidonPlayfield : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
public const float LANE_HEIGHT = 70;
|
public const float LANE_HEIGHT = 70;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Pippidon.UI
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LaneContainer : BeatSyncedContainer
|
private partial class LaneContainer : BeatSyncedContainer
|
||||||
{
|
{
|
||||||
private OsuColour colours;
|
private OsuColour colours;
|
||||||
private FillFlowContainer fill;
|
private FillFlowContainer fill;
|
||||||
@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Pippidon.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Lane : CompositeDrawable
|
private partial class Lane : CompositeDrawable
|
||||||
{
|
{
|
||||||
public Lane()
|
public Lane()
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AssemblyTitle>osu.Game.Rulesets.Pippidon</AssemblyTitle>
|
<AssemblyTitle>osu.Game.Rulesets.Pippidon</AssemblyTitle>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
@ -12,4 +12,4 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\..\osu.Game\osu.Game.csproj" />
|
<ProjectReference Include="..\..\..\..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
17
UseLocalFramework.ps1
Normal file
17
UseLocalFramework.ps1
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Run this script to use a local copy of osu-framework rather than fetching it from nuget.
|
||||||
|
# It expects the osu-framework directory to be at the same level as the osu directory
|
||||||
|
#
|
||||||
|
# https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects
|
||||||
|
|
||||||
|
$CSPROJ="osu.Game/osu.Game.csproj"
|
||||||
|
$SLN="osu.sln"
|
||||||
|
|
||||||
|
dotnet remove $CSPROJ package ppy.osu.Framework;
|
||||||
|
dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj ../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj;
|
||||||
|
dotnet add $CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj
|
||||||
|
|
||||||
|
$SLNF=Get-Content "osu.Desktop.slnf" | ConvertFrom-Json
|
||||||
|
$TMP=New-TemporaryFile
|
||||||
|
$SLNF.solution.projects += ("../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj")
|
||||||
|
ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8
|
||||||
|
Move-Item -Path $TMP -Destination "osu.Desktop.slnf" -Force
|
18
UseLocalFramework.sh
Executable file
18
UseLocalFramework.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Run this script to use a local copy of osu-framework rather than fetching it from nuget.
|
||||||
|
# It expects the osu-framework directory to be at the same level as the osu directory
|
||||||
|
#
|
||||||
|
# https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects
|
||||||
|
|
||||||
|
CSPROJ="osu.Game/osu.Game.csproj"
|
||||||
|
SLN="osu.sln"
|
||||||
|
|
||||||
|
dotnet remove $CSPROJ package ppy.osu.Framework
|
||||||
|
dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj ../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj
|
||||||
|
dotnet add $CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj
|
||||||
|
|
||||||
|
SLNF="osu.Desktop.slnf"
|
||||||
|
tmp=$(mktemp)
|
||||||
|
jq '.solution.projects += ["../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj"]' osu.Desktop.slnf > $tmp
|
||||||
|
mv -f $tmp $SLNF
|
12
UseLocalResources.ps1
Normal file
12
UseLocalResources.ps1
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
$CSPROJ="osu.Game/osu.Game.csproj"
|
||||||
|
$SLN="osu.sln"
|
||||||
|
|
||||||
|
dotnet remove $CSPROJ package ppy.osu.Game.Resources;
|
||||||
|
dotnet sln $SLN add ../osu-resources/osu.Game.Resources/osu.Game.Resources.csproj
|
||||||
|
dotnet add $CSPROJ reference ../osu-resources/osu.Game.Resources/osu.Game.Resources.csproj
|
||||||
|
|
||||||
|
$SLNF=Get-Content "osu.Desktop.slnf" | ConvertFrom-Json
|
||||||
|
$TMP=New-TemporaryFile
|
||||||
|
$SLNF.solution.projects += ("../osu-resources/osu.Game.Resources/osu.Game.Resources.csproj")
|
||||||
|
ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8
|
||||||
|
Move-Item -Path $TMP -Destination "osu.Desktop.slnf" -Force
|
11
UseLocalResources.sh
Executable file
11
UseLocalResources.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
CSPROJ="osu.Game/osu.Game.csproj"
|
||||||
|
SLN="osu.sln"
|
||||||
|
|
||||||
|
dotnet remove $CSPROJ package ppy.osu.Game.Resources;
|
||||||
|
dotnet sln $SLN add ../osu-resources/osu.Game.Resources/osu.Game.Resources.csproj
|
||||||
|
dotnet add $CSPROJ reference ../osu-resources/osu.Game.Resources/osu.Game.Resources.csproj
|
||||||
|
|
||||||
|
SLNF="osu.Desktop.slnf"
|
||||||
|
TMP=$(mktemp)
|
||||||
|
jq '.solution.projects += ["../osu-resources/osu.Game.Resources/osu.Game.Resources.csproj"]' $SLNF > $TMP
|
||||||
|
mv -f $TMP $SLNF
|
@ -1,6 +1,6 @@
|
|||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
version: '{branch}-{build}'
|
version: '{branch}-{build}'
|
||||||
image: Visual Studio 2019
|
image: Visual Studio 2022
|
||||||
cache:
|
cache:
|
||||||
- '%LOCALAPPDATA%\NuGet\v3-cache -> appveyor.yml'
|
- '%LOCALAPPDATA%\NuGet\v3-cache -> appveyor.yml'
|
||||||
|
|
||||||
@ -11,6 +11,8 @@ dotnet_csproj:
|
|||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
- cmd: dotnet --info # Useful when version mismatch between CI and local
|
- cmd: dotnet --info # Useful when version mismatch between CI and local
|
||||||
|
- cmd: dotnet workload install maui-android # Change to `dotnet workload restore` once there's no old projects
|
||||||
|
- cmd: dotnet workload install maui-ios # Change to `dotnet workload restore` once there's no old projects
|
||||||
- cmd: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects
|
- cmd: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
version: '{build}'
|
version: '{build}'
|
||||||
image: Visual Studio 2019
|
image: Visual Studio 2022
|
||||||
test: off
|
test: off
|
||||||
skip_non_tags: true
|
skip_non_tags: true
|
||||||
configuration: Release
|
configuration: Release
|
||||||
@ -83,4 +83,4 @@ artifacts:
|
|||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
- provider: Environment
|
- provider: Environment
|
||||||
name: nuget
|
name: nuget
|
||||||
|
@ -138,10 +138,10 @@ platform :ios do
|
|||||||
end
|
end
|
||||||
|
|
||||||
lane :testflight_prune_dry do
|
lane :testflight_prune_dry do
|
||||||
clean_testflight_testers(days_of_inactivity:45, dry_run: true)
|
clean_testflight_testers(days_of_inactivity:30, dry_run: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
lane :testflight_prune do
|
lane :testflight_prune do
|
||||||
clean_testflight_testers(days_of_inactivity: 45)
|
clean_testflight_testers(days_of_inactivity: 30)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,61 +1,20 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<LangVersion>8.0</LangVersion>
|
<SupportedOSPlatformVersion>21.0</SupportedOSPlatformVersion>
|
||||||
<OutputPath>bin\$(Configuration)</OutputPath>
|
<RuntimeIdentifiers>android-x86;android-arm;android-arm64</RuntimeIdentifiers>
|
||||||
<WarningLevel>4</WarningLevel>
|
<AndroidPackageFormat>apk</AndroidPackageFormat>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<MandroidI18n>CJK;Mideast;Rare;West;Other;</MandroidI18n>
|
||||||
<BundleAssemblies>false</BundleAssemblies>
|
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidMessageHandler</AndroidHttpClientHandlerType>
|
||||||
<AotAssemblies>false</AotAssemblies>
|
<!-- NullabilityInfoContextSupport is disabled by default for Android -->
|
||||||
<OutputType>Library</OutputType>
|
<NullabilityInfoContextSupport>true</NullabilityInfoContextSupport>
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
|
||||||
<AndroidApplication>True</AndroidApplication>
|
|
||||||
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
|
||||||
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
|
|
||||||
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
|
||||||
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
|
|
||||||
<MandroidI18n>cjk,mideast,other,rare,west</MandroidI18n>
|
|
||||||
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
|
||||||
<DebugSymbols>True</DebugSymbols>
|
|
||||||
<DebugType>portable</DebugType>
|
|
||||||
<Optimize>False</Optimize>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
|
||||||
<AndroidUseSharedRuntime>true</AndroidUseSharedRuntime>
|
|
||||||
<EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<DebugSymbols>false</DebugSymbols>
|
|
||||||
<DebugType>None</DebugType>
|
|
||||||
<Optimize>True</Optimize>
|
|
||||||
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
|
||||||
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
|
|
||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="$(MSBuildThisFileDirectory)\osu.licenseheader">
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.1226.0" />
|
||||||
<Link>osu.licenseheader</Link>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="Mono.Android" />
|
|
||||||
<Reference Include="Java.Interop" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.527.0" />
|
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.605.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
|
||||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
|
||||||
<PackageReference Include="Realm" Version="10.14.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||||
|
Since Realm objects are not declared directly in Android projects, simply disable Fody. -->
|
||||||
|
<DisableFody>true</DisableFody>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
76
osu.Android/AndroidJoystickSettings.cs
Normal file
76
osu.Android/AndroidJoystickSettings.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Android.Input;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Localisation;
|
||||||
|
using osu.Game.Overlays.Settings;
|
||||||
|
|
||||||
|
namespace osu.Android
|
||||||
|
{
|
||||||
|
public partial class AndroidJoystickSettings : SettingsSubsection
|
||||||
|
{
|
||||||
|
protected override LocalisableString Header => JoystickSettingsStrings.JoystickGamepad;
|
||||||
|
|
||||||
|
private readonly AndroidJoystickHandler joystickHandler;
|
||||||
|
|
||||||
|
private readonly Bindable<bool> enabled = new BindableBool(true);
|
||||||
|
|
||||||
|
private SettingsSlider<float> deadzoneSlider = null!;
|
||||||
|
|
||||||
|
private Bindable<float> handlerDeadzone = null!;
|
||||||
|
|
||||||
|
private Bindable<float> localDeadzone = null!;
|
||||||
|
|
||||||
|
public AndroidJoystickSettings(AndroidJoystickHandler joystickHandler)
|
||||||
|
{
|
||||||
|
this.joystickHandler = joystickHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
// use local bindable to avoid changing enabled state of game host's bindable.
|
||||||
|
handlerDeadzone = joystickHandler.DeadzoneThreshold.GetBoundCopy();
|
||||||
|
localDeadzone = handlerDeadzone.GetUnboundCopy();
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new SettingsCheckbox
|
||||||
|
{
|
||||||
|
LabelText = CommonStrings.Enabled,
|
||||||
|
Current = enabled
|
||||||
|
},
|
||||||
|
deadzoneSlider = new SettingsSlider<float>
|
||||||
|
{
|
||||||
|
LabelText = JoystickSettingsStrings.DeadzoneThreshold,
|
||||||
|
KeyboardStep = 0.01f,
|
||||||
|
DisplayAsPercentage = true,
|
||||||
|
Current = localDeadzone,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
enabled.BindTo(joystickHandler.Enabled);
|
||||||
|
enabled.BindValueChanged(e => deadzoneSlider.Current.Disabled = !e.NewValue, true);
|
||||||
|
|
||||||
|
handlerDeadzone.BindValueChanged(val =>
|
||||||
|
{
|
||||||
|
bool disabled = localDeadzone.Disabled;
|
||||||
|
|
||||||
|
localDeadzone.Disabled = false;
|
||||||
|
localDeadzone.Value = val.NewValue;
|
||||||
|
localDeadzone.Disabled = disabled;
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
localDeadzone.BindValueChanged(val => handlerDeadzone.Value = val.NewValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" package="sh.ppy.osulazer" android:installLocation="auto" android:versionName="0.1.0">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="sh.ppy.osulazer" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
|
||||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!" android:icon="@drawable/lazer" />
|
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!" android:icon="@drawable/lazer" />
|
||||||
</manifest>
|
</manifest>
|
97
osu.Android/AndroidMouseSettings.cs
Normal file
97
osu.Android/AndroidMouseSettings.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// 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 Android.OS;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Android.Input;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Localisation;
|
||||||
|
using osu.Game.Overlays.Settings;
|
||||||
|
using osu.Game.Overlays.Settings.Sections.Input;
|
||||||
|
|
||||||
|
namespace osu.Android
|
||||||
|
{
|
||||||
|
public partial class AndroidMouseSettings : SettingsSubsection
|
||||||
|
{
|
||||||
|
private readonly AndroidMouseHandler mouseHandler;
|
||||||
|
|
||||||
|
protected override LocalisableString Header => MouseSettingsStrings.Mouse;
|
||||||
|
|
||||||
|
private Bindable<double> handlerSensitivity = null!;
|
||||||
|
|
||||||
|
private Bindable<double> localSensitivity = null!;
|
||||||
|
|
||||||
|
private Bindable<bool> relativeMode = null!;
|
||||||
|
|
||||||
|
public AndroidMouseSettings(AndroidMouseHandler mouseHandler)
|
||||||
|
{
|
||||||
|
this.mouseHandler = mouseHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuConfigManager osuConfig)
|
||||||
|
{
|
||||||
|
// use local bindable to avoid changing enabled state of game host's bindable.
|
||||||
|
handlerSensitivity = mouseHandler.Sensitivity.GetBoundCopy();
|
||||||
|
localSensitivity = handlerSensitivity.GetUnboundCopy();
|
||||||
|
|
||||||
|
relativeMode = mouseHandler.UseRelativeMode.GetBoundCopy();
|
||||||
|
|
||||||
|
// High precision/pointer capture is only available on Android 8.0 and up
|
||||||
|
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
|
||||||
|
{
|
||||||
|
AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new SettingsCheckbox
|
||||||
|
{
|
||||||
|
LabelText = MouseSettingsStrings.HighPrecisionMouse,
|
||||||
|
TooltipText = MouseSettingsStrings.HighPrecisionMouseTooltip,
|
||||||
|
Current = relativeMode,
|
||||||
|
Keywords = new[] { @"raw", @"input", @"relative", @"cursor", @"captured", @"pointer" },
|
||||||
|
},
|
||||||
|
new MouseSettings.SensitivitySetting
|
||||||
|
{
|
||||||
|
LabelText = MouseSettingsStrings.CursorSensitivity,
|
||||||
|
Current = localSensitivity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
new SettingsCheckbox
|
||||||
|
{
|
||||||
|
LabelText = MouseSettingsStrings.DisableMouseWheelVolumeAdjust,
|
||||||
|
TooltipText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip,
|
||||||
|
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableWheel),
|
||||||
|
},
|
||||||
|
new SettingsCheckbox
|
||||||
|
{
|
||||||
|
LabelText = MouseSettingsStrings.DisableMouseButtons,
|
||||||
|
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableButtons),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
relativeMode.BindValueChanged(relative => localSensitivity.Disabled = !relative.NewValue, true);
|
||||||
|
|
||||||
|
handlerSensitivity.BindValueChanged(val =>
|
||||||
|
{
|
||||||
|
bool disabled = localSensitivity.Disabled;
|
||||||
|
|
||||||
|
localSensitivity.Disabled = false;
|
||||||
|
localSensitivity.Value = val.NewValue;
|
||||||
|
localSensitivity.Disabled = disabled;
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
localSensitivity.BindValueChanged(val => handlerSensitivity.Value = val.NewValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using Android.Content.PM;
|
using Android.Content.PM;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
@ -9,7 +11,7 @@ using osu.Game;
|
|||||||
|
|
||||||
namespace osu.Android
|
namespace osu.Android
|
||||||
{
|
{
|
||||||
public class GameplayScreenRotationLocker : Component
|
public partial class GameplayScreenRotationLocker : Component
|
||||||
{
|
{
|
||||||
private Bindable<bool> localUserPlaying;
|
private Bindable<bool> localUserPlaying;
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
@ -72,11 +75,23 @@ namespace osu.Android
|
|||||||
Debug.Assert(Resources?.DisplayMetrics != null);
|
Debug.Assert(Resources?.DisplayMetrics != null);
|
||||||
|
|
||||||
Point displaySize = new Point();
|
Point displaySize = new Point();
|
||||||
|
#pragma warning disable 618 // GetSize is deprecated
|
||||||
WindowManager.DefaultDisplay.GetSize(displaySize);
|
WindowManager.DefaultDisplay.GetSize(displaySize);
|
||||||
|
#pragma warning restore 618
|
||||||
float smallestWidthDp = Math.Min(displaySize.X, displaySize.Y) / Resources.DisplayMetrics.Density;
|
float smallestWidthDp = Math.Min(displaySize.X, displaySize.Y) / Resources.DisplayMetrics.Density;
|
||||||
bool isTablet = smallestWidthDp >= 600f;
|
bool isTablet = smallestWidthDp >= 600f;
|
||||||
|
|
||||||
RequestedOrientation = DefaultOrientation = isTablet ? ScreenOrientation.FullUser : ScreenOrientation.SensorLandscape;
|
RequestedOrientation = DefaultOrientation = isTablet ? ScreenOrientation.FullUser : ScreenOrientation.SensorLandscape;
|
||||||
|
|
||||||
|
// Currently (SDK 6.0.200), BundleAssemblies is not runnable for net6-android.
|
||||||
|
// The assembly files are not available as files either after native AOT.
|
||||||
|
// Manually load them so that they can be loaded by RulesetStore.loadFromAppDomain.
|
||||||
|
// REMEMBER to fully uninstall previous version every time when investigating this!
|
||||||
|
// Don't forget osu.Game.Tests.Android too.
|
||||||
|
Assembly.Load("osu.Game.Rulesets.Osu");
|
||||||
|
Assembly.Load("osu.Game.Rulesets.Taiko");
|
||||||
|
Assembly.Load("osu.Game.Rulesets.Catch");
|
||||||
|
Assembly.Load("osu.Game.Rulesets.Mania");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewIntent(Intent intent) => handleIntent(intent);
|
protected override void OnNewIntent(Intent intent) => handleIntent(intent);
|
||||||
@ -125,7 +140,7 @@ namespace osu.Android
|
|||||||
|
|
||||||
cursor.MoveToFirst();
|
cursor.MoveToFirst();
|
||||||
|
|
||||||
int filenameColumn = cursor.GetColumnIndex(OpenableColumns.DisplayName);
|
int filenameColumn = cursor.GetColumnIndex(IOpenableColumns.DisplayName);
|
||||||
string filename = cursor.GetString(filenameColumn);
|
string filename = cursor.GetString(filenameColumn);
|
||||||
|
|
||||||
// SharpCompress requires archive streams to be seekable, which the stream opened by
|
// SharpCompress requires archive streams to be seekable, which the stream opened by
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.OS;
|
using Microsoft.Maui.Devices;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Android.Input;
|
||||||
|
using osu.Framework.Input.Handlers;
|
||||||
|
using osu.Framework.Platform;
|
||||||
using osu.Game;
|
using osu.Game;
|
||||||
|
using osu.Game.Overlays.Settings;
|
||||||
using osu.Game.Updater;
|
using osu.Game.Updater;
|
||||||
using osu.Game.Utils;
|
using osu.Game.Utils;
|
||||||
using Xamarin.Essentials;
|
|
||||||
|
|
||||||
namespace osu.Android
|
namespace osu.Android
|
||||||
{
|
{
|
||||||
public class OsuGameAndroid : OsuGame
|
public partial class OsuGameAndroid : OsuGame
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly OsuGameActivity gameActivity;
|
private readonly OsuGameActivity gameActivity;
|
||||||
@ -42,7 +47,7 @@ namespace osu.Android
|
|||||||
// https://stackoverflow.com/questions/52977079/android-sdk-28-versioncode-in-packageinfo-has-been-deprecated
|
// https://stackoverflow.com/questions/52977079/android-sdk-28-versioncode-in-packageinfo-has-been-deprecated
|
||||||
string versionName = string.Empty;
|
string versionName = string.Empty;
|
||||||
|
|
||||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
if (OperatingSystem.IsAndroidVersionAtLeast(28))
|
||||||
{
|
{
|
||||||
versionName = packageInfo.LongVersionCode.ToString();
|
versionName = packageInfo.LongVersionCode.ToString();
|
||||||
// ensure we only read the trailing portion of long (the part we are interested in).
|
// ensure we only read the trailing portion of long (the part we are interested in).
|
||||||
@ -73,15 +78,36 @@ namespace osu.Android
|
|||||||
LoadComponentAsync(new GameplayScreenRotationLocker(), Add);
|
LoadComponentAsync(new GameplayScreenRotationLocker(), Add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void SetHost(GameHost host)
|
||||||
|
{
|
||||||
|
base.SetHost(host);
|
||||||
|
host.Window.CursorState |= CursorState.Hidden;
|
||||||
|
}
|
||||||
|
|
||||||
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
||||||
|
|
||||||
protected override BatteryInfo CreateBatteryInfo() => new AndroidBatteryInfo();
|
protected override BatteryInfo CreateBatteryInfo() => new AndroidBatteryInfo();
|
||||||
|
|
||||||
|
public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler)
|
||||||
|
{
|
||||||
|
switch (handler)
|
||||||
|
{
|
||||||
|
case AndroidMouseHandler mh:
|
||||||
|
return new AndroidMouseSettings(mh);
|
||||||
|
|
||||||
|
case AndroidJoystickHandler jh:
|
||||||
|
return new AndroidJoystickSettings(jh);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return base.CreateSettingsSubsectionFor(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class AndroidBatteryInfo : BatteryInfo
|
private class AndroidBatteryInfo : BatteryInfo
|
||||||
{
|
{
|
||||||
public override double ChargeLevel => Battery.ChargeLevel;
|
public override double? ChargeLevel => Battery.ChargeLevel;
|
||||||
|
|
||||||
public override bool IsCharging => Battery.PowerSource != BatteryPowerSource.Battery;
|
public override bool OnBattery => Battery.PowerSource == BatteryPowerSource.Battery;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using Android;
|
using Android;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
|
|
||||||
|
@ -1,71 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="..\osu.Android.props" />
|
<Import Project="..\osu.Android.props" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<TargetFramework>net6.0-android</TargetFramework>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<OutputType>Exe</OutputType>
|
||||||
<ProductVersion>8.0.30703</ProductVersion>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
<ProjectGuid>{D1D5F9A8-B40B-40E6-B02F-482D03346D3D}</ProjectGuid>
|
|
||||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
|
||||||
<TemplateGuid>{122416d6-6b49-4ee2-a1e8-b825f31c79fe}</TemplateGuid>
|
|
||||||
<RootNamespace>osu.Android</RootNamespace>
|
<RootNamespace>osu.Android</RootNamespace>
|
||||||
<AssemblyName>osu.Android</AssemblyName>
|
<AssemblyName>osu.Android</AssemblyName>
|
||||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
<UseMauiEssentials>true</UseMauiEssentials>
|
||||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
<!-- This currently causes random lockups during gameplay. https://github.com/mono/mono/issues/18973 -->
|
||||||
<EnableLLVM>false</EnableLLVM> <!-- This currently causes random lockups during gameplay. https://github.com/mono/mono/issues/18973 -->
|
<EnableLLVM>false</EnableLLVM>
|
||||||
</PropertyGroup>
|
<Version>0.0.0</Version>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<ApplicationVersion Condition=" '$(ApplicationVersion)' == '' ">1</ApplicationVersion>
|
||||||
<MandroidI18n>cjk;mideast;other;rare;west</MandroidI18n>
|
<ApplicationDisplayVersion Condition=" '$(ApplicationDisplayVersion)' == '' ">$(Version)</ApplicationDisplayVersion>
|
||||||
<AndroidDexTool>d8</AndroidDexTool>
|
|
||||||
<AndroidLinkTool>r8</AndroidLinkTool>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<AndroidLinkMode>None</AndroidLinkMode>
|
|
||||||
<MandroidI18n>cjk;mideast;other;rare;west</MandroidI18n>
|
|
||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="GameplayScreenRotationLocker.cs" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
<Compile Include="OsuGameActivity.cs" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
||||||
<Compile Include="OsuGameAndroid.cs" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||||
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
</Project>
|
||||||
<None Include="Properties\AndroidManifest.xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
|
|
||||||
<Project>{58f6c80c-1253-4a0e-a465-b8c85ebeadf3}</Project>
|
|
||||||
<Name>osu.Game.Rulesets.Catch</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj">
|
|
||||||
<Project>{48f4582b-7687-4621-9cbe-5c24197cb536}</Project>
|
|
||||||
<Name>osu.Game.Rulesets.Mania</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj">
|
|
||||||
<Project>{c92a607b-1fdd-4954-9f92-03ff547d9080}</Project>
|
|
||||||
<Name>osu.Game.Rulesets.Osu</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj">
|
|
||||||
<Project>{f167e17a-7de6-4af5-b920-a5112296c695}</Project>
|
|
||||||
<Name>osu.Game.Rulesets.Taiko</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
|
||||||
<Project>{2a66dd92-adb1-4994-89e2-c94e04acda0d}</Project>
|
|
||||||
<Name>osu.Game</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<AndroidResource Include="Resources\drawable\lazer.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="System.Formats.Asn1">
|
|
||||||
<Version>5.0.0</Version>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Xamarin.Essentials" Version="1.7.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
|
||||||
</Project>
|
|
||||||
|
@ -9,6 +9,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Extensions;
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
@ -19,16 +20,19 @@ using LogLevel = osu.Framework.Logging.LogLevel;
|
|||||||
|
|
||||||
namespace osu.Desktop
|
namespace osu.Desktop
|
||||||
{
|
{
|
||||||
internal class DiscordRichPresence : Component
|
internal partial class DiscordRichPresence : Component
|
||||||
{
|
{
|
||||||
private const string client_id = "367827983903490050";
|
private const string client_id = "367827983903490050";
|
||||||
|
|
||||||
private DiscordRpcClient client;
|
private DiscordRpcClient client = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private IBindable<RulesetInfo> ruleset { get; set; }
|
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||||
|
|
||||||
private IBindable<APIUser> user;
|
private IBindable<APIUser> user = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; } = null!;
|
||||||
|
|
||||||
private readonly IBindable<UserStatus> status = new Bindable<UserStatus>();
|
private readonly IBindable<UserStatus> status = new Bindable<UserStatus>();
|
||||||
private readonly IBindable<UserActivity> activity = new Bindable<UserActivity>();
|
private readonly IBindable<UserActivity> activity = new Bindable<UserActivity>();
|
||||||
@ -41,7 +45,7 @@ namespace osu.Desktop
|
|||||||
};
|
};
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IAPIProvider provider, OsuConfigManager config)
|
private void load(OsuConfigManager config)
|
||||||
{
|
{
|
||||||
client = new DiscordRpcClient(client_id)
|
client = new DiscordRpcClient(client_id)
|
||||||
{
|
{
|
||||||
@ -51,13 +55,14 @@ namespace osu.Desktop
|
|||||||
client.OnReady += onReady;
|
client.OnReady += onReady;
|
||||||
|
|
||||||
// safety measure for now, until we performance test / improve backoff for failed connections.
|
// safety measure for now, until we performance test / improve backoff for failed connections.
|
||||||
client.OnConnectionFailed += (_, __) => client.Deinitialize();
|
client.OnConnectionFailed += (_, _) => client.Deinitialize();
|
||||||
|
|
||||||
client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network);
|
client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network);
|
||||||
|
|
||||||
config.BindWith(OsuSetting.DiscordRichPresence, privacyMode);
|
config.BindWith(OsuSetting.DiscordRichPresence, privacyMode);
|
||||||
|
|
||||||
(user = provider.LocalUser.GetBoundCopy()).BindValueChanged(u =>
|
user = api.LocalUser.GetBoundCopy();
|
||||||
|
user.BindValueChanged(u =>
|
||||||
{
|
{
|
||||||
status.UnbindBindings();
|
status.UnbindBindings();
|
||||||
status.BindTo(u.NewValue.Status);
|
status.BindTo(u.NewValue.Status);
|
||||||
@ -95,6 +100,22 @@ namespace osu.Desktop
|
|||||||
{
|
{
|
||||||
presence.State = truncate(activity.Value.Status);
|
presence.State = truncate(activity.Value.Status);
|
||||||
presence.Details = truncate(getDetails(activity.Value));
|
presence.Details = truncate(getDetails(activity.Value));
|
||||||
|
|
||||||
|
if (getBeatmap(activity.Value) is IBeatmapInfo beatmap && beatmap.OnlineID > 0)
|
||||||
|
{
|
||||||
|
presence.Buttons = new[]
|
||||||
|
{
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Label = "View beatmap",
|
||||||
|
Url = $@"{api.WebsiteRootUrl}/beatmapsets/{beatmap.BeatmapSet?.OnlineID}#{ruleset.Value.ShortName}/{beatmap.OnlineID}"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
presence.Buttons = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -106,7 +127,12 @@ namespace osu.Desktop
|
|||||||
if (privacyMode.Value == DiscordRichPresenceMode.Limited)
|
if (privacyMode.Value == DiscordRichPresenceMode.Limited)
|
||||||
presence.Assets.LargeImageText = string.Empty;
|
presence.Assets.LargeImageText = string.Empty;
|
||||||
else
|
else
|
||||||
presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.GlobalRank > 0 ? $" (rank #{user.Value.Statistics.GlobalRank:N0})" : string.Empty);
|
{
|
||||||
|
if (user.Value.RulesetsStatistics != null && user.Value.RulesetsStatistics.TryGetValue(ruleset.Value.ShortName, out UserStatistics? statistics))
|
||||||
|
presence.Assets.LargeImageText = $"{user.Value.Username}" + (statistics.GlobalRank > 0 ? $" (rank #{statistics.GlobalRank:N0})" : string.Empty);
|
||||||
|
else
|
||||||
|
presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.GlobalRank > 0 ? $" (rank #{user.Value.Statistics.GlobalRank:N0})" : string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
// update ruleset
|
// update ruleset
|
||||||
presence.Assets.SmallImageKey = ruleset.Value.IsLegacyRuleset() ? $"mode_{ruleset.Value.OnlineID}" : "mode_custom";
|
presence.Assets.SmallImageKey = ruleset.Value.IsLegacyRuleset() ? $"mode_{ruleset.Value.OnlineID}" : "mode_custom";
|
||||||
@ -136,15 +162,29 @@ namespace osu.Desktop
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IBeatmapInfo? getBeatmap(UserActivity activity)
|
||||||
|
{
|
||||||
|
switch (activity)
|
||||||
|
{
|
||||||
|
case UserActivity.InGame game:
|
||||||
|
return game.BeatmapInfo;
|
||||||
|
|
||||||
|
case UserActivity.Editing edit:
|
||||||
|
return edit.BeatmapInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private string getDetails(UserActivity activity)
|
private string getDetails(UserActivity activity)
|
||||||
{
|
{
|
||||||
switch (activity)
|
switch (activity)
|
||||||
{
|
{
|
||||||
case UserActivity.InGame game:
|
case UserActivity.InGame game:
|
||||||
return game.BeatmapInfo.ToString();
|
return game.BeatmapInfo.ToString() ?? string.Empty;
|
||||||
|
|
||||||
case UserActivity.Editing edit:
|
case UserActivity.Editing edit:
|
||||||
return edit.BeatmapInfo.ToString();
|
return edit.BeatmapInfo.ToString() ?? string.Empty;
|
||||||
|
|
||||||
case UserActivity.InLobby lobby:
|
case UserActivity.InLobby lobby:
|
||||||
return privacyMode.Value == DiscordRichPresenceMode.Limited ? string.Empty : lobby.Room.Name.Value;
|
return privacyMode.Value == DiscordRichPresenceMode.Limited ? string.Empty : lobby.Room.Name.Value;
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Desktop.LegacyIpc
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class LegacyIpcDifficultyCalculationRequest
|
public class LegacyIpcDifficultyCalculationRequest
|
||||||
{
|
{
|
||||||
public string BeatmapFile { get; set; }
|
public string BeatmapFile { get; set; } = string.Empty;
|
||||||
public int RulesetId { get; set; }
|
public int RulesetId { get; set; }
|
||||||
public int Mods { get; set; }
|
public int Mods { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -37,17 +37,20 @@ namespace osu.Desktop.LegacyIpc
|
|||||||
public new object Value
|
public new object Value
|
||||||
{
|
{
|
||||||
get => base.Value;
|
get => base.Value;
|
||||||
set => base.Value = new Data
|
set => base.Value = new Data(value.GetType().Name, value);
|
||||||
{
|
|
||||||
MessageType = value.GetType().Name,
|
|
||||||
MessageData = value
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Data
|
public class Data
|
||||||
{
|
{
|
||||||
public string MessageType { get; set; }
|
public string MessageType { get; }
|
||||||
public object MessageData { get; set; }
|
|
||||||
|
public object MessageData { get; }
|
||||||
|
|
||||||
|
public Data(string messageType, object messageData)
|
||||||
|
{
|
||||||
|
MessageType = messageType;
|
||||||
|
MessageData = messageData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,6 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Taiko;
|
using osu.Game.Rulesets.Taiko;
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
namespace osu.Desktop.LegacyIpc
|
namespace osu.Desktop.LegacyIpc
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -20,23 +20,28 @@ using osu.Game.Updater;
|
|||||||
using osu.Desktop.Windows;
|
using osu.Desktop.Windows;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Game.IO;
|
using osu.Game.IO;
|
||||||
|
using osu.Game.IPC;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
using SDL2;
|
||||||
|
|
||||||
namespace osu.Desktop
|
namespace osu.Desktop
|
||||||
{
|
{
|
||||||
internal class OsuGameDesktop : OsuGame
|
internal partial class OsuGameDesktop : OsuGame
|
||||||
{
|
{
|
||||||
public OsuGameDesktop(string[] args = null)
|
private OsuSchemeLinkIPCChannel? osuSchemeLinkIPCChannel;
|
||||||
|
|
||||||
|
public OsuGameDesktop(string[]? args = null)
|
||||||
: base(args)
|
: base(args)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override StableStorage GetStorageForStableInstall()
|
public override StableStorage? GetStorageForStableInstall()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Host is DesktopGameHost desktopHost)
|
if (Host is DesktopGameHost desktopHost)
|
||||||
{
|
{
|
||||||
string stablePath = getStableInstallPath();
|
string? stablePath = getStableInstallPath();
|
||||||
if (!string.IsNullOrEmpty(stablePath))
|
if (!string.IsNullOrEmpty(stablePath))
|
||||||
return new StableStorage(stablePath, desktopHost);
|
return new StableStorage(stablePath, desktopHost);
|
||||||
}
|
}
|
||||||
@ -49,11 +54,11 @@ namespace osu.Desktop
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getStableInstallPath()
|
private string? getStableInstallPath()
|
||||||
{
|
{
|
||||||
static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")) || File.Exists(Path.Combine(p, "osu!.cfg"));
|
static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")) || File.Exists(Path.Combine(p, "osu!.cfg"));
|
||||||
|
|
||||||
string stableInstallPath;
|
string? stableInstallPath;
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
@ -81,15 +86,15 @@ namespace osu.Desktop
|
|||||||
}
|
}
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
private string getStableInstallPathFromRegistry()
|
private string? getStableInstallPathFromRegistry()
|
||||||
{
|
{
|
||||||
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
|
using (RegistryKey? key = Registry.ClassesRoot.OpenSubKey("osu"))
|
||||||
return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
|
return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override UpdateManager CreateUpdateManager()
|
protected override UpdateManager CreateUpdateManager()
|
||||||
{
|
{
|
||||||
string packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER");
|
string? packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER");
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(packageManaged))
|
if (!string.IsNullOrEmpty(packageManaged))
|
||||||
return new NoActionUpdateManager();
|
return new NoActionUpdateManager();
|
||||||
@ -116,24 +121,29 @@ namespace osu.Desktop
|
|||||||
LoadComponentAsync(new GameplayWinKeyBlocker(), Add);
|
LoadComponentAsync(new GameplayWinKeyBlocker(), Add);
|
||||||
|
|
||||||
LoadComponentAsync(new ElevatedPrivilegesChecker(), Add);
|
LoadComponentAsync(new ElevatedPrivilegesChecker(), Add);
|
||||||
|
|
||||||
|
osuSchemeLinkIPCChannel = new OsuSchemeLinkIPCChannel(Host, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetHost(GameHost host)
|
public override void SetHost(GameHost host)
|
||||||
{
|
{
|
||||||
base.SetHost(host);
|
base.SetHost(host);
|
||||||
|
|
||||||
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
|
||||||
|
|
||||||
var desktopWindow = (SDL2DesktopWindow)host.Window;
|
var desktopWindow = (SDL2DesktopWindow)host.Window;
|
||||||
|
|
||||||
|
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
||||||
|
if (iconStream != null)
|
||||||
|
desktopWindow.SetIconFromStream(iconStream);
|
||||||
|
|
||||||
desktopWindow.CursorState |= CursorState.Hidden;
|
desktopWindow.CursorState |= CursorState.Hidden;
|
||||||
desktopWindow.SetIconFromStream(iconStream);
|
|
||||||
desktopWindow.Title = Name;
|
desktopWindow.Title = Name;
|
||||||
desktopWindow.DragDrop += f => fileDrop(new[] { f });
|
desktopWindow.DragDrop += f => fileDrop(new[] { f });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override BatteryInfo CreateBatteryInfo() => new SDL2BatteryInfo();
|
||||||
|
|
||||||
private readonly List<string> importableFiles = new List<string>();
|
private readonly List<string> importableFiles = new List<string>();
|
||||||
private ScheduledDelegate importSchedule;
|
private ScheduledDelegate? importSchedule;
|
||||||
|
|
||||||
private void fileDrop(string[] filePaths)
|
private void fileDrop(string[] filePaths)
|
||||||
{
|
{
|
||||||
@ -166,5 +176,29 @@ namespace osu.Desktop
|
|||||||
Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning);
|
Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
osuSchemeLinkIPCChannel?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SDL2BatteryInfo : BatteryInfo
|
||||||
|
{
|
||||||
|
public override double? ChargeLevel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
SDL.SDL_GetPowerInfo(out _, out int percentage);
|
||||||
|
|
||||||
|
if (percentage == -1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return percentage / 100.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnBattery => SDL.SDL_GetPowerInfo(out _, out _) == SDL.SDL_PowerState.SDL_POWERSTATE_ON_BATTERY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,24 +9,50 @@ using osu.Framework;
|
|||||||
using osu.Framework.Development;
|
using osu.Framework.Development;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
|
using osu.Game;
|
||||||
using osu.Game.IPC;
|
using osu.Game.IPC;
|
||||||
using osu.Game.Tournament;
|
using osu.Game.Tournament;
|
||||||
|
using SDL2;
|
||||||
using Squirrel;
|
using Squirrel;
|
||||||
|
|
||||||
namespace osu.Desktop
|
namespace osu.Desktop
|
||||||
{
|
{
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
private const string base_game_name = @"osu-development";
|
||||||
|
#else
|
||||||
private const string base_game_name = @"osu";
|
private const string base_game_name = @"osu";
|
||||||
|
#endif
|
||||||
|
|
||||||
private static LegacyTcpIpcProvider legacyIpc;
|
private static LegacyTcpIpcProvider? legacyIpc;
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
// run Squirrel first, as the app may exit after these run
|
// run Squirrel first, as the app may exit after these run
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
var windowsVersion = Environment.OSVersion.Version;
|
||||||
|
|
||||||
|
// While .NET 6 still supports Windows 7 and above, 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/#supported-platforms
|
||||||
|
if (windowsVersion.Major < 6 || (windowsVersion.Major == 6 && windowsVersion.Minor <= 2))
|
||||||
|
{
|
||||||
|
// If users running in compatibility mode becomes more of a common thing, we may want to provide better guidance or even consider
|
||||||
|
// disabling it ourselves.
|
||||||
|
// 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
|
||||||
|
SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR,
|
||||||
|
"Your operating system is too old to run osu!",
|
||||||
|
"This version of osu! requires at least Windows 8.1 to run.\n"
|
||||||
|
+ "Please upgrade your operating system or consider using an older version of osu!.\n\n"
|
||||||
|
+ "If you are running a newer version of windows, please check you don't have \"Compatibility mode\" turned on for osu!", IntPtr.Zero);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setupSquirrel();
|
setupSquirrel();
|
||||||
|
}
|
||||||
|
|
||||||
// Back up the cwd before DesktopGameHost changes it
|
// Back up the cwd before DesktopGameHost changes it
|
||||||
string cwd = Environment.CurrentDirectory;
|
string cwd = Environment.CurrentDirectory;
|
||||||
@ -63,19 +89,8 @@ namespace osu.Desktop
|
|||||||
{
|
{
|
||||||
if (!host.IsPrimaryInstance)
|
if (!host.IsPrimaryInstance)
|
||||||
{
|
{
|
||||||
if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args
|
if (trySendIPCMessage(host, cwd, args))
|
||||||
{
|
|
||||||
var importer = new ArchiveImportIPCChannel(host);
|
|
||||||
|
|
||||||
foreach (string file in args)
|
|
||||||
{
|
|
||||||
Console.WriteLine(@"Importing {0}", file);
|
|
||||||
if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000))
|
|
||||||
throw new TimeoutException(@"IPC took too long to send");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// we want to allow multiple instances to be started when in debug.
|
// we want to allow multiple instances to be started when in debug.
|
||||||
if (!DebugUtils.IsDebugBuild)
|
if (!DebugUtils.IsDebugBuild)
|
||||||
@ -106,18 +121,49 @@ namespace osu.Desktop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool trySendIPCMessage(IIpcHost host, string cwd, string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length == 1 && args[0].StartsWith(OsuGameBase.OSU_PROTOCOL, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var osuSchemeLinkHandler = new OsuSchemeLinkIPCChannel(host);
|
||||||
|
if (!osuSchemeLinkHandler.HandleLinkAsync(args[0]).Wait(3000))
|
||||||
|
throw new IPCTimeoutException(osuSchemeLinkHandler.GetType());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args
|
||||||
|
{
|
||||||
|
var importer = new ArchiveImportIPCChannel(host);
|
||||||
|
|
||||||
|
foreach (string file in args)
|
||||||
|
{
|
||||||
|
Console.WriteLine(@"Importing {0}", file);
|
||||||
|
if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000))
|
||||||
|
throw new IPCTimeoutException(importer.GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
private static void setupSquirrel()
|
private static void setupSquirrel()
|
||||||
{
|
{
|
||||||
SquirrelAwareApp.HandleEvents(onInitialInstall: (version, tools) =>
|
SquirrelAwareApp.HandleEvents(onInitialInstall: (_, tools) =>
|
||||||
{
|
{
|
||||||
tools.CreateShortcutForThisExe();
|
tools.CreateShortcutForThisExe();
|
||||||
tools.CreateUninstallerRegistryEntry();
|
tools.CreateUninstallerRegistryEntry();
|
||||||
}, onAppUninstall: (version, tools) =>
|
}, onAppUpdate: (_, tools) =>
|
||||||
|
{
|
||||||
|
tools.CreateUninstallerRegistryEntry();
|
||||||
|
}, onAppUninstall: (_, tools) =>
|
||||||
{
|
{
|
||||||
tools.RemoveShortcutForThisExe();
|
tools.RemoveShortcutForThisExe();
|
||||||
tools.RemoveUninstallerRegistryEntry();
|
tools.RemoveUninstallerRegistryEntry();
|
||||||
}, onEveryRun: (version, tools, firstRun) =>
|
}, onEveryRun: (_, _, _) =>
|
||||||
{
|
{
|
||||||
// While setting the `ProcessAppUserModelId` fixes duplicate icons/shortcuts on the taskbar, it currently
|
// While setting the `ProcessAppUserModelId` fixes duplicate icons/shortcuts on the taskbar, it currently
|
||||||
// causes the right-click context menu to function incorrectly.
|
// causes the right-click context menu to function incorrectly.
|
||||||
|
@ -16,10 +16,10 @@ namespace osu.Desktop.Security
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the game is running with elevated privileges (as admin in Windows, root in Unix) and displays a warning notification if so.
|
/// Checks if the game is running with elevated privileges (as admin in Windows, root in Unix) and displays a warning notification if so.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ElevatedPrivilegesChecker : Component
|
public partial class ElevatedPrivilegesChecker : Component
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private INotificationOverlay notifications { get; set; }
|
private INotificationOverlay notifications { get; set; } = null!;
|
||||||
|
|
||||||
private bool elevated;
|
private bool elevated;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ namespace osu.Desktop.Security
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ElevatedPrivilegesNotification : SimpleNotification
|
private partial class ElevatedPrivilegesNotification : SimpleNotification
|
||||||
{
|
{
|
||||||
public override bool IsImportant => true;
|
public override bool IsImportant => true;
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ namespace osu.Desktop.Security
|
|||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
Icon = FontAwesome.Solid.ShieldAlt;
|
Icon = FontAwesome.Solid.ShieldAlt;
|
||||||
IconBackground.Colour = colours.YellowDark;
|
IconContent.Colour = colours.YellowDark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,29 +5,24 @@ using System;
|
|||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Colour;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game;
|
using osu.Game;
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Notifications;
|
using osu.Game.Overlays.Notifications;
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using Squirrel;
|
using Squirrel;
|
||||||
using Squirrel.SimpleSplat;
|
using Squirrel.SimpleSplat;
|
||||||
|
using LogLevel = Squirrel.SimpleSplat.LogLevel;
|
||||||
|
using UpdateManager = osu.Game.Updater.UpdateManager;
|
||||||
|
|
||||||
namespace osu.Desktop.Updater
|
namespace osu.Desktop.Updater
|
||||||
{
|
{
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
public class SquirrelUpdateManager : osu.Game.Updater.UpdateManager
|
public partial class SquirrelUpdateManager : UpdateManager
|
||||||
{
|
{
|
||||||
private UpdateManager updateManager;
|
private Squirrel.UpdateManager? updateManager;
|
||||||
private INotificationOverlay notificationOverlay;
|
private INotificationOverlay notificationOverlay = null!;
|
||||||
|
|
||||||
public Task PrepareUpdateAsync() => UpdateManager.RestartAppWhenExited();
|
public Task PrepareUpdateAsync() => Squirrel.UpdateManager.RestartAppWhenExited();
|
||||||
|
|
||||||
private static readonly Logger logger = Logger.GetLogger("updater");
|
private static readonly Logger logger = Logger.GetLogger("updater");
|
||||||
|
|
||||||
@ -38,6 +33,9 @@ namespace osu.Desktop.Updater
|
|||||||
|
|
||||||
private readonly SquirrelLogger squirrelLogger = new SquirrelLogger();
|
private readonly SquirrelLogger squirrelLogger = new SquirrelLogger();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuGameBase game { get; set; } = null!;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(INotificationOverlay notifications)
|
private void load(INotificationOverlay notifications)
|
||||||
{
|
{
|
||||||
@ -48,12 +46,12 @@ namespace osu.Desktop.Updater
|
|||||||
|
|
||||||
protected override async Task<bool> PerformUpdateCheck() => await checkForUpdateAsync().ConfigureAwait(false);
|
protected override async Task<bool> PerformUpdateCheck() => await checkForUpdateAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
private async Task<bool> checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification notification = null)
|
private async Task<bool> checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification? notification = null)
|
||||||
{
|
{
|
||||||
// should we schedule a retry on completion of this check?
|
// should we schedule a retry on completion of this check?
|
||||||
bool scheduleRecheck = true;
|
bool scheduleRecheck = true;
|
||||||
|
|
||||||
const string github_token = null; // TODO: populate.
|
const string? github_token = null; // TODO: populate.
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -66,7 +64,14 @@ namespace osu.Desktop.Updater
|
|||||||
if (updatePending)
|
if (updatePending)
|
||||||
{
|
{
|
||||||
// the user may have dismissed the completion notice, so show it again.
|
// the user may have dismissed the completion notice, so show it again.
|
||||||
notificationOverlay.Post(new UpdateCompleteNotification(this));
|
notificationOverlay.Post(new UpdateApplicationCompleteNotification
|
||||||
|
{
|
||||||
|
Activated = () =>
|
||||||
|
{
|
||||||
|
restartToApplyUpdate();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,19 +83,21 @@ namespace osu.Desktop.Updater
|
|||||||
|
|
||||||
if (notification == null)
|
if (notification == null)
|
||||||
{
|
{
|
||||||
notification = new UpdateProgressNotification(this) { State = ProgressNotificationState.Active };
|
notification = new UpdateProgressNotification
|
||||||
|
{
|
||||||
|
CompletionClickAction = restartToApplyUpdate,
|
||||||
|
};
|
||||||
|
|
||||||
Schedule(() => notificationOverlay.Post(notification));
|
Schedule(() => notificationOverlay.Post(notification));
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.Progress = 0;
|
notification.StartDownload();
|
||||||
notification.Text = @"Downloading update...";
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await updateManager.DownloadReleases(info.ReleasesToApply, p => notification.Progress = p / 100f).ConfigureAwait(false);
|
await updateManager.DownloadReleases(info.ReleasesToApply, p => notification.Progress = p / 100f).ConfigureAwait(false);
|
||||||
|
|
||||||
notification.Progress = 0;
|
notification.StartInstall();
|
||||||
notification.Text = @"Installing update...";
|
|
||||||
|
|
||||||
await updateManager.ApplyReleases(info, p => notification.Progress = p / 100f).ConfigureAwait(false);
|
await updateManager.ApplyReleases(info, p => notification.Progress = p / 100f).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -110,9 +117,7 @@ namespace osu.Desktop.Updater
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// In the case of an error, a separate notification will be displayed.
|
// In the case of an error, a separate notification will be displayed.
|
||||||
notification.State = ProgressNotificationState.Cancelled;
|
notification.FailDownload();
|
||||||
notification.Close();
|
|
||||||
|
|
||||||
Logger.Error(e, @"update failed!");
|
Logger.Error(e, @"update failed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,84 +139,24 @@ namespace osu.Desktop.Updater
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool restartToApplyUpdate()
|
||||||
|
{
|
||||||
|
PrepareUpdateAsync()
|
||||||
|
.ContinueWith(_ => Schedule(() => game.AttemptExit()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
updateManager?.Dispose();
|
updateManager?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UpdateCompleteNotification : ProgressCompletionNotification
|
|
||||||
{
|
|
||||||
[Resolved]
|
|
||||||
private OsuGame game { get; set; }
|
|
||||||
|
|
||||||
public UpdateCompleteNotification(SquirrelUpdateManager updateManager)
|
|
||||||
{
|
|
||||||
Text = @"Update ready to install. Click to restart!";
|
|
||||||
|
|
||||||
Activated = () =>
|
|
||||||
{
|
|
||||||
updateManager.PrepareUpdateAsync()
|
|
||||||
.ContinueWith(_ => updateManager.Schedule(() => game?.GracefullyExit()));
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class UpdateProgressNotification : ProgressNotification
|
|
||||||
{
|
|
||||||
private readonly SquirrelUpdateManager updateManager;
|
|
||||||
|
|
||||||
public UpdateProgressNotification(SquirrelUpdateManager updateManager)
|
|
||||||
{
|
|
||||||
this.updateManager = updateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Notification CreateCompletionNotification()
|
|
||||||
{
|
|
||||||
return new UpdateCompleteNotification(updateManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
IconContent.AddRange(new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = ColourInfo.GradientVertical(colours.YellowDark, colours.Yellow)
|
|
||||||
},
|
|
||||||
new SpriteIcon
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Icon = FontAwesome.Solid.Upload,
|
|
||||||
Colour = Color4.White,
|
|
||||||
Size = new Vector2(20),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Close()
|
|
||||||
{
|
|
||||||
// cancelling updates is not currently supported by the underlying updater.
|
|
||||||
// only allow dismissing for now.
|
|
||||||
|
|
||||||
switch (State)
|
|
||||||
{
|
|
||||||
case ProgressNotificationState.Cancelled:
|
|
||||||
base.Close();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SquirrelLogger : ILogger, IDisposable
|
private class SquirrelLogger : ILogger, IDisposable
|
||||||
{
|
{
|
||||||
public Squirrel.SimpleSplat.LogLevel Level { get; set; } = Squirrel.SimpleSplat.LogLevel.Info;
|
public LogLevel Level { get; set; } = LogLevel.Info;
|
||||||
|
|
||||||
public void Write(string message, Squirrel.SimpleSplat.LogLevel logLevel)
|
public void Write(string message, LogLevel logLevel)
|
||||||
{
|
{
|
||||||
if (logLevel < Level)
|
if (logLevel < Level)
|
||||||
return;
|
return;
|
||||||
|
@ -10,14 +10,14 @@ using osu.Game.Screens.Play;
|
|||||||
|
|
||||||
namespace osu.Desktop.Windows
|
namespace osu.Desktop.Windows
|
||||||
{
|
{
|
||||||
public class GameplayWinKeyBlocker : Component
|
public partial class GameplayWinKeyBlocker : Component
|
||||||
{
|
{
|
||||||
private Bindable<bool> disableWinKey;
|
private Bindable<bool> disableWinKey = null!;
|
||||||
private IBindable<bool> localUserPlaying;
|
private IBindable<bool> localUserPlaying = null!;
|
||||||
private IBindable<bool> isActive;
|
private IBindable<bool> isActive = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private GameHost host { get; set; }
|
private GameHost host { get; set; } = null!;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ILocalUserPlayInfo localUserInfo, OsuConfigManager config)
|
private void load(ILocalUserPlayInfo localUserInfo, OsuConfigManager config)
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Desktop.Windows
|
|||||||
private const int wm_syskeyup = 261;
|
private const int wm_syskeyup = 261;
|
||||||
|
|
||||||
//Resharper disable once NotAccessedField.Local
|
//Resharper disable once NotAccessedField.Local
|
||||||
private static LowLevelKeyboardProcDelegate keyboardHookDelegate; // keeping a reference alive for the GC
|
private static LowLevelKeyboardProcDelegate? keyboardHookDelegate; // keeping a reference alive for the GC
|
||||||
private static IntPtr keyHook;
|
private static IntPtr keyHook;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
@ -24,15 +24,10 @@
|
|||||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Clowd.Squirrel" Version="2.9.40" />
|
<PackageReference Include="Clowd.Squirrel" Version="2.9.42" />
|
||||||
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
|
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
|
||||||
<PackageReference Include="System.IO.Packaging" Version="6.0.0" />
|
<PackageReference Include="System.IO.Packaging" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.14" />
|
<PackageReference Include="DiscordRichPresence" Version="1.1.1.14" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.14">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Resources">
|
<ItemGroup Label="Resources">
|
||||||
<EmbeddedResource Include="lazer.ico" />
|
<EmbeddedResource Include="lazer.ico" />
|
||||||
|
166
osu.Game.Benchmarks/BenchmarkHitObject.cs
Normal file
166
osu.Game.Benchmarks/BenchmarkHitObject.cs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
// 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 BenchmarkDotNet.Attributes;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Benchmarks
|
||||||
|
{
|
||||||
|
public class BenchmarkHitObject : BenchmarkTest
|
||||||
|
{
|
||||||
|
[Params(1, 100, 1000)]
|
||||||
|
public int Count { get; set; }
|
||||||
|
|
||||||
|
[Params(false, true)]
|
||||||
|
public bool WithBindableAccess { get; set; }
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public HitCircle[] OsuCircle()
|
||||||
|
{
|
||||||
|
var circles = new HitCircle[Count];
|
||||||
|
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
circles[i] = new HitCircle();
|
||||||
|
|
||||||
|
if (WithBindableAccess)
|
||||||
|
{
|
||||||
|
_ = circles[i].PositionBindable;
|
||||||
|
_ = circles[i].ScaleBindable;
|
||||||
|
_ = circles[i].ComboIndexBindable;
|
||||||
|
_ = circles[i].ComboOffsetBindable;
|
||||||
|
_ = circles[i].StackHeightBindable;
|
||||||
|
_ = circles[i].LastInComboBindable;
|
||||||
|
_ = circles[i].ComboIndexWithOffsetsBindable;
|
||||||
|
_ = circles[i].IndexInCurrentComboBindable;
|
||||||
|
_ = circles[i].SamplesBindable;
|
||||||
|
_ = circles[i].StartTimeBindable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ = circles[i].Position;
|
||||||
|
_ = circles[i].Scale;
|
||||||
|
_ = circles[i].ComboIndex;
|
||||||
|
_ = circles[i].ComboOffset;
|
||||||
|
_ = circles[i].StackHeight;
|
||||||
|
_ = circles[i].LastInCombo;
|
||||||
|
_ = circles[i].ComboIndexWithOffsets;
|
||||||
|
_ = circles[i].IndexInCurrentCombo;
|
||||||
|
_ = circles[i].Samples;
|
||||||
|
_ = circles[i].StartTime;
|
||||||
|
_ = circles[i].Position;
|
||||||
|
_ = circles[i].Scale;
|
||||||
|
_ = circles[i].ComboIndex;
|
||||||
|
_ = circles[i].ComboOffset;
|
||||||
|
_ = circles[i].StackHeight;
|
||||||
|
_ = circles[i].LastInCombo;
|
||||||
|
_ = circles[i].ComboIndexWithOffsets;
|
||||||
|
_ = circles[i].IndexInCurrentCombo;
|
||||||
|
_ = circles[i].Samples;
|
||||||
|
_ = circles[i].StartTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return circles;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public Hit[] TaikoHit()
|
||||||
|
{
|
||||||
|
var hits = new Hit[Count];
|
||||||
|
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
hits[i] = new Hit();
|
||||||
|
|
||||||
|
if (WithBindableAccess)
|
||||||
|
{
|
||||||
|
_ = hits[i].TypeBindable;
|
||||||
|
_ = hits[i].IsStrongBindable;
|
||||||
|
_ = hits[i].SamplesBindable;
|
||||||
|
_ = hits[i].StartTimeBindable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ = hits[i].Type;
|
||||||
|
_ = hits[i].IsStrong;
|
||||||
|
_ = hits[i].Samples;
|
||||||
|
_ = hits[i].StartTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public Fruit[] CatchFruit()
|
||||||
|
{
|
||||||
|
var fruit = new Fruit[Count];
|
||||||
|
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
fruit[i] = new Fruit();
|
||||||
|
|
||||||
|
if (WithBindableAccess)
|
||||||
|
{
|
||||||
|
_ = fruit[i].OriginalXBindable;
|
||||||
|
_ = fruit[i].XOffsetBindable;
|
||||||
|
_ = fruit[i].ScaleBindable;
|
||||||
|
_ = fruit[i].ComboIndexBindable;
|
||||||
|
_ = fruit[i].HyperDashBindable;
|
||||||
|
_ = fruit[i].LastInComboBindable;
|
||||||
|
_ = fruit[i].ComboIndexWithOffsetsBindable;
|
||||||
|
_ = fruit[i].IndexInCurrentComboBindable;
|
||||||
|
_ = fruit[i].IndexInBeatmapBindable;
|
||||||
|
_ = fruit[i].SamplesBindable;
|
||||||
|
_ = fruit[i].StartTimeBindable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ = fruit[i].OriginalX;
|
||||||
|
_ = fruit[i].XOffset;
|
||||||
|
_ = fruit[i].Scale;
|
||||||
|
_ = fruit[i].ComboIndex;
|
||||||
|
_ = fruit[i].HyperDash;
|
||||||
|
_ = fruit[i].LastInCombo;
|
||||||
|
_ = fruit[i].ComboIndexWithOffsets;
|
||||||
|
_ = fruit[i].IndexInCurrentCombo;
|
||||||
|
_ = fruit[i].IndexInBeatmap;
|
||||||
|
_ = fruit[i].Samples;
|
||||||
|
_ = fruit[i].StartTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fruit;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public Note[] ManiaNote()
|
||||||
|
{
|
||||||
|
var notes = new Note[Count];
|
||||||
|
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
notes[i] = new Note();
|
||||||
|
|
||||||
|
if (WithBindableAccess)
|
||||||
|
{
|
||||||
|
_ = notes[i].ColumnBindable;
|
||||||
|
_ = notes[i].SamplesBindable;
|
||||||
|
_ = notes[i].StartTimeBindable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ = notes[i].Column;
|
||||||
|
_ = notes[i].Samples;
|
||||||
|
_ = notes[i].StartTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return notes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ namespace osu.Game.Benchmarks
|
|||||||
{
|
{
|
||||||
public class BenchmarkMod : BenchmarkTest
|
public class BenchmarkMod : BenchmarkTest
|
||||||
{
|
{
|
||||||
private OsuModDoubleTime mod;
|
private OsuModDoubleTime mod = null!;
|
||||||
|
|
||||||
[Params(1, 10, 100)]
|
[Params(1, 10, 100)]
|
||||||
public int Times { get; set; }
|
public int Times { get; set; }
|
||||||
|
@ -15,9 +15,9 @@ namespace osu.Game.Benchmarks
|
|||||||
{
|
{
|
||||||
public class BenchmarkRealmReads : BenchmarkTest
|
public class BenchmarkRealmReads : BenchmarkTest
|
||||||
{
|
{
|
||||||
private TemporaryNativeStorage storage;
|
private TemporaryNativeStorage storage = null!;
|
||||||
private RealmAccess realm;
|
private RealmAccess realm = null!;
|
||||||
private UpdateThread updateThread;
|
private UpdateThread updateThread = null!;
|
||||||
|
|
||||||
[Params(1, 100, 1000)]
|
[Params(1, 100, 1000)]
|
||||||
public int ReadsPerFetch { get; set; }
|
public int ReadsPerFetch { get; set; }
|
||||||
@ -29,7 +29,7 @@ namespace osu.Game.Benchmarks
|
|||||||
|
|
||||||
realm = new RealmAccess(storage, OsuGameBase.CLIENT_DATABASE_FILENAME);
|
realm = new RealmAccess(storage, OsuGameBase.CLIENT_DATABASE_FILENAME);
|
||||||
|
|
||||||
realm.Run(r =>
|
realm.Run(_ =>
|
||||||
{
|
{
|
||||||
realm.Write(c => c.Add(TestResources.CreateTestBeatmapSetInfo(rulesets: new[] { new OsuRuleset().RulesetInfo })));
|
realm.Write(c => c.Add(TestResources.CreateTestBeatmapSetInfo(rulesets: new[] { new OsuRuleset().RulesetInfo })));
|
||||||
});
|
});
|
||||||
@ -74,7 +74,7 @@ namespace osu.Game.Benchmarks
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
done.Wait();
|
done.Wait(60000);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
@ -113,7 +113,7 @@ namespace osu.Game.Benchmarks
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
done.Wait();
|
done.Wait(60000);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Benchmark]
|
[Benchmark]
|
||||||
@ -133,9 +133,9 @@ namespace osu.Game.Benchmarks
|
|||||||
[GlobalCleanup]
|
[GlobalCleanup]
|
||||||
public void Cleanup()
|
public void Cleanup()
|
||||||
{
|
{
|
||||||
realm?.Dispose();
|
realm.Dispose();
|
||||||
storage?.Dispose();
|
storage.Dispose();
|
||||||
updateThread?.Exit();
|
updateThread.Exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ namespace osu.Game.Benchmarks
|
|||||||
{
|
{
|
||||||
public class BenchmarkRuleset : BenchmarkTest
|
public class BenchmarkRuleset : BenchmarkTest
|
||||||
{
|
{
|
||||||
private OsuRuleset ruleset;
|
private OsuRuleset ruleset = null!;
|
||||||
private APIMod apiModDoubleTime;
|
private APIMod apiModDoubleTime = null!;
|
||||||
private APIMod apiModDifficultyAdjust;
|
private APIMod apiModDifficultyAdjust = null!;
|
||||||
|
|
||||||
public override void SetUp()
|
public override void SetUp()
|
||||||
{
|
{
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
|
||||||
<PackageReference Include="nunit" Version="3.13.3" />
|
<PackageReference Include="nunit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- using a different name because package name cannot contain 'catch' -->
|
<!-- using a different name because package name cannot contain 'catch' -->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Catch_Tests.Android" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Catch_Tests.Android" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
|
||||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!catch Test" />
|
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!catch Test" />
|
||||||
</manifest>
|
</manifest>
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using osu.Framework.Android;
|
using osu.Framework.Android;
|
||||||
using osu.Game.Tests;
|
using osu.Game.Tests;
|
||||||
|
@ -1,49 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="..\osu.Android.props" />
|
<Import Project="..\osu.Android.props" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<TargetFramework>net6.0-android</TargetFramework>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<OutputType>Exe</OutputType>
|
||||||
<ProductVersion>8.0.30703</ProductVersion>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
<ProjectGuid>{C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}</ProjectGuid>
|
|
||||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
|
||||||
<TemplateGuid>{122416d6-6b49-4ee2-a1e8-b825f31c79fe}</TemplateGuid>
|
|
||||||
<RootNamespace>osu.Game.Rulesets.Catch.Tests</RootNamespace>
|
<RootNamespace>osu.Game.Rulesets.Catch.Tests</RootNamespace>
|
||||||
<AssemblyName>osu.Game.Rulesets.Catch.Tests.Android</AssemblyName>
|
<AssemblyName>osu.Game.Rulesets.Catch.Tests.Android</AssemblyName>
|
||||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
|
||||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<AndroidLinkMode>None</AndroidLinkMode>
|
|
||||||
<MandroidI18n>cjk;mideast;other;rare;west</MandroidI18n>
|
|
||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="MainActivity.cs" />
|
<Compile Include="..\osu.Game.Rulesets.Catch.Tests\**\*.cs" Exclude="**\obj\**">
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Properties\AndroidManifest.xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\osu.Game.Rulesets.Catch.Tests\*.cs">
|
|
||||||
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
|
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<!-- TargetPath is relative to RootNamespace,
|
||||||
|
and DllResourceStore is relative to AssemblyName. -->
|
||||||
|
<EmbeddedResource Include="..\osu.Game.Rulesets.Catch.Tests\**\Resources\**\*">
|
||||||
|
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||||
|
<TargetPath>Android\%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
|
||||||
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
<Project>{58f6c80c-1253-4a0e-a465-b8c85ebeadf3}</Project>
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||||
<Name>osu.Game.Rulesets.Catch</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
|
||||||
<Project>{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}</Project>
|
|
||||||
<Name>osu.Game</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="System.Formats.Asn1">
|
|
||||||
<Version>5.0.0</Version>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
|
||||||
</Project>
|
</Project>
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using Foundation;
|
using Foundation;
|
||||||
using osu.Framework.iOS;
|
using osu.Framework.iOS;
|
||||||
using osu.Game.Tests;
|
using osu.Game.Tests;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.iOS;
|
#nullable disable
|
||||||
|
|
||||||
using UIKit;
|
using UIKit;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests.iOS
|
namespace osu.Game.Rulesets.Catch.Tests.iOS
|
||||||
@ -10,7 +11,7 @@ namespace osu.Game.Rulesets.Catch.Tests.iOS
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate));
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>10.0</string>
|
<string>13.4</string>
|
||||||
<key>UIDeviceFamily</key>
|
<key>UIDeviceFamily</key>
|
||||||
<array>
|
<array>
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
|
@ -1,35 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
|
|
||||||
<ProjectGuid>{4004C7B7-1A62-43F1-9DF2-52450FA67E70}</ProjectGuid>
|
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0-ios</TargetFramework>
|
||||||
|
<SupportedOSPlatformVersion>13.4</SupportedOSPlatformVersion>
|
||||||
<RootNamespace>osu.Game.Rulesets.Catch.Tests</RootNamespace>
|
<RootNamespace>osu.Game.Rulesets.Catch.Tests</RootNamespace>
|
||||||
<AssemblyName>osu.Game.Rulesets.Catch.Tests.iOS</AssemblyName>
|
<AssemblyName>osu.Game.Rulesets.Catch.Tests.iOS</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="..\osu.iOS.props" />
|
<Import Project="..\osu.iOS.props" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Info.plist" />
|
|
||||||
<None Include="Entitlements.plist" />
|
|
||||||
<LinkDescription Include="..\osu.iOS\Linker.xml">
|
|
||||||
<Link>Linker.xml</Link>
|
|
||||||
</LinkDescription>
|
|
||||||
<Compile Include="Application.cs" />
|
|
||||||
<Compile Include="AppDelegate.cs" />
|
|
||||||
<Compile Include="..\osu.Game.Rulesets.Catch.Tests\**\*.cs" Exclude="**\obj\**">
|
<Compile Include="..\osu.Game.Rulesets.Catch.Tests\**\*.cs" Exclude="**\obj\**">
|
||||||
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
|
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||||
<Project>{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}</Project>
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
<Name>osu.Game</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
|
|
||||||
<Project>{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}</Project>
|
|
||||||
<Name>osu.Game.Rulesets.Catch</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
</Project>
|
||||||
</Project>
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Difficulty;
|
using osu.Game.Rulesets.Catch.Difficulty;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps.Legacy;
|
using osu.Game.Beatmaps.Legacy;
|
||||||
@ -22,21 +24,24 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
new object[] { LegacyMods.DoubleTime, new[] { typeof(CatchModDoubleTime) } },
|
new object[] { LegacyMods.DoubleTime, new[] { typeof(CatchModDoubleTime) } },
|
||||||
new object[] { LegacyMods.Relax, new[] { typeof(CatchModRelax) } },
|
new object[] { LegacyMods.Relax, new[] { typeof(CatchModRelax) } },
|
||||||
new object[] { LegacyMods.HalfTime, new[] { typeof(CatchModHalfTime) } },
|
new object[] { LegacyMods.HalfTime, new[] { typeof(CatchModHalfTime) } },
|
||||||
new object[] { LegacyMods.Nightcore, new[] { typeof(CatchModNightcore) } },
|
|
||||||
new object[] { LegacyMods.Flashlight, new[] { typeof(CatchModFlashlight) } },
|
new object[] { LegacyMods.Flashlight, new[] { typeof(CatchModFlashlight) } },
|
||||||
new object[] { LegacyMods.Autoplay, new[] { typeof(CatchModAutoplay) } },
|
new object[] { LegacyMods.Autoplay, new[] { typeof(CatchModAutoplay) } },
|
||||||
new object[] { LegacyMods.Perfect, new[] { typeof(CatchModPerfect) } },
|
|
||||||
new object[] { LegacyMods.Cinema, new[] { typeof(CatchModCinema) } },
|
|
||||||
new object[] { LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(CatchModHardRock), typeof(CatchModDoubleTime) } }
|
new object[] { LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(CatchModHardRock), typeof(CatchModDoubleTime) } }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[TestCaseSource(nameof(catch_mod_mapping))]
|
||||||
|
[TestCase(LegacyMods.Cinema, new[] { typeof(CatchModCinema) })]
|
||||||
|
[TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(CatchModCinema) })]
|
||||||
|
[TestCase(LegacyMods.Nightcore, new[] { typeof(CatchModNightcore) })]
|
||||||
|
[TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModNightcore) })]
|
||||||
|
[TestCase(LegacyMods.Perfect, new[] { typeof(CatchModPerfect) })]
|
||||||
|
[TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(CatchModPerfect) })]
|
||||||
|
public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods);
|
||||||
|
|
||||||
[TestCaseSource(nameof(catch_mod_mapping))]
|
[TestCaseSource(nameof(catch_mod_mapping))]
|
||||||
[TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(CatchModCinema) })]
|
[TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(CatchModCinema) })]
|
||||||
[TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModNightcore) })]
|
[TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModNightcore) })]
|
||||||
[TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(CatchModPerfect) })]
|
[TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(CatchModPerfect) })]
|
||||||
public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods);
|
|
||||||
|
|
||||||
[TestCaseSource(nameof(catch_mod_mapping))]
|
|
||||||
public new void TestToLegacy(LegacyMods legacyMods, Type[] givenMods) => base.TestToLegacy(legacyMods, givenMods);
|
public new void TestToLegacy(LegacyMods legacyMods, Type[] givenMods) => base.TestToLegacy(legacyMods, givenMods);
|
||||||
|
|
||||||
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
using osu.Game.Rulesets.Catch.Skinning;
|
using osu.Game.Rulesets.Catch.Skinning;
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
{
|
{
|
||||||
public abstract class CatchSkinnableTestScene : SkinnableTestScene
|
public abstract partial class CatchSkinnableTestScene : SkinnableTestScene
|
||||||
{
|
{
|
||||||
protected override Ruleset CreateRulesetForSkinProvider() => new CatchRuleset();
|
protected override Ruleset CreateRulesetForSkinProvider() => new CatchRuleset();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -14,7 +16,7 @@ using osu.Game.Tests.Visual;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||||
{
|
{
|
||||||
public class CatchEditorTestSceneContainer : Container
|
public partial class CatchEditorTestSceneContainer : Container
|
||||||
{
|
{
|
||||||
[Cached(typeof(Playfield))]
|
[Cached(typeof(Playfield))]
|
||||||
public readonly ScrollingPlayfield Playfield;
|
public readonly ScrollingPlayfield Playfield;
|
||||||
@ -55,7 +57,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestCatchPlayfield : CatchEditorPlayfield
|
private partial class TestCatchPlayfield : CatchEditorPlayfield
|
||||||
{
|
{
|
||||||
public TestCatchPlayfield()
|
public TestCatchPlayfield()
|
||||||
: base(new BeatmapDifficulty { CircleSize = 0 })
|
: base(new BeatmapDifficulty { CircleSize = 0 })
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -19,7 +21,7 @@ using osuTK.Input;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||||
{
|
{
|
||||||
public abstract class CatchPlacementBlueprintTestScene : PlacementBlueprintTestScene
|
public abstract partial class CatchPlacementBlueprintTestScene : PlacementBlueprintTestScene
|
||||||
{
|
{
|
||||||
protected const double TIME_SNAP = 100;
|
protected const double TIME_SNAP = 100;
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user