Compare commits
95 Commits
1.6.0-1.16
...
1.18
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a70ab1961 | ||
|
|
1722c2ccaa | ||
|
|
46dafc3e71 | ||
|
|
99298b2bc4 | ||
|
|
070083ab6e | ||
|
|
4d74892e53 | ||
|
|
2e861470d8 | ||
|
|
e87ed53485 | ||
|
|
8847c7f499 | ||
|
|
da2773b1e9 | ||
|
|
3650e756c3 | ||
|
|
6b885beede | ||
|
|
abb3d1de3c | ||
|
|
a8cdfeeba9 | ||
|
|
ed4d310565 | ||
|
|
ac73c99506 | ||
|
|
d45eeac6dc | ||
|
|
77ff589544 | ||
|
|
ce5c0b22db | ||
|
|
98af13fd0b | ||
|
|
2387444d3a | ||
|
|
57860490c8 | ||
|
|
f46aa175a4 | ||
|
|
78390ca02f | ||
|
|
31821b4833 | ||
|
|
e34ba6025a | ||
|
|
e8cfee7de5 | ||
|
|
06c589e7f8 | ||
|
|
a71dcb9765 | ||
|
|
9891cd2977 | ||
|
|
8566e859e3 | ||
|
|
281b266b18 | ||
|
|
8d4f8822d3 | ||
|
|
735b9e8718 | ||
|
|
71ee3d8e0a | ||
|
|
11f102759c | ||
|
|
02dd543027 | ||
|
|
c247e51d00 | ||
|
|
e3052343d3 | ||
|
|
9e879f9230 | ||
|
|
bda436d863 | ||
|
|
98d2cdae63 | ||
|
|
8e0e444d15 | ||
|
|
f586647e07 | ||
|
|
73ab8456e7 | ||
|
|
1a3d7ce225 | ||
|
|
965ab57159 | ||
|
|
c8dba43b90 | ||
|
|
dd8e62c73e | ||
|
|
b24a158b9b | ||
|
|
df7c7bbdad | ||
|
|
3ddae57eab | ||
|
|
a0701f55f6 | ||
|
|
b15766dfdb | ||
|
|
19ed068da9 | ||
|
|
d2e21f8723 | ||
|
|
b3f7350de9 | ||
|
|
34408d7a2a | ||
|
|
6e64c7c97d | ||
|
|
bca73c93cc | ||
|
|
913e79fe5b | ||
|
|
b1334a0455 | ||
|
|
ce9495c79c | ||
|
|
ff8270d18a | ||
|
|
3f33549760 | ||
|
|
d034607032 | ||
|
|
e9a11c0ab9 | ||
|
|
e0d90fc56a | ||
|
|
cac23d12a1 | ||
|
|
b982772d31 | ||
|
|
e4ca0db2a2 | ||
|
|
f0cd2a51d1 | ||
|
|
9d37862144 | ||
|
|
c31fb76215 | ||
|
|
b6563af2b1 | ||
|
|
1a0030a680 | ||
|
|
78c858b753 | ||
|
|
24288b3ebd | ||
|
|
0226bfc62f | ||
|
|
28d92a65d4 | ||
|
|
132bdc0cc5 | ||
|
|
bdffef681f | ||
|
|
a49a64ef44 | ||
|
|
0e192b2af4 | ||
|
|
6dd654f2f5 | ||
|
|
eb406a4681 | ||
|
|
d386e3d9a2 | ||
|
|
5fcf4c2b1b | ||
|
|
bfaa4f5d9a | ||
|
|
5d5d808403 | ||
|
|
d08647b3fc | ||
|
|
1039ea5344 | ||
|
|
bb19ea4da5 | ||
|
|
a1773cc0d9 | ||
|
|
e652390583 |
23
.github/workflows/gradlebuild.yml
vendored
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
name: Gradle Build
|
||||||
|
|
||||||
|
on: [ push, pull_request ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK 16
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 16
|
||||||
|
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
|
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew build
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Artifacts
|
||||||
|
path: ./build/libs/
|
||||||
40
.github/workflows/gradlepublish.yml
vendored
Executable file
@@ -0,0 +1,40 @@
|
|||||||
|
name: Gradle Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK 16
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 16
|
||||||
|
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
|
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew build
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Artifacts
|
||||||
|
path: ./build/libs/
|
||||||
|
|
||||||
|
# The USERNAME and PASSWORD need to correspond to the credentials environment variables used in
|
||||||
|
# the publishing section of your build.gradle
|
||||||
|
- name: Publish to GitHub Packages and other Mavens
|
||||||
|
run: ./gradlew publish
|
||||||
|
env:
|
||||||
|
BRANCH_NAME: ${{ github.ref }}
|
||||||
|
RUN_COUNT: ${{ github.run_number }}
|
||||||
|
REPO_NAME: ${{ github.repository }}
|
||||||
|
USERNAME: ${{ github.actor }}
|
||||||
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
midnightcontrols_MAVEN: ${{ secrets.MAVEN_URL }}
|
||||||
|
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
|
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
23
.github/workflows/modrinth_update.yml
vendored
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
name: Gradle Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK 16
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 16
|
||||||
|
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
|
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
env:
|
||||||
|
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||||
|
run: ./gradlew publishModrinth
|
||||||
7
.gitignore
vendored
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# LambdAurora's ignore file
|
# LambdAurora's ignore file
|
||||||
#
|
#
|
||||||
# v0.13
|
# v0.15
|
||||||
|
|
||||||
# JetBrains
|
# JetBrains
|
||||||
.idea/
|
.idea/
|
||||||
@@ -53,6 +53,8 @@ __pycache__/
|
|||||||
# OS
|
# OS
|
||||||
## Windows
|
## Windows
|
||||||
desktop.ini
|
desktop.ini
|
||||||
|
# MacOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
# File types
|
# File types
|
||||||
*.dll
|
*.dll
|
||||||
@@ -61,10 +63,13 @@ desktop.ini
|
|||||||
*.lib
|
*.lib
|
||||||
lib*.a
|
lib*.a
|
||||||
*.png~
|
*.png~
|
||||||
|
*.tar.?z
|
||||||
|
|
||||||
# Common
|
# Common
|
||||||
bin/
|
bin/
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
|
lib/
|
||||||
|
obj/
|
||||||
run/
|
run/
|
||||||
target/
|
target/
|
||||||
|
|||||||
63
CHANGELOG.md
@@ -1,6 +1,22 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## v1.0.0
|
# MidnightControls
|
||||||
|
|
||||||
|
## 0.1.0
|
||||||
|
First beta!
|
||||||
|
Changes from LambdaControls:
|
||||||
|
|
||||||
|
- Support for Steam Deck and Dualsense
|
||||||
|
- Support for L4, L5, R4, R5 buttons
|
||||||
|
- Updated Libraries
|
||||||
|
- New Logo and Name
|
||||||
|
- Lots of Bugfixes
|
||||||
|
- MidnightConfig backend
|
||||||
|
|
||||||
|
|
||||||
|
# LambdaControls
|
||||||
|
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
:tada: First release! :tada:
|
:tada: First release! :tada:
|
||||||
|
|
||||||
@@ -12,11 +28,11 @@
|
|||||||
- Added key bindings for look around.
|
- Added key bindings for look around.
|
||||||
- And more!
|
- And more!
|
||||||
|
|
||||||
### v1.0.1
|
### 1.0.1
|
||||||
|
|
||||||
- Fixed tutorial toast to look around not affected by camera movement done with a controller. ([#2](https://github.com/LambdAurora/LambdaControls/issues/2))
|
- Fixed tutorial toast to look around not affected by camera movement done with a controller. ([#2](https://github.com/LambdAurora/LambdaControls/issues/2))
|
||||||
|
|
||||||
### v1.0.2 (Unofficial)
|
### 1.0.2 (Unofficial)
|
||||||
|
|
||||||
This update was never pushed but was aiming to fix [#4](https://github.com/LambdAurora/LambdaControls/issues/4).
|
This update was never pushed but was aiming to fix [#4](https://github.com/LambdAurora/LambdaControls/issues/4).
|
||||||
|
|
||||||
@@ -24,7 +40,7 @@ This update was never pushed but was aiming to fix [#4](https://github.com/Lambd
|
|||||||
- Fixed broken chat arrow keys.
|
- Fixed broken chat arrow keys.
|
||||||
- Optimized a little bit the button indicator. (need more work)
|
- Optimized a little bit the button indicator. (need more work)
|
||||||
|
|
||||||
## v1.1.0 - Chording update
|
## 1.1.0 - Chording update
|
||||||
|
|
||||||
This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAurora/LambdaControls/issues/9)).
|
This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAurora/LambdaControls/issues/9)).
|
||||||
|
|
||||||
@@ -46,9 +62,9 @@ This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAur
|
|||||||
- HUD side affects button indicators now.
|
- HUD side affects button indicators now.
|
||||||
- Added support for Advancements tabs.
|
- Added support for Advancements tabs.
|
||||||
|
|
||||||
### v1.1.1
|
### 1.1.1
|
||||||
|
|
||||||
## v1.2.0-1.3.0
|
## 1.2.0-1.3.0
|
||||||
|
|
||||||
- Improved rotation algorithm ([#11](https://github.com/LambdAurora/LambdaControls/issues/11)).
|
- Improved rotation algorithm ([#11](https://github.com/LambdAurora/LambdaControls/issues/11)).
|
||||||
- Added virtual mouse.
|
- Added virtual mouse.
|
||||||
@@ -60,21 +76,21 @@ This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAur
|
|||||||
- And more!
|
- And more!
|
||||||
- v1.3.0 specific: Updated to Minecraft 1.16.1
|
- v1.3.0 specific: Updated to Minecraft 1.16.1
|
||||||
|
|
||||||
### v1.3.1
|
### 1.3.1
|
||||||
|
|
||||||
- Fixed broken inventory interactions ([#13](https://github.com/LambdAurora/LambdaControls/issues/13))
|
- Fixed broken inventory interactions ([#13](https://github.com/LambdAurora/LambdaControls/issues/13))
|
||||||
- Fixed virtual mouse preventing continuous attack (thus making breaking blocks impossible).
|
- Fixed virtual mouse preventing continuous attack (thus making breaking blocks impossible).
|
||||||
- Added support for [ModUpdater](https://gitea.thebrokenrail.com/TheBrokenRail/ModUpdater) hopefully.
|
- Added support for [ModUpdater](https://gitea.thebrokenrail.com/TheBrokenRail/ModUpdater) hopefully.
|
||||||
- Updated [SpruceUI](https://github.com/LambdAurora/SpruceUI) to 1.5.2.
|
- Updated [SpruceUI](https://github.com/LambdAurora/SpruceUI) to 1.5.2.
|
||||||
|
|
||||||
### v1.3.2
|
### 1.3.2
|
||||||
|
|
||||||
- Added vertical reacharound.
|
- Added vertical reacharound.
|
||||||
- Added more API for compatibility handlers.
|
- Added more API for compatibility handlers.
|
||||||
- Improved reacharound API.
|
- Improved reacharound API.
|
||||||
- Improved [REI](https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items) compatibility.
|
- Improved [REI](https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items) compatibility.
|
||||||
|
|
||||||
## v1.4.0
|
## 1.4.0
|
||||||
|
|
||||||
- Added analog movements ([#10](https://github.com/LambdAurora/LambdaControls/issues/10)).
|
- Added analog movements ([#10](https://github.com/LambdAurora/LambdaControls/issues/10)).
|
||||||
- Improved Ok Zoomer compability.
|
- Improved Ok Zoomer compability.
|
||||||
@@ -90,11 +106,11 @@ This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAur
|
|||||||
- Will allow for better compability with other mods.
|
- Will allow for better compability with other mods.
|
||||||
- Might be interesting for keyboard users too.
|
- Might be interesting for keyboard users too.
|
||||||
|
|
||||||
### v1.4.1
|
### 1.4.1
|
||||||
|
|
||||||
- Fixed crash with [REI](https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items).
|
- Fixed crash with [REI](https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items).
|
||||||
|
|
||||||
## v1.5.0
|
## 1.5.0
|
||||||
|
|
||||||
- Added mappings string editor screen.
|
- Added mappings string editor screen.
|
||||||
- Added Simplified Chinese translations ([#18](https://github.com/LambdAurora/LambdaControls/pull/18)).
|
- Added Simplified Chinese translations ([#18](https://github.com/LambdAurora/LambdaControls/pull/18)).
|
||||||
@@ -104,9 +120,32 @@ This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAur
|
|||||||
- Respect toggle setting in Accessibility screen.
|
- Respect toggle setting in Accessibility screen.
|
||||||
- Tweaked rotation speeds.
|
- Tweaked rotation speeds.
|
||||||
- Updated to Minecraft 1.16.2.
|
- Updated to Minecraft 1.16.2.
|
||||||
- Updated [SpruceUI](https://github.com/LambdAurora/SpruceUI) to 1.6.4.
|
- Updated [SpruceUI] to 1.6.4.
|
||||||
- Overhauled REI compatibility.
|
- Overhauled REI compatibility.
|
||||||
- Improved horizontal reach-around.
|
- Improved horizontal reach-around.
|
||||||
- Fixed crashes with Ok Zoomer.
|
- Fixed crashes with Ok Zoomer.
|
||||||
- Fixed crashes with key unbinding.
|
- Fixed crashes with key unbinding.
|
||||||
- More WIP on keybind ring.
|
- More WIP on keybind ring.
|
||||||
|
|
||||||
|
## 1.6.0
|
||||||
|
|
||||||
|
- Reworked entirely the settings screen.
|
||||||
|
- Added independent stick dead zones. ([#32](https://github.com/LambdAurora/LambdaControls/issues/32))
|
||||||
|
- Added max values range. ([#41](https://github.com/LambdAurora/LambdaControls/issues/41))
|
||||||
|
- Updated [SpruceUI] and fix related crashes due to incompatible versions ([#40](https://github.com/LambdAurora/LambdaControls/issues/40), [#48](https://github.com/LambdAurora/LambdaControls/issues/48)).
|
||||||
|
- Fix boat control issues ([#37](https://github.com/LambdAurora/LambdaControls/issues/37)).
|
||||||
|
- Fix incompatibilities with mods using night-config. Now shadowing properly night-config. ([#33](https://github.com/LambdAurora/LambdaControls/issues/33), [#39](https://github.com/LambdAurora/LambdaControls/issues/39))
|
||||||
|
|
||||||
|
## 1.7.0
|
||||||
|
|
||||||
|
- Updated to 1.17.
|
||||||
|
- Small improvements to the codebase thanks to Java 16.
|
||||||
|
- Fix controller bindings not being saved ([#31](https://github.com/LambdAurora/LambdaControls/issues/31), [#55](https://github.com/LambdAurora/LambdaControls/issues/55)).
|
||||||
|
- Dropped entirely Touchscreen Input Mode.
|
||||||
|
- Dropped Roughly Enough Items compatibility.
|
||||||
|
|
||||||
|
### 1.7.1
|
||||||
|
|
||||||
|
- Fix crash at startup.
|
||||||
|
|
||||||
|
[SpruceUI]: https://github.com/LambdAurora/SpruceUI
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# Contributing to LambdaControls
|
# Contributing to midnightcontrols
|
||||||
|
|
||||||
:tada: First of all, thanks for taking time to contribute! :tada:
|
:tada: First of all, thanks for taking time to contribute! :tada:
|
||||||
|
|
||||||
The following is a set of guidelines for contributing to LambdaControls.
|
The following is a set of guidelines for contributing to MidnightControls.
|
||||||
Feel free to propose changes to this document in a pull request.
|
Feel free to propose changes to this document in a pull request.
|
||||||
|
|
||||||
**Table of Contents**
|
**Table of Contents**
|
||||||
@@ -17,8 +17,8 @@ Feel free to propose changes to this document in a pull request.
|
|||||||
|
|
||||||
## Code of Conduct
|
## Code of Conduct
|
||||||
|
|
||||||
This project and everyone participating in it is governed by the [Code of Conduct](https://github.com/LambdAurora/LambdaControls/blob/master/CODE_OF_CONDUCT.md).
|
This project and everyone participating in it is governed by the [Code of Conduct](https://github.com/LambdAurora/midnightcontrols/blob/master/CODE_OF_CONDUCT.md).
|
||||||
By participating, you are expected to uphold this code. Please report unacceptable behavior at [aurora42lambda@gmail.com](mailto:aurora42lambda@gmail.com).
|
By participating, you are expected to uphold this code. Please report unacceptable behavior at [motschen@midnightdust.eu](mailto:motschen@midnightdust.eu).
|
||||||
|
|
||||||
## What should I know before I get started?
|
## What should I know before I get started?
|
||||||
|
|
||||||
@@ -26,9 +26,9 @@ By participating, you are expected to uphold this code. Please report unacceptab
|
|||||||
|
|
||||||
[Fabric](https://fabricmc.net/) is the mod loader and the software which allows Gradle to setup the workspace.
|
[Fabric](https://fabricmc.net/) is the mod loader and the software which allows Gradle to setup the workspace.
|
||||||
|
|
||||||
### Java 8
|
### Java 17
|
||||||
|
|
||||||
Java is the main language used to make LambdaControls alive.
|
Java is the main language used to make MidnightControls alive.
|
||||||
Knowing how to code in Java is necessary if you contribute to the code.
|
Knowing how to code in Java is necessary if you contribute to the code.
|
||||||
|
|
||||||
### Minecraft
|
### Minecraft
|
||||||
@@ -45,9 +45,9 @@ As it is a Minecraft mod you should know a bit how Minecraft works and how moddi
|
|||||||
|
|
||||||
### Git
|
### Git
|
||||||
|
|
||||||
Git is the control version software we use for LambdaControls, please know how to use it if you consider contributing to the code.
|
Git is the control version software we use for midnightcontrols, please know how to use it if you consider contributing to the code.
|
||||||
|
|
||||||
Git commits should be and must be signed.
|
Git commits should be signed.
|
||||||
|
|
||||||
## How can I contribute?
|
## How can I contribute?
|
||||||
|
|
||||||
@@ -55,21 +55,21 @@ Git commits should be and must be signed.
|
|||||||
|
|
||||||
#### Before submitting a bug report
|
#### Before submitting a bug report
|
||||||
|
|
||||||
- Check if you can reproduce it on other platforms, on multiple web browsers.
|
- Check if you can reproduce it on other platforms.
|
||||||
- Perform a search to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one.
|
- Perform a search to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one.
|
||||||
|
|
||||||
#### How do I submit a bug report?
|
#### How do I submit a bug report?
|
||||||
|
|
||||||
Go in the issues tab in GitHub and read the [bug report guide](https://github.com/LambdAurora/LambdaControls/blob/master/.github/ISSUE_TEMPLATE/bug_report.md)
|
Go in the issues tab in GitHub and read the [bug report guide](https://github.com/TeamMidnightDust/MidnightControls/blob/1.18/.github/ISSUE_TEMPLATE/bug_report.md)
|
||||||
|
|
||||||
### Suggesting enhancements
|
### Suggesting enhancements
|
||||||
|
|
||||||
Enhancement suggestions are tracked as [GitHub issues](https://github.com/LambdAurora/LambdaControls/issues).
|
Enhancement suggestions are tracked as [GitHub issues](https://github.com/TeamMidnightDust/MidnightControls/issues).
|
||||||
Check out the [feature request](https://github.com/LambdAurora/LambdaControls/blob/master/.github/ISSUE_TEMPLATE/feature_request.md) guide.
|
Check out the [feature request](https://github.com/TeamMidnightDust/MidnightControls/blob/1.17/.github/ISSUE_TEMPLATE/feature_request.md) guide.
|
||||||
|
|
||||||
### Do pull requests
|
### Do pull requests
|
||||||
|
|
||||||
You can help LambdaControls by writing code and submit it with pull requests.
|
You can help midnightcontrols by writing code and submit it with pull requests.
|
||||||
|
|
||||||
Pull requests will be accepted if they follow the [styleguide](#styleguides), if they are useful, etc...
|
Pull requests will be accepted if they follow the [styleguide](#styleguides), if they are useful, etc...
|
||||||
We can refuse a pull request if the commits are not signed, so don't forget to [sign them](https://help.github.com/en/articles/signing-commits)!
|
We can refuse a pull request if the commits are not signed, so don't forget to [sign them](https://help.github.com/en/articles/signing-commits)!
|
||||||
@@ -81,21 +81,16 @@ Feel free to pull request!
|
|||||||
### Git commit messages
|
### Git commit messages
|
||||||
|
|
||||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||||
* Consider starting the commit message with an emote, emotes for your commit can be found at the [gitmoji guide](https://gitmoji.carloscuesta.me/).
|
|
||||||
* (Not for the message) Don't forget to sign the commit.
|
* (Not for the message) Don't forget to sign the commit.
|
||||||
|
|
||||||
### Naming convention
|
### Naming convention
|
||||||
|
|
||||||
Names in the code should be explicit and always in `snake_case`, `camelCase` will not be allowed.
|
Names in the code should be explicit and always in `camelCase`, `snake_case` will not be allowed.
|
||||||
`PascalCase` can be used for class name.
|
`PascalCase` can be used for class name.
|
||||||
|
|
||||||
We chose `snake_case` because it is more accessible for everyone: for people who don't speak English as their native language it is more easy to see the words when they are separated,
|
|
||||||
it also allows the correct use of screen reader on the code with `snake_case` due to the absence of upper case characters.
|
|
||||||
|
|
||||||
### Brace placement
|
### Brace placement
|
||||||
|
|
||||||
Every braces should be at the end of the line of function declaration, etc...
|
Every braces should be at the end of the line of function declaration, etc.
|
||||||
The only exception is class declarations: braces must be on the next line.
|
|
||||||
|
|
||||||
### Quick note for users of the Intellij IDEA IDE
|
### Quick note for users of the Intellij IDEA IDE
|
||||||
|
|
||||||
|
|||||||
5
HEADER
@@ -1,6 +1,7 @@
|
|||||||
Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
Copyright © 2022 Motschen <motschen@midnightdust.eu>
|
||||||
|
|
||||||
This file is part of LambdaControls.
|
This file is part of MidnightControls.
|
||||||
|
|
||||||
Licensed under the MIT license. For more information,
|
Licensed under the MIT license. For more information,
|
||||||
see the LICENSE file.
|
see the LICENSE file.
|
||||||
|
|||||||
3
LICENSE
@@ -1,6 +1,7 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
Copyright © 2022 Motschen <motschen@midnightdust.eu>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -18,4 +19,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|||||||
64
README.md
@@ -1,26 +1,29 @@
|
|||||||
# LambdaControls
|
<div align="center">
|
||||||
|
<img src=https://github.com/TeamMidnightDust/MidnightControls/blob/1.19/src/main/resources/assets/midnightcontrols/icon.png>
|
||||||
|
|
||||||

|
# MidnightControls
|
||||||
[](https://raw.githubusercontent.com/LambdAurora/LambdaControls/master/LICENSE)
|
|
||||||

|
|
||||||
[![Mod loader: Fabric]][fabric]
|
|
||||||

|
|
||||||
[](https://www.curseforge.com/minecraft/mc-mods/lambdacontrols)
|
|
||||||
|
|
||||||
A Fabric Minecraft mod which adds better controls, reach-around and controller support.
|
[](https://www.curseforge.com/minecraft/mc-mods/midnightcontrols)
|
||||||
|
[![Modrinth]](https://modrinth.com/mod/midnightcontrols)
|
||||||
|
[](https://github.com/TeamMidnightDust/MidnightControls/releases)
|
||||||
|

|
||||||
|
[![Mod loader: Quilt/Fabric]][Quilt]
|
||||||
|
[](https://www.oracle.com/java/technologies/downloads/#java17)
|
||||||
|
[](LICENSE)
|
||||||
|
|
||||||
|
A Fabric Minecraft mod which adds better controls, reach-around and controller support.
|
||||||
|
Forked from [LambdaControls](https://github.com/LambdAurora/LambdaControls) by the amazing [LambdAurora](https://github.com/LambdAurora), which was sadly discontinued.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
## What's this mod?
|
## What's this mod?
|
||||||
|
|
||||||
This mod adds better controls, reach-around features, etc.
|
MidnightControls is a mod which provides controller and touchscreen support in Minecraft: Java Edition.<br />It also includes some Bedrock Edition parity and reach-around features!
|
||||||
|
|
||||||
Haven't you dreamed to travel in your modded Minecraft world with your controller? Yes? Then this mod is made for you!
|
## Features:
|
||||||
|
|
||||||
This mod also adds controller support.
|
|
||||||
|
|
||||||
## ✅ Features:
|
|
||||||
|
|
||||||
- Controller support
|
- Controller support
|
||||||
- Touchscreen support (very experimental and buggy).
|
- Touchscreen support
|
||||||
- Keyboard controls to look around.
|
- Keyboard controls to look around.
|
||||||
- Toggleable on screen button indicator (like in Bedrock Edition).
|
- Toggleable on screen button indicator (like in Bedrock Edition).
|
||||||
- Vertical reach-around.
|
- Vertical reach-around.
|
||||||
@@ -29,27 +32,38 @@ This mod also adds controller support.
|
|||||||
- Front block placing (be careful with this one)
|
- Front block placing (be careful with this one)
|
||||||
- New controls settings!
|
- New controls settings!
|
||||||
- Many options in config to change to your liking.
|
- Many options in config to change to your liking.
|
||||||
- Many controllers supported and in a simply way your own controller mappings.
|
- Many controllers supported and in a simple way your own controller mappings.
|
||||||
- An easy API for developers to add their own button bindings.
|
- An easy API for developers to add their own button bindings.
|
||||||
|
|
||||||
## 🎮 Supported Controllers:
|
## 🎮 Supported Controllers:
|
||||||
|
|
||||||
- Dualshock controllers
|
- DualShock controllers
|
||||||
|
- DualSense controllers
|
||||||
- Xbox controllers
|
- Xbox controllers
|
||||||
- Switch Pro controllers
|
- Switch Pro controllers
|
||||||
- Joycons
|
- Joy-Cons
|
||||||
|
- Steam controller and Steam Deck (WIP)
|
||||||
- And many more!
|
- And many more!
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
![controller_controls]
|

|
||||||
![controller_options]
|

|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
Just do `./gradlew shadowRemapJar` and everything should build just fine!
|
Clone the repo with:
|
||||||
|
```
|
||||||
|
git clone https://github.com/TeamMidnightDust/MidnightControls
|
||||||
|
```
|
||||||
|
Enter the folder created and run:
|
||||||
|
```
|
||||||
|
./gradlew build
|
||||||
|
```
|
||||||
|
After this is done, everything should be built just fine!
|
||||||
|
|
||||||
[controller_controls]: images/controller_controls.png
|
[Quilt]: https://quiltmc.org
|
||||||
[controller_options]: images/controller_options.png
|
|
||||||
[fabric]: https://fabricmc.net
|
[Mod loader: Quilt/Fabric]: https://img.shields.io/badge/modloader-Quilt%2FFabric-blueviolet?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAADGAAAAxgGwdJvFAAAFU0lEQVR4nO1bwW7bOBCdCHtP+wUNxIvhS7yA7kkPOjf9AKPam4/OF2zzB96bblXhH0jPPkS5G1jnIvgib/IFtX/ALoYZemmKtEWRRe3aDzAsURbJGQ6HM4/02Wq1gmNGcNTSnxQA8IdakDK4AOCfJpj3SpiI98r2rAMAbxrWNWFFOMeL1nCJdXQa1gPTbpCbnm34ABIeBThv2hgAfOyVcF+2ZwkAfHGo54kVIRe6NVxiny4d6vpn2g36ugfqFLhwFB6kkUoc67k0XLv0qYKj9wEnBXiqZwEAf/ZKOOuV8BkLWBFesyI8A4C/LOt6AoC39C7HtBvg9Vt65hUnC/BUDzrOf1MGq5S9WkDZnuVle7ZqsBKgw/tO73K0hku8/u64EmhxsoA96MMvxdEroBIKO+CWoshnqqJPYTAGRJ8sql3QO3Op7D19D3z7AV8KeAGArFf+32lWhDwnKNuzuaUCclaE93KBiOU9hMQV+FLAOxz9lPHRR0VkZXs2oBDUNon5ULZnKOgcYwl4FTwna/K+CtRRwIK+dTnCCwkP9I0fkXmh4FcN+6UKqqtHblvtb+18po4TvKaPilsS8qVuYx5havsbJXS1I0ZVAXP1B5jfyzm+hAnN+We1XPluioX03kJtY9oNtG1T+b1aburDxhRAQVMGHw3z9k65F41nktmjUnjjrAj7ZXv27ECIyEKgBd7saBuka7lsPu0GA1MjR0+KVpwgMTlrMkN4YoztlZ/2camTvD0QjcWZF6KxMgcLyKbdAN+HKOb1y6PYH49gEsUwUKw1G48gi2KQZcApkYxH1eldUQBxeKbkRfXEQjDZ21+h2bMiHJDwH2wk1rSX0XWueHZd2yCZ/oVSnilTaA3VAiqjRRahQ0JBjuov3ijfPqAua0kUg67tmyjWCmvsS504wGQRnywjPJ8wtY3xw3827fjMBXziUalL3DcNrIzYRwXcTbvBZ7lgPHoNxKKYky1/+2xsHxXQbw2X/EIoggQHyjC9Yh8VcC6NshDc66jLOHpC5KSAPejDL8U+KuArboTQZgjHeARn+MFnvhvbRyfYaQ2XfNkTVFgUr/mIxlvkJuyjAjCae6BrYQUPW37vhDpT4MnAsCyIgbHBnYbcADJt7/t+deBCiSWsCG8sOv5IgU2FnJh2g+RnBDl1oCpgogqEx1TEURUFokx+tpCYnEzzjg1kh+fq/Ix9OXpG6OjjgI1VIGWcOMhlXh4PPdAz1VTe90rIU8Z/L9JUnALXSK4SjSUzOY+Y1ekyOlzjaamTvf3X8cjunBH1v6OeVtsG1QI66qYEVkoVmyA/O5fYmIHjgSsrskUavAc6q1BLeXXiANMZu0HKwGav7opGv+LticZqHOToLBeZrJRxC97qjOsowCTgZYO9OlNa25haMwgvsFMJPp3gLW1ji8b6dO89fhfYIbzAl23T4adtjyNvD6/mbbs9Xgs1hRcwWoIvCxDb47nQNm5aRDHvoPGcblNYCi+gtQSfU+AdLYfioLXYtHA9eruBhsILVJRwUIGQo/ACG0o4GAV4El5grQSffMA3SqbEnBdb1zeunfYsvAB3jL4UwE92KauA2NnNbLerNKhEqJ6Q+FIAOjpcATAVzjFHoC3qC9OurCW0W9s+6vXpAy4p0hPkSUL3ziNHiY3tqfNdQN4jORgnSEGMLyU8Udbq1QIEdEyRF3hSwlp4vKkwQimrHDuxAR6S4tleFIPzERnhSFXQEtbkD1kbwiMOlhJroISK8IiDpcQsp4NWeMRBc4I1lWAUHnHwpOgOJWwVHvFbsMIGJewUHvFb7QuQYxR/ttgIzbUAgB9KOM3uc+PN7QAAAABJRU5ErkJggg==
|
||||||
[Mod loader: Fabric]: https://img.shields.io/badge/modloader-Fabric-1976d2?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE4LTEyLTE2VDE2OjU0OjE3LTA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wNy0yOFQyMToxNzo0OC0wNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wNy0yOFQyMToxNzo0OC0wNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowZWRiMWMyYy1mZjhjLWU0NDEtOTMxZi00OTVkNGYxNGM3NjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MGVkYjFjMmMtZmY4Yy1lNDQxLTkzMWYtNDk1ZDRmMTRjNzYwIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MGVkYjFjMmMtZmY4Yy1lNDQxLTkzMWYtNDk1ZDRmMTRjNzYwIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDowZWRiMWMyYy1mZjhjLWU0NDEtOTMxZi00OTVkNGYxNGM3NjAiIHN0RXZ0OndoZW49IjIwMTgtMTItMTZUMTY6NTQ6MTctMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4/HiGMAAAAtUlEQVRYw+XXrQqAMBQF4D2P2eBL+QIG8RnEJFaNBjEum+0+zMQLtwwv+wV3ZzhhMDgfJ0wUSinxZUQWgKos1JP/AbD4OneIDyQPwCFniA+EJ4CaXm4TxAXCC0BNHgLhAdAnx9hC8PwGSRtAFVMQjF7cNTWED8B1cgwW20yfJgAvrssAsZ1cB3g/xckAxr6FmCDU5N6f488BrpCQ4rQBJkiMYh4ACmLzwOQF0CExinkCsvw7vgGikl+OotaKRwAAAABJRU5ErkJggg==
|
|
||||||
|
[Modrinth]: https://img.shields.io/modrinth/dt/bXX9h73M?logoColor=white&logo=data:image/svg%2bxml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNTEyIDUxNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTUwMy4xNiAzMjMuNTZDNTE0LjU1IDI4MS40NyA1MTUuMzIgMjM1LjkxIDUwMy4yIDE5MC43NkM0NjYuNTcgNTQuMjI5OSAzMjYuMDQgLTI2LjgwMDEgMTg5LjMzIDkuNzc5OTFDODMuODEwMSAzOC4wMTk5IDExLjM4OTkgMTI4LjA3IDAuNjg5OTQxIDIzMC40N0g0My45OUM1NC4yOSAxNDcuMzMgMTEzLjc0IDc0LjcyOTggMTk5Ljc1IDUxLjcwOThDMzA2LjA1IDIzLjI1OTggNDE1LjEzIDgwLjY2OTkgNDUzLjE3IDE4MS4zOEw0MTEuMDMgMTkyLjY1QzM5MS42NCAxNDUuOCAzNTIuNTcgMTExLjQ1IDMwNi4zIDk2LjgxOThMMjk4LjU2IDE0MC42NkMzMzUuMDkgMTU0LjEzIDM2NC43MiAxODQuNSAzNzUuNTYgMjI0LjkxQzM5MS4zNiAyODMuOCAzNjEuOTQgMzQ0LjE0IDMwOC41NiAzNjkuMTdMMzIwLjA5IDQxMi4xNkMzOTAuMjUgMzgzLjIxIDQzMi40IDMxMC4zIDQyMi40MyAyMzUuMTRMNDY0LjQxIDIyMy45MUM0NjguOTEgMjUyLjYyIDQ2Ny4zNSAyODEuMTYgNDYwLjU1IDMwOC4wN0w1MDMuMTYgMzIzLjU2WiIgZmlsbD0iIzMwYjI3YiIvPgogIDxwYXRoIGQ9Ik0zMjEuOTkgNTA0LjIyQzE4NS4yNyA1NDAuOCA0NC43NTAxIDQ1OS43NyA4LjExMDExIDMyMy4yNEMzLjg0MDExIDMwNy4zMSAxLjE3IDI5MS4zMyAwIDI3NS40Nkg0My4yN0M0NC4zNiAyODcuMzcgNDYuNDY5OSAyOTkuMzUgNDkuNjc5OSAzMTEuMjlDNTMuMDM5OSAzMjMuOCA1Ny40NSAzMzUuNzUgNjIuNzkgMzQ3LjA3TDEwMS4zOCAzMjMuOTJDOTguMTI5OSAzMTYuNDIgOTUuMzkgMzA4LjYgOTMuMjEgMzAwLjQ3QzY5LjE3IDIxMC44NyAxMjIuNDEgMTE4Ljc3IDIxMi4xMyA5NC43NjAxQzIyOS4xMyA5MC4yMTAxIDI0Ni4yMyA4OC40NDAxIDI2Mi45MyA4OS4xNTAxTDI1NS4xOSAxMzNDMjQ0LjczIDEzMy4wNSAyMzQuMTEgMTM0LjQyIDIyMy41MyAxMzcuMjVDMTU3LjMxIDE1NC45OCAxMTguMDEgMjIyLjk1IDEzNS43NSAyODkuMDlDMTM2Ljg1IDI5My4xNiAxMzguMTMgMjk3LjEzIDEzOS41OSAzMDAuOTlMMTg4Ljk0IDI3MS4zOEwxNzQuMDcgMjMxLjk1TDIyMC42NyAxODQuMDhMMjc5LjU3IDE3MS4zOUwyOTYuNjIgMTkyLjM4TDI2OS40NyAyMTkuODhMMjQ1Ljc5IDIyNy4zM0wyMjguODcgMjQ0LjcyTDIzNy4xNiAyNjcuNzlDMjM3LjE2IDI2Ny43OSAyNTMuOTUgMjg1LjYzIDI1My45OCAyODUuNjRMMjc3LjcgMjc5LjMzTDI5NC41OCAyNjAuNzlMMzMxLjQ0IDI0OS4xMkwzNDIuNDIgMjczLjgyTDMwNC4zOSAzMjAuNDVMMjQwLjY2IDM0MC42M0wyMTIuMDggMzA4LjgxTDE2Mi4yNiAzMzguN0MxODcuOCAzNjcuNzggMjI2LjIgMzgzLjkzIDI2Ni4wMSAzODAuNTZMMjc3LjU0IDQyMy41NUMyMTguMTMgNDMxLjQxIDE2MC4xIDQwNi44MiAxMjQuMDUgMzYxLjY0TDg1LjYzOTkgMzg0LjY4QzEzNi4yNSA0NTEuMTcgMjIzLjg0IDQ4NC4xMSAzMDkuNjEgNDYxLjE2QzM3MS4zNSA0NDQuNjQgNDE5LjQgNDAyLjU2IDQ0NS40MiAzNDkuMzhMNDg4LjA2IDM2NC44OEM0NTcuMTcgNDMxLjE2IDM5OC4yMiA0ODMuODIgMzIxLjk5IDUwNC4yMloiIGZpbGw9IiMzMGIyN2IiLz4KPC9zdmc+
|
||||||
|
|||||||
283
build.gradle
@@ -1,59 +1,82 @@
|
|||||||
buildscript {
|
|
||||||
dependencies {
|
|
||||||
constraints {
|
|
||||||
["asm", "asm-util", "asm-tree", "asm-analysis"].each {
|
|
||||||
classpath("org.ow2.asm:$it") {
|
|
||||||
version { require("9.1") }
|
|
||||||
because("Fabric's TinyRemapper requires ASM 9")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '0.6-SNAPSHOT'
|
id 'fabric-loom' version '0.11-SNAPSHOT'
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id 'com.github.johnrengelman.shadow' version '6.1.0'
|
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
||||||
id 'org.cadixdev.licenser' version '0.5.0'
|
id 'com.modrinth.minotaur' version '1.2.+'
|
||||||
}
|
}
|
||||||
|
|
||||||
import net.fabricmc.loom.task.RemapJarTask
|
import com.google.gson.GsonBuilder
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.modrinth.minotaur.TaskModrinthUpload
|
||||||
|
import com.modrinth.minotaur.request.VersionType
|
||||||
|
import com.modrinth.minotaur.responses.ResponseError
|
||||||
|
import org.apache.http.client.config.CookieSpecs
|
||||||
|
import org.apache.http.client.config.RequestConfig
|
||||||
|
import org.apache.http.client.entity.EntityBuilder
|
||||||
|
import org.apache.http.client.methods.HttpPatch
|
||||||
|
import org.apache.http.entity.ContentType
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder
|
||||||
|
import org.apache.http.util.EntityUtils
|
||||||
|
|
||||||
group = project.maven_group
|
group = project.maven_group
|
||||||
version = "${project.mod_version}+${getMCVersionString()}"
|
version = "${project.mod_version}+${getMCVersionString()}"
|
||||||
archivesBaseName = project.archives_base_name + "-fabric"
|
archivesBaseName = project.archives_base_name
|
||||||
|
|
||||||
// This field defines the Java version your mod target.
|
// This field defines the Java version your mod target.
|
||||||
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too.
|
def targetJavaVersion = 17
|
||||||
def targetJavaVersion = 8
|
|
||||||
|
|
||||||
def getMCVersionString() {
|
boolean isMCVersionNonRelease() {
|
||||||
if (project.minecraft_version.matches("\\d\\dw\\d\\d[a-z]")) {
|
return project.minecraft_version.matches('^\\d\\dw\\d\\d[a-z]$')
|
||||||
|
|| project.minecraft_version.matches('\\d+\\.\\d+-(pre|rc)(\\d+)')
|
||||||
|
}
|
||||||
|
|
||||||
|
String getMCVersionString() {
|
||||||
|
if (isMCVersionNonRelease()) {
|
||||||
return project.minecraft_version
|
return project.minecraft_version
|
||||||
}
|
}
|
||||||
int lastDot = project.minecraft_version.lastIndexOf('.')
|
def version = project.minecraft_version.split('\\.')
|
||||||
return project.minecraft_version.substring(0, lastDot)
|
return version[0] + '.' + version[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
minecraft {
|
boolean pingUrl(String address) {
|
||||||
|
try {
|
||||||
|
def conn = (HttpURLConnection) new URL(address).openConnection()
|
||||||
|
int responseCode = conn.getResponseCode()
|
||||||
|
return (200 <= responseCode && responseCode <= 399)
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String parseReadme() {
|
||||||
|
def excludeRegex = /(?m)<!-- modrinth_exclude\.start -->(.|\n)*?<!-- modrinth_exclude\.end -->/
|
||||||
|
def linkRegex = /!\[([A-z_ ]+)]\((images\/[A-z.\/_]+)\)/
|
||||||
|
|
||||||
|
def readme = (String) file('README.md').text
|
||||||
|
readme = readme.replaceAll(excludeRegex, '')
|
||||||
|
return readme
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url = 'https://aperlambda.github.io/maven' }
|
maven { url 'https://aperlambda.github.io/maven' }
|
||||||
maven {
|
maven {
|
||||||
name = 'CottonMC'
|
name 'Gegy'
|
||||||
url = 'http://server.bbkr.space:8081/artifactory/libs-snapshot'
|
url 'https://maven.gegy.dev'
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
name = 'Terraformers'
|
name = "CottonMC"
|
||||||
url = 'https://maven.terraformersmc.com/releases'
|
url = "https://server.bbkr.space/artifactory/libs-release"
|
||||||
}
|
}
|
||||||
maven { url "https://maven.shedaniel.me/" }
|
maven { url "https://maven.terraformersmc.com/releases/" }
|
||||||
maven { url = "https://jitpack.io" }
|
maven { url 'https://maven.kosmx.dev' }
|
||||||
|
maven { url 'https://maven.shedaniel.me/' }
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
maven { url "https://api.modrinth.com/maven" }
|
||||||
|
maven { url 'https://maven.quiltmc.org/repository/release'}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
@@ -70,20 +93,38 @@ dependencies {
|
|||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||||
|
|
||||||
|
modImplementation "dev.lambdaurora:spruceui:${project.spruceui_version}"
|
||||||
|
include "dev.lambdaurora:spruceui:${project.spruceui_version}"
|
||||||
|
api('org.aperlambda:lambdajcommon:1.8.1') {
|
||||||
|
exclude group: 'com.google.code.gson'
|
||||||
|
exclude group: 'com.google.guava'
|
||||||
|
}
|
||||||
|
include 'org.aperlambda:lambdajcommon:1.8.1'
|
||||||
|
|
||||||
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
|
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
|
||||||
modImplementation "com.github.lambdaurora:spruceui:${project.spruceui_version}"
|
|
||||||
include "com.github.lambdaurora:spruceui:${project.spruceui_version}"
|
|
||||||
|
|
||||||
// Compatibility mods
|
// Compatibility mods
|
||||||
modImplementation("com.github.joaoh1:okzoomer:e13183c59b") {
|
|
||||||
exclude group: 'me.shedaniel.cloth'
|
|
||||||
exclude group: 'io.github.prospector'
|
|
||||||
}
|
|
||||||
|
|
||||||
modImplementation("me.shedaniel:RoughlyEnoughItems:5.10.184")
|
// Ok Zoomer and LibZoomer are temporarily disabled for the time being, as we are currently using Reflection at runtime instead in OkZoomerCompat due to there being two major, completely incompatible API versions.
|
||||||
|
// modImplementation("maven.modrinth:ok-zoomer:${project.ok_zoomer_version}")
|
||||||
|
// modImplementation "io.github.ennuil:LibZoomer:${project.libzoomer_version}"
|
||||||
|
|
||||||
shadow "com.electronwill.night-config:core:3.6.3"
|
modImplementation "io.github.cottonmc:LibGui:${project.libgui_version}"
|
||||||
shadow "com.electronwill.night-config:toml:3.6.3"
|
modImplementation "org.quiltmc:quilt-json5:1.0.0"
|
||||||
|
modCompileOnly "maven.modrinth:sodium:${project.sodium_version}"
|
||||||
|
modImplementation("maven.modrinth:emi:${project.emi_version}")
|
||||||
|
modImplementation "maven.modrinth:emotecraft:${project.emotecraft_version}"
|
||||||
|
modImplementation "io.github.kosmx:bendy-lib:${project.bendylib_version}"
|
||||||
|
|
||||||
|
modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}"
|
||||||
|
include "maven.modrinth:midnightlib:${project.midnightlib_version}"
|
||||||
|
|
||||||
|
shadow 'com.electronwill.night-config:core:3.6.3'
|
||||||
|
shadow 'com.electronwill.night-config:toml:3.6.3'
|
||||||
|
apply plugin: 'java-library'
|
||||||
|
}
|
||||||
|
loom {
|
||||||
|
accessWidenerPath = file("src/main/resources/midnightcontrols.accesswidener")
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@@ -94,76 +135,126 @@ java {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
it.options.encoding = "UTF-8"
|
it.options.encoding = 'UTF-8'
|
||||||
|
|
||||||
if (JavaVersion.current().isJava9Compatible()) {
|
it.options.release.set(targetJavaVersion)
|
||||||
if (JavaVersion.current().isJava9Compatible()) {
|
}
|
||||||
it.options.release = targetJavaVersion
|
|
||||||
|
processResources {
|
||||||
|
inputs.property 'version', project.version
|
||||||
|
|
||||||
|
filesMatching('fabric.mod.json') {
|
||||||
|
expand 'version': project.version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task publishModrinth(type: TaskModrinthUpload) {
|
||||||
|
dependsOn(build)
|
||||||
|
onlyIf {
|
||||||
|
System.getenv('MODRINTH_TOKEN')
|
||||||
|
}
|
||||||
|
|
||||||
|
token = System.getenv('MODRINTH_TOKEN')
|
||||||
|
projectId = project.modrinth_id
|
||||||
|
versionNumber = version
|
||||||
|
versionName = "midnightcontrols ${project.mod_version} (${getMCVersionString()})"
|
||||||
|
addGameVersion((String) project.minecraft_version)
|
||||||
|
addLoader('fabric')
|
||||||
|
versionType = isMCVersionNonRelease() ? VersionType.BETA : VersionType.RELEASE
|
||||||
|
|
||||||
|
// Changelog fetching
|
||||||
|
def changelogText = file('CHANGELOG.md').text
|
||||||
|
def regexVersion = ((String) project.mod_version).replaceAll('\\.', /\\./).replaceAll('\\+', '\\+')
|
||||||
|
def changelogRegex = ~"###? ${regexVersion}\\n\\n(( *- .+\\n)+)"
|
||||||
|
def matcher = changelogText =~ changelogRegex
|
||||||
|
|
||||||
|
if (matcher.find()) {
|
||||||
|
changelog = matcher.group(1)
|
||||||
|
|
||||||
|
def changelogLines = changelogText.split('\n')
|
||||||
|
def linkRefRegex = ~'^\\[([A-z0-9 _\\-/+.]+)]: '
|
||||||
|
for (int i = changelogLines.length - 1; i > 0; i--) {
|
||||||
|
def line = changelogLines[i]
|
||||||
|
if ((line =~ linkRefRegex).find())
|
||||||
|
changelog += '\n' + line
|
||||||
|
else break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Readme
|
||||||
|
doFirst {
|
||||||
|
final def client = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
|
||||||
|
final def patch = new HttpPatch((String) (apiURL + '/v1/mod/' + projectId))
|
||||||
|
patch.addHeader("Authorization", token)
|
||||||
|
|
||||||
|
var json = new JsonObject()
|
||||||
|
json.addProperty("body", parseReadme())
|
||||||
|
patch.setEntity(EntityBuilder.create()
|
||||||
|
.setText(json.toString())
|
||||||
|
.setContentType(ContentType.APPLICATION_JSON)
|
||||||
|
.build())
|
||||||
|
|
||||||
|
final def response = client.execute(patch)
|
||||||
|
final int status = response.getStatusLine().getStatusCode()
|
||||||
|
|
||||||
|
final def gson = new GsonBuilder().create()
|
||||||
|
if (status == 200) {
|
||||||
|
project.getLogger().lifecycle("Successfully updated readme to ${projectId}.")
|
||||||
|
} else {
|
||||||
|
errorInfo = gson.fromJson(EntityUtils.toString(response.getEntity()), ResponseError.class)
|
||||||
|
project.getLogger().error("Upload failed! Status: ${status} Error: ${errorInfo.getError()} Reason: ${errorInfo.getDescription()}")
|
||||||
|
throw new GradleException("Upload failed! Status: ${status} Reason: ${errorInfo.getDescription()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
|
||||||
inputs.property "version", project.version
|
|
||||||
|
|
||||||
filesMatching("fabric.mod.json") {
|
|
||||||
expand "version": project.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
from("LICENSE") {
|
|
||||||
rename { "${it}_${project.archivesBaseName}" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
license {
|
|
||||||
header file('HEADER')
|
|
||||||
include '**/*.java'
|
|
||||||
}
|
|
||||||
|
|
||||||
shadowJar {
|
|
||||||
dependsOn jar
|
|
||||||
configurations = [project.configurations.shadow]
|
|
||||||
archiveClassifier.set('dev')
|
|
||||||
|
|
||||||
exclude 'META-INF/maven/**'
|
|
||||||
exclude 'com/google/**'
|
|
||||||
exclude 'javax/**'
|
|
||||||
exclude 'org/**'
|
|
||||||
relocate 'com.electronwill.nightconfig', 'dev.lambdaurora.lambdacontrols.shadow.nightconfig'
|
|
||||||
}
|
|
||||||
|
|
||||||
task shadowRemapJar(type: RemapJarTask) {
|
|
||||||
dependsOn shadowJar
|
|
||||||
|
|
||||||
input = file("${project.buildDir}/libs/$archivesBaseName-$version-dev.jar")
|
|
||||||
archiveName = "${archivesBaseName}-${version}.jar"
|
|
||||||
addNestedDependencies = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure the maven publication
|
// configure the maven publication
|
||||||
publishing {
|
publishing {
|
||||||
|
publications {
|
||||||
|
mavenJava(MavenPublication) {
|
||||||
|
artifact(sourcesJar) {
|
||||||
|
builtBy remapSourcesJar
|
||||||
|
}
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name = 'midnightcontrols'
|
||||||
|
description = 'Adds better controls, and controller support.'
|
||||||
|
}
|
||||||
|
|
||||||
|
pom.withXml {
|
||||||
|
def dependenciesNode = asNode().appendNode('dependencies')
|
||||||
|
|
||||||
|
configurations.shadow.allDependencies.each {
|
||||||
|
def dependencyNode = dependenciesNode.appendNode('dependency')
|
||||||
|
|
||||||
|
dependencyNode.appendNode('groupId', it.group)
|
||||||
|
dependencyNode.appendNode('artifactId', it.name)
|
||||||
|
dependencyNode.appendNode('version', it.version)
|
||||||
|
dependencyNode.appendNode('scope', 'compile')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
maven {
|
maven {
|
||||||
name = "GithubPackages"
|
name 'GithubPackages'
|
||||||
url = uri("https://maven.pkg.github.com/LambdAurora/LambdaControls")
|
url uri('https://maven.pkg.github.com/LambdAurora/midnightcontrols')
|
||||||
credentials {
|
credentials {
|
||||||
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
|
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
|
||||||
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
|
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
def midnightcontrolsMaven = System.getenv('midnightcontrols_MAVEN')
|
||||||
|
if (midnightcontrolsMaven) {
|
||||||
publications {
|
maven {
|
||||||
mavenJava(MavenPublication) {
|
name 'midnightcontrolsMaven'
|
||||||
// add all the jars that should be included when publishing to maven
|
url uri(midnightcontrolsMaven)
|
||||||
artifact(remapJar) {
|
credentials {
|
||||||
builtBy remapJar
|
username = project.findProperty('gpr.user') ?: System.getenv('MAVEN_USERNAME')
|
||||||
}
|
password = project.findProperty('gpr.key') ?: System.getenv('MAVEN_PASSWORD')
|
||||||
artifact(sourcesJar) {
|
}
|
||||||
builtBy remapSourcesJar
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
303
controller.svg
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="1024.0px"
|
||||||
|
height="1024.0px"
|
||||||
|
viewBox="0 0 1024.0 1024.0"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
sodipodi:docname="controller.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview893"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="0.42961102"
|
||||||
|
inkscape:cx="455.06282"
|
||||||
|
inkscape:cy="790.24975"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1050"
|
||||||
|
inkscape:window-x="1920"
|
||||||
|
inkscape:window-y="30"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid956" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs888">
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient1152">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ed02a0;stop-opacity:1"
|
||||||
|
offset="0"
|
||||||
|
id="stop1148" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8900cb;stop-opacity:1"
|
||||||
|
offset="1"
|
||||||
|
id="stop1150" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient1154"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1020"
|
||||||
|
y2="1020"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient4289"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1020"
|
||||||
|
y2="1020"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient4663"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1020"
|
||||||
|
y2="1020"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient5165"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1020"
|
||||||
|
y2="1020"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient5507"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1020"
|
||||||
|
y2="1020" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient5817"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1020"
|
||||||
|
y2="1020"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient6161"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1020"
|
||||||
|
y2="1020"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient6535"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1025"
|
||||||
|
y2="1025"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient7579"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1025"
|
||||||
|
y2="1025"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient8115"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1025"
|
||||||
|
y2="1025"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient1154);fill-opacity:1"
|
||||||
|
id="rect1033"
|
||||||
|
width="1025"
|
||||||
|
height="1025"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
rx="0"
|
||||||
|
ry="0" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect2078"
|
||||||
|
width="671.12531"
|
||||||
|
height="330.82504"
|
||||||
|
x="178.42294"
|
||||||
|
y="283.78436"
|
||||||
|
ry="110.27502" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41852"
|
||||||
|
id="rect2146"
|
||||||
|
width="199.30905"
|
||||||
|
height="504.61328"
|
||||||
|
x="518.59406"
|
||||||
|
y="450.07187"
|
||||||
|
ry="97.030388"
|
||||||
|
transform="matrix(0.97214881,-0.23436445,0.26615211,0.96393104,0,0)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41852"
|
||||||
|
id="rect2146-3"
|
||||||
|
width="200.94308"
|
||||||
|
height="502.92538"
|
||||||
|
x="271.98715"
|
||||||
|
y="209.38025"
|
||||||
|
ry="97.050156"
|
||||||
|
transform="matrix(0.97237519,0.23342343,-0.26569554,0.96405699,0,0)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect2384"
|
||||||
|
width="87.538078"
|
||||||
|
height="55.137505"
|
||||||
|
x="251.37137"
|
||||||
|
y="270"
|
||||||
|
ry="27.568752" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect2384-6"
|
||||||
|
width="87.538078"
|
||||||
|
height="55.137505"
|
||||||
|
x="691.97968"
|
||||||
|
y="270"
|
||||||
|
ry="27.568752" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient4663);fill-opacity:1"
|
||||||
|
id="path2566"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="302.43524"
|
||||||
|
sodipodi:cy="400.95157"
|
||||||
|
sodipodi:rx="51.063881"
|
||||||
|
sodipodi:ry="48.245316"
|
||||||
|
sodipodi:start="2.7492077"
|
||||||
|
sodipodi:end="2.731929"
|
||||||
|
sodipodi:open="true"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="m 255.25223,419.40025 a 51.063881,48.245316 0 0 1 27.4529,-62.94723 51.063881,48.245316 0 0 1 66.74267,25.66543 51.063881,48.245316 0 0 1 -26.87629,63.16896 51.063881,48.245316 0 0 1 -66.97486,-25.11969" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient5817);fill-opacity:1"
|
||||||
|
id="path2566-7"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="663.29633"
|
||||||
|
sodipodi:cy="527.23883"
|
||||||
|
sodipodi:rx="51.063881"
|
||||||
|
sodipodi:ry="48.245316"
|
||||||
|
sodipodi:start="2.7492077"
|
||||||
|
sodipodi:end="2.731929"
|
||||||
|
sodipodi:open="true"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="m 616.11332,545.68751 a 51.063881,48.245316 0 0 1 27.45289,-62.94723 51.063881,48.245316 0 0 1 66.74267,25.66543 51.063881,48.245316 0 0 1 -26.87628,63.16896 51.063881,48.245316 0 0 1 -66.97487,-25.11969" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient5165);fill-opacity:1"
|
||||||
|
id="path2710"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="740.12561"
|
||||||
|
sodipodi:cy="345.81409"
|
||||||
|
sodipodi:rx="21.88452"
|
||||||
|
sodipodi:ry="20.676565"
|
||||||
|
sodipodi:start="2.7492077"
|
||||||
|
sodipodi:end="2.731929"
|
||||||
|
sodipodi:open="true"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="m 719.90432,353.72066 a 21.88452,20.676565 0 0 1 11.76553,-26.97738 21.88452,20.676565 0 0 1 28.604,10.99947 21.88452,20.676565 0 0 1 -11.51841,27.07241 21.88452,20.676565 0 0 1 -28.70351,-10.76558" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient5507);fill-opacity:1"
|
||||||
|
id="path2710-5"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="785.35364"
|
||||||
|
sodipodi:cy="385.78876"
|
||||||
|
sodipodi:rx="21.88452"
|
||||||
|
sodipodi:ry="20.676565"
|
||||||
|
sodipodi:start="2.7492077"
|
||||||
|
sodipodi:end="2.731929"
|
||||||
|
sodipodi:open="true"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="m 765.13235,393.69534 a 21.88452,20.676565 0 0 1 11.76553,-26.97739 21.88452,20.676565 0 0 1 28.604,10.99947 21.88452,20.676565 0 0 1 -11.51841,27.07241 21.88452,20.676565 0 0 1 -28.70351,-10.76558" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient6535);fill-opacity:1"
|
||||||
|
id="path2710-3"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="697.81555"
|
||||||
|
sodipodi:cy="385.78876"
|
||||||
|
sodipodi:rx="21.88452"
|
||||||
|
sodipodi:ry="20.676565"
|
||||||
|
sodipodi:start="2.7492077"
|
||||||
|
sodipodi:end="2.731929"
|
||||||
|
sodipodi:open="true"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="m 677.59426,393.69534 a 21.88452,20.676565 0 0 1 11.76553,-26.97739 21.88452,20.676565 0 0 1 28.604,10.99947 21.88452,20.676565 0 0 1 -11.51841,27.07241 21.88452,20.676565 0 0 1 -28.70351,-10.76558" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient6161);fill-opacity:1"
|
||||||
|
id="path2710-56"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="741.58459"
|
||||||
|
sodipodi:cy="427.14188"
|
||||||
|
sodipodi:rx="21.88452"
|
||||||
|
sodipodi:ry="20.676565"
|
||||||
|
sodipodi:start="2.7492077"
|
||||||
|
sodipodi:end="2.731929"
|
||||||
|
sodipodi:open="true"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="m 721.36331,435.04845 a 21.88452,20.676565 0 0 1 11.76552,-26.97738 21.88452,20.676565 0 0 1 28.604,10.99947 21.88452,20.676565 0 0 1 -11.51841,27.07241 21.88452,20.676565 0 0 1 -28.70351,-10.76558" />
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient8115);fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect2896"
|
||||||
|
width="36.474197"
|
||||||
|
height="110.27502"
|
||||||
|
x="369.54779"
|
||||||
|
y="476.76566"
|
||||||
|
ry="13.784376" />
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient7579);fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect2898"
|
||||||
|
width="116.71745"
|
||||||
|
height="37.217815"
|
||||||
|
x="327.2377"
|
||||||
|
y="512.60504"
|
||||||
|
ry="13.383304" />
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient4289);fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect3104"
|
||||||
|
width="233.43489"
|
||||||
|
height="110.27502"
|
||||||
|
x="400.1861"
|
||||||
|
y="338.92191"
|
||||||
|
ry="13.383307" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 9.3 KiB |
269
controller_banner.svg
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="1920"
|
||||||
|
height="1080"
|
||||||
|
viewBox="0 0 1920 1080"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
sodipodi:docname="controller_banner.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
inkscape:export-filename="/home/martin/Bilder/Bilder/MidnightControlsBanner.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview893"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:pageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="0.40120419"
|
||||||
|
inkscape:cx="928.45492"
|
||||||
|
inkscape:cy="816.29258"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1050"
|
||||||
|
inkscape:window-x="1920"
|
||||||
|
inkscape:window-y="30"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid956" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs888">
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient2059">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ed02a0;stop-opacity:0.72909278"
|
||||||
|
offset="0"
|
||||||
|
id="stop2055" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8900cb;stop-opacity:0.73234183"
|
||||||
|
offset="1"
|
||||||
|
id="stop2057" />
|
||||||
|
</linearGradient>
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="powerclip"
|
||||||
|
id="path-effect904"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
inverse="true"
|
||||||
|
flatten="false"
|
||||||
|
hide_clip="false"
|
||||||
|
message="Füllregel Gerade-Ungerade im <b>Füllung und Kontur</b>-Dialog verwenden, wenn das Anwenden des Ausschnitts mit nachfolgendem Umwandeln in Pfade kein Ergebnis bringt" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="powerclip"
|
||||||
|
id="path-effect900"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
inverse="true"
|
||||||
|
flatten="false"
|
||||||
|
hide_clip="false"
|
||||||
|
message="Füllregel Gerade-Ungerade im <b>Füllung und Kontur</b>-Dialog verwenden, wenn das Anwenden des Ausschnitts mit nachfolgendem Umwandeln in Pfade kein Ergebnis bringt" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="powerclip"
|
||||||
|
id="path-effect896"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
inverse="true"
|
||||||
|
flatten="false"
|
||||||
|
hide_clip="false"
|
||||||
|
message="Füllregel Gerade-Ungerade im <b>Füllung und Kontur</b>-Dialog verwenden, wenn das Anwenden des Ausschnitts mit nachfolgendem Umwandeln in Pfade kein Ergebnis bringt" />
|
||||||
|
<rect
|
||||||
|
x="500"
|
||||||
|
y="800"
|
||||||
|
width="840"
|
||||||
|
height="220"
|
||||||
|
id="rect7833" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient1152">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ed02a0;stop-opacity:1"
|
||||||
|
offset="0"
|
||||||
|
id="stop1148" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8900cb;stop-opacity:1"
|
||||||
|
offset="1"
|
||||||
|
id="stop1150" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient2059"
|
||||||
|
id="linearGradient1154"
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1920"
|
||||||
|
y2="1080"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient4289"
|
||||||
|
x1="-398"
|
||||||
|
y1="56"
|
||||||
|
x2="1522"
|
||||||
|
y2="1136"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(398,-56)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient7579"
|
||||||
|
x1="-398"
|
||||||
|
y1="56"
|
||||||
|
x2="1522"
|
||||||
|
y2="1136"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(398,-56)" />
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath878">
|
||||||
|
<path
|
||||||
|
id="path880"
|
||||||
|
style="display:none;fill:url(#linearGradient882);stroke-width:1.00028"
|
||||||
|
d="m 1170.0221,-4.111892 a 21.817197,20.751893 3.393352 0 0 -8.3753,3.68511674 21.817197,20.751893 3.393352 0 0 -4.1775,28.99380526 l 0.2304,0.284584 a 21.817197,20.751893 3.393352 0 0 30.5488,3.770316 21.817197,20.751893 3.393352 0 0 3.9128,-29.0289691 21.817197,20.751893 3.393352 0 0 -22.1392,-7.7048529 z M 858.04762,85.714292 c -7.15183,1.731644 -11.32417,8.932859 -9.35312,16.146398 l 22.2005,81.24794 c 1.97106,7.21354 9.31675,11.62594 16.46858,9.8943 L 1086.714,144.73497 c 7.1518,-1.73163 11.3223,-8.9324 9.3512,-16.14595 l -22.2005,-81.247936 c -1.971,-7.213536 -9.3149,-11.626381 -16.4667,-9.894748 z M 756.02165,124.73884 a 50.906793,48.421082 3.3933293 0 0 -19.54511,8.59585 50.906793,48.421082 3.3933293 0 0 -9.74699,67.65414 l 0.53564,0.66651 a 50.906793,48.421082 3.3933293 0 0 71.28286,8.79621 50.906793,48.421082 3.3933293 0 0 9.13065,-67.73384 50.906793,48.421082 3.3933293 0 0 -51.65705,-17.97887 z M 1139.8366,44.661798 a 21.817197,20.751893 3.393352 0 0 -8.3752,3.685094 21.817197,20.751893 3.393352 0 0 -4.1775,28.993805 l 0.2304,0.284584 a 21.817197,20.751893 3.393352 0 0 30.5487,3.770339 21.817197,20.751893 3.393352 0 0 3.9147,-29.029436 21.817197,20.751893 3.393352 0 0 -22.1411,-7.704386 z m 84.4396,-20.445031 a 21.817197,20.751893 3.393352 0 0 -8.3754,3.685117 21.817197,20.751893 3.393352 0 0 -4.1774,28.993806 l 0.2285,0.285027 a 21.817197,20.751893 3.393352 0 0 30.5488,3.77034 21.817197,20.751893 3.393352 0 0 3.9147,-29.02946 21.817197,20.751893 3.393352 0 0 -22.1392,-7.70483 z M 1193.05,74.672751 a 21.817197,20.751893 3.393352 0 0 -8.3759,3.68321 21.817197,20.751893 3.393352 0 0 -4.1769,28.995709 l 0.2303,0.28458 a 21.817197,20.751893 3.393352 0 0 30.5488,3.77035 21.817197,20.751893 3.393352 0 0 3.9128,-29.029006 21.817197,20.751893 3.393352 0 0 -22.1391,-7.704843 z M 865.52481,226.88685 c -7.36616,1.78355 -11.66248,9.20165 -9.63236,16.63136 l 5.86309,21.45735 -27.90161,6.7557 c -7.15183,1.73165 -11.32229,8.9324 -9.35123,16.14595 l 2.77837,10.1681 c 1.97106,7.21354 9.31487,11.6264 16.46669,9.89476 l 27.90161,-6.75571 6.22966,22.7989 c 2.03012,7.42971 9.59558,11.97577 16.96174,10.19223 l 8.59091,-2.08008 c 7.36616,-1.78354 11.6606,-9.2012 9.63048,-16.63091 l -6.22966,-22.7989 23.68151,-5.73391 c 7.15183,-1.73165 11.32229,-8.93242 9.35123,-16.14595 l -2.77837,-10.16811 c -1.97106,-7.21354 -9.31486,-11.62639 -16.46669,-9.89474 l -23.68151,5.73391 -5.86309,-21.45735 c -2.03012,-7.42971 -9.5937,-11.97623 -16.95987,-10.19269 z m 272.15169,-63.56116 a 50.906793,48.421082 3.3933293 0 0 -19.5432,8.59539 50.906793,48.421082 3.3933293 0 0 -9.747,67.65414 l 0.5356,0.66651 a 50.906793,48.421082 3.3933293 0 0 71.2829,8.79621 50.906793,48.421082 3.3933293 0 0 9.1307,-67.73384 50.906793,48.421082 3.3933293 0 0 -51.659,-17.97841 z" />
|
||||||
|
<path
|
||||||
|
id="lpe_path-effect896"
|
||||||
|
style="fill:url(#linearGradient882);stroke-width:1.00028"
|
||||||
|
class="powerclip"
|
||||||
|
d="M 636.0108,56.943474 H 846.95389 V 569.86886 H 636.0108 Z m 534.0113,-61.055366 a 21.817197,20.751893 3.393352 0 0 -8.3753,3.68511674 21.817197,20.751893 3.393352 0 0 -4.1775,28.99380526 l 0.2304,0.284584 a 21.817197,20.751893 3.393352 0 0 30.5488,3.770316 21.817197,20.751893 3.393352 0 0 3.9128,-29.0289691 21.817197,20.751893 3.393352 0 0 -22.1392,-7.7048529 z M 858.04762,85.714292 c -7.15183,1.731644 -11.32417,8.932859 -9.35312,16.146398 l 22.2005,81.24794 c 1.97106,7.21354 9.31675,11.62594 16.46858,9.8943 L 1086.714,144.73497 c 7.1518,-1.73163 11.3223,-8.9324 9.3512,-16.14595 l -22.2005,-81.247936 c -1.971,-7.213536 -9.3149,-11.626381 -16.4667,-9.894748 z M 756.02165,124.73884 a 50.906793,48.421082 3.3933293 0 0 -19.54511,8.59585 50.906793,48.421082 3.3933293 0 0 -9.74699,67.65414 l 0.53564,0.66651 a 50.906793,48.421082 3.3933293 0 0 71.28286,8.79621 50.906793,48.421082 3.3933293 0 0 9.13065,-67.73384 50.906793,48.421082 3.3933293 0 0 -51.65705,-17.97887 z M 1139.8366,44.661798 a 21.817197,20.751893 3.393352 0 0 -8.3752,3.685094 21.817197,20.751893 3.393352 0 0 -4.1775,28.993805 l 0.2304,0.284584 a 21.817197,20.751893 3.393352 0 0 30.5487,3.770339 21.817197,20.751893 3.393352 0 0 3.9147,-29.029436 21.817197,20.751893 3.393352 0 0 -22.1411,-7.704386 z m 84.4396,-20.445031 a 21.817197,20.751893 3.393352 0 0 -8.3754,3.685117 21.817197,20.751893 3.393352 0 0 -4.1774,28.993806 l 0.2285,0.285027 a 21.817197,20.751893 3.393352 0 0 30.5488,3.77034 21.817197,20.751893 3.393352 0 0 3.9147,-29.02946 21.817197,20.751893 3.393352 0 0 -22.1392,-7.70483 z M 1193.05,74.672751 a 21.817197,20.751893 3.393352 0 0 -8.3759,3.68321 21.817197,20.751893 3.393352 0 0 -4.1769,28.995709 l 0.2303,0.28458 a 21.817197,20.751893 3.393352 0 0 30.5488,3.77035 21.817197,20.751893 3.393352 0 0 3.9128,-29.029006 21.817197,20.751893 3.393352 0 0 -22.1391,-7.704843 z M 865.52481,226.88685 c -7.36616,1.78355 -11.66248,9.20165 -9.63236,16.63136 l 5.86309,21.45735 -27.90161,6.7557 c -7.15183,1.73165 -11.32229,8.9324 -9.35123,16.14595 l 2.77837,10.1681 c 1.97106,7.21354 9.31487,11.6264 16.46669,9.89476 l 27.90161,-6.75571 6.22966,22.7989 c 2.03012,7.42971 9.59558,11.97577 16.96174,10.19223 l 8.59091,-2.08008 c 7.36616,-1.78354 11.6606,-9.2012 9.63048,-16.63091 l -6.22966,-22.7989 23.68151,-5.73391 c 7.15183,-1.73165 11.32229,-8.93242 9.35123,-16.14595 l -2.77837,-10.16811 c -1.97106,-7.21354 -9.31486,-11.62639 -16.46669,-9.89474 l -23.68151,5.73391 -5.86309,-21.45735 c -2.03012,-7.42971 -9.5937,-11.97623 -16.95987,-10.19269 z m 272.15169,-63.56116 a 50.906793,48.421082 3.3933293 0 0 -19.5432,8.59539 50.906793,48.421082 3.3933293 0 0 -9.747,67.65414 l 0.5356,0.66651 a 50.906793,48.421082 3.3933293 0 0 71.2829,8.79621 50.906793,48.421082 3.3933293 0 0 9.1307,-67.73384 50.906793,48.421082 3.3933293 0 0 -51.659,-17.97841 z" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient882"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.96459266,-0.23355313,0.26584317,0.97291549,369.02066,-147.43741)"
|
||||||
|
x1="-398"
|
||||||
|
y1="56"
|
||||||
|
x2="1522"
|
||||||
|
y2="1136" />
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath884">
|
||||||
|
<path
|
||||||
|
id="path886"
|
||||||
|
style="display:none;fill:url(#linearGradient888);stroke-width:1.00027"
|
||||||
|
d="m 1026.6374,528.82806 a 20.752793,21.815894 86.926601 0 0 -9.2243,-0.58528 20.752793,21.815894 86.926601 0 0 -18.53105,23.48045 l 0.0557,0.35396 a 20.752793,21.815894 86.926601 0 0 24.81605,17.20206 20.752793,21.815894 86.926601 0 0 18.3173,-23.63171 20.752793,21.815894 86.926601 0 0 -15.4337,-16.81948 z M 707.37883,465.4963 c -7.15078,-1.7386 -14.49832,2.66675 -16.47273,9.87849 l -22.23828,81.2277 c -1.97441,7.21175 2.19438,14.41711 9.34515,16.15571 l 199.32113,48.46175 c 7.15073,1.73859 14.49643,-2.66722 16.47084,-9.87896 l 22.23828,-81.2277 c 1.97441,-7.21174 -2.19254,-14.41666 -9.34327,-16.15524 z M 598.02135,453.23104 a 48.423182,50.903752 86.926623 0 0 -21.5241,-1.36927 48.423182,50.903752 86.926623 0 0 -43.23978,54.7896 l 0.12713,0.82721 a 48.423182,50.903752 86.926623 0 0 57.90649,40.13811 48.423182,50.903752 86.926623 0 0 42.74098,-55.13985 48.423182,50.903752 86.926623 0 0 -36.01072,-39.2458 z m 377.16446,104.5578 a 20.752793,21.815894 86.926601 0 0 -9.22414,-0.58526 20.752793,21.815894 86.926601 0 0 -18.53108,23.48045 l 0.0557,0.35396 a 20.752793,21.815894 86.926601 0 0 24.8159,17.20204 20.752793,21.815894 86.926601 0 0 18.31921,-23.63124 20.752793,21.815894 86.926601 0 0 -15.43563,-16.81995 z m 84.42719,20.52712 a 20.752793,21.815894 86.926601 0 0 -9.2243,-0.58529 20.752793,21.815894 86.926601 0 0 -18.531,23.48045 l 0.054,0.35352 a 20.752793,21.815894 86.926601 0 0 24.8159,17.20204 20.752793,21.815894 86.926601 0 0 18.3193,-23.63122 20.752793,21.815894 86.926601 0 0 -15.4338,-16.8195 z m -53.2258,29.9599 a 20.752793,21.815894 86.926601 0 0 -9.22373,-0.58718 20.752793,21.815894 86.926601 0 0 -18.53161,23.48235 l 0.0557,0.35395 a 20.752793,21.815894 86.926601 0 0 24.81584,17.20205 20.752793,21.815894 86.926601 0 0 18.3174,-23.63169 20.752793,21.815894 86.926601 0 0 -15.4337,-16.81948 z M 641.50831,592.48259 c -7.36508,-1.79069 -14.93245,2.74811 -16.96603,10.17597 l -5.87307,21.452 -27.8975,-6.78283 c -7.15078,-1.7386 -14.49644,2.6672 -16.47085,9.87895 l -2.7831,10.16557 c -1.97441,7.21174 2.1925,14.41666 9.34328,16.15525 l 27.8975,6.78284 -6.24026,22.79322 c -2.03358,7.42786 2.25909,14.85024 9.62417,16.64094 l 8.58964,2.08844 c 7.36508,1.7907 14.93057,-2.74856 16.96415,-10.17642 l 6.24026,-22.79322 23.67803,5.75693 c 7.15078,1.7386 14.49644,-2.66722 16.47085,-9.87896 l 2.7831,-10.16557 c 1.97441,-7.21175 -2.1925,-14.41665 -9.34328,-16.15525 l -23.67803,-5.75693 5.87307,-21.45201 c 2.03358,-7.42785 -2.25721,-14.84978 -9.62229,-16.64048 z m 270.91446,68.20272 a 48.423182,50.903752 86.926623 0 0 -21.52221,-1.3688 48.423182,50.903752 86.926623 0 0 -43.23975,54.78961 l 0.12708,0.8272 a 48.423182,50.903752 86.926623 0 0 57.90652,40.13811 48.423182,50.903752 86.926623 0 0 42.74097,-55.13984 48.423182,50.903752 86.926623 0 0 -36.01261,-39.24628 z" />
|
||||||
|
<path
|
||||||
|
id="lpe_path-effect900"
|
||||||
|
style="fill:url(#linearGradient888);stroke-width:1.00027"
|
||||||
|
class="powerclip"
|
||||||
|
d="M 912.35657,483.93158 H 1121.6656 V 998.54486 H 912.35657 Z m 114.28083,44.89648 a 20.752793,21.815894 86.926601 0 0 -9.2243,-0.58528 20.752793,21.815894 86.926601 0 0 -18.53105,23.48045 l 0.0557,0.35396 a 20.752793,21.815894 86.926601 0 0 24.81605,17.20206 20.752793,21.815894 86.926601 0 0 18.3173,-23.63171 20.752793,21.815894 86.926601 0 0 -15.4337,-16.81948 z M 707.37883,465.4963 c -7.15078,-1.7386 -14.49832,2.66675 -16.47273,9.87849 l -22.23828,81.2277 c -1.97441,7.21175 2.19438,14.41711 9.34515,16.15571 l 199.32113,48.46175 c 7.15073,1.73859 14.49643,-2.66722 16.47084,-9.87896 l 22.23828,-81.2277 c 1.97441,-7.21174 -2.19254,-14.41666 -9.34327,-16.15524 z M 598.02135,453.23104 a 48.423182,50.903752 86.926623 0 0 -21.5241,-1.36927 48.423182,50.903752 86.926623 0 0 -43.23978,54.7896 l 0.12713,0.82721 a 48.423182,50.903752 86.926623 0 0 57.90649,40.13811 48.423182,50.903752 86.926623 0 0 42.74098,-55.13985 48.423182,50.903752 86.926623 0 0 -36.01072,-39.2458 z m 377.16446,104.5578 a 20.752793,21.815894 86.926601 0 0 -9.22414,-0.58526 20.752793,21.815894 86.926601 0 0 -18.53108,23.48045 l 0.0557,0.35396 a 20.752793,21.815894 86.926601 0 0 24.8159,17.20204 20.752793,21.815894 86.926601 0 0 18.31921,-23.63124 20.752793,21.815894 86.926601 0 0 -15.43563,-16.81995 z m 84.42719,20.52712 a 20.752793,21.815894 86.926601 0 0 -9.2243,-0.58529 20.752793,21.815894 86.926601 0 0 -18.531,23.48045 l 0.054,0.35352 a 20.752793,21.815894 86.926601 0 0 24.8159,17.20204 20.752793,21.815894 86.926601 0 0 18.3193,-23.63122 20.752793,21.815894 86.926601 0 0 -15.4338,-16.8195 z m -53.2258,29.9599 a 20.752793,21.815894 86.926601 0 0 -9.22373,-0.58718 20.752793,21.815894 86.926601 0 0 -18.53161,23.48235 l 0.0557,0.35395 a 20.752793,21.815894 86.926601 0 0 24.81584,17.20205 20.752793,21.815894 86.926601 0 0 18.3174,-23.63169 20.752793,21.815894 86.926601 0 0 -15.4337,-16.81948 z M 641.50831,592.48259 c -7.36508,-1.79069 -14.93245,2.74811 -16.96603,10.17597 l -5.87307,21.452 -27.8975,-6.78283 c -7.15078,-1.7386 -14.49644,2.6672 -16.47085,9.87895 l -2.7831,10.16557 c -1.97441,7.21174 2.1925,14.41666 9.34328,16.15525 l 27.8975,6.78284 -6.24026,22.79322 c -2.03358,7.42786 2.25909,14.85024 9.62417,16.64094 l 8.58964,2.08844 c 7.36508,1.7907 14.93057,-2.74856 16.96415,-10.17642 l 6.24026,-22.79322 23.67803,5.75693 c 7.15078,1.7386 14.49644,-2.66722 16.47085,-9.87896 l 2.7831,-10.16557 c 1.97441,-7.21175 -2.1925,-14.41665 -9.34328,-16.15525 l -23.67803,-5.75693 5.87307,-21.45201 c 2.03358,-7.42785 -2.25721,-14.84978 -9.62229,-16.64048 z m 270.91446,68.20272 a 48.423182,50.903752 86.926623 0 0 -21.52221,-1.3688 48.423182,50.903752 86.926623 0 0 -43.23975,54.78961 l 0.12708,0.8272 a 48.423182,50.903752 86.926623 0 0 57.90652,40.13811 48.423182,50.903752 86.926623 0 0 42.74097,-55.13984 48.423182,50.903752 86.926623 0 0 -36.01261,-39.24628 z" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient888"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.96445087,0.23449084,-0.26629564,0.97267307,398.764,38.857662)"
|
||||||
|
x1="-398"
|
||||||
|
y1="56"
|
||||||
|
x2="1522"
|
||||||
|
y2="1136" />
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath890">
|
||||||
|
<path
|
||||||
|
id="path892"
|
||||||
|
style="display:none;fill:url(#linearGradient894)"
|
||||||
|
d="m 1138.793,269.14648 a 21.88452,20.676565 0 0 0 -9.1231,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1484,0.32813 a 21.88452,20.676565 0 0 0 28.7032,10.76562 21.88452,20.676565 0 0 0 11.5175,-27.07226 21.88452,20.676565 0 0 0 -19.4804,-12.59571 z m -327.22269,13.7754 c -7.41435,0 -13.38476,5.96846 -13.38476,13.38281 v 83.50976 c 0,7.41436 5.97041,13.38282 13.38476,13.38282 h 206.66799 c 7.4143,0 13.3828,-5.96846 13.3828,-13.38282 v -83.50976 c 0,-7.41435 -5.9685,-13.38281 -13.3828,-13.38281 z m -109.57617,13.80664 a 51.063881,48.245316 0 0 0 -21.28906,3.7246 51.063881,48.245316 0 0 0 -27.45313,62.94727 l 0.34375,0.76758 a 51.063881,48.245316 0 0 0 66.97657,25.11914 51.063881,48.245316 0 0 0 26.875,-63.16797 51.063881,48.245316 0 0 0 -45.45313,-29.39062 z m 394.48826,12.39257 a 21.88452,20.676565 0 0 0 -9.123,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1484,0.32813 a 21.88452,20.676565 0 0 0 28.7031,10.76562 21.88452,20.676565 0 0 0 11.5195,-27.07226 21.88452,20.676565 0 0 0 -19.4824,-12.59571 z m 87.5391,0 a 21.88452,20.676565 0 0 0 -9.1231,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1465,0.32813 a 21.88452,20.676565 0 0 0 28.7031,10.76562 21.88452,20.676565 0 0 0 11.5196,-27.07226 21.88452,20.676565 0 0 0 -19.4805,-12.59571 z m -43.7695,41.35352 a 21.88452,20.676565 0 0 0 -9.1231,1.5957 21.88452,20.676565 0 0 0 -11.7656,26.97852 l 0.1484,0.32812 a 21.88452,20.676565 0 0 0 28.7031,10.76563 21.88452,20.676565 0 0 0 11.5176,-27.07227 21.88452,20.676565 0 0 0 -19.4804,-12.5957 z m -358.91997,70.29101 c -7.63655,10e-6 -13.78515,6.14862 -13.78515,13.78516 v 22.05469 h -28.92579 c -7.41435,0 -13.38281,5.96845 -13.38281,13.38281 v 10.45117 c 0,7.41435 5.96846,13.38282 13.38281,13.38282 h 28.92579 v 23.43359 c 0,7.63654 6.1486,13.78516 13.78515,13.78516 h 8.90625 c 7.63655,0 13.7832,-6.14862 13.7832,-13.78516 v -23.43359 h 24.55079 c 7.41435,0 13.38281,-5.96847 13.38281,-13.38282 v -10.45117 c 0,-7.41436 -5.96846,-13.38281 -13.38281,-13.38281 h -24.55079 v -22.05469 c 0,-7.63654 -6.14665,-13.78516 -13.7832,-13.78516 z m 281.52147,2.25 a 51.063881,48.245316 0 0 0 -21.2871,3.72461 51.063881,48.245316 0 0 0 -27.4531,62.94727 l 0.3437,0.76758 a 51.063881,48.245316 0 0 0 66.9766,25.11914 51.063881,48.245316 0 0 0 26.875,-63.16797 51.063881,48.245316 0 0 0 -45.4551,-29.39063 z" />
|
||||||
|
<path
|
||||||
|
id="lpe_path-effect904"
|
||||||
|
style="fill:url(#linearGradient894)"
|
||||||
|
class="powerclip"
|
||||||
|
d="M 571.42297,222.78436 H 1252.5483 V 563.60941 H 571.42297 Z m 567.37003,46.36212 a 21.88452,20.676565 0 0 0 -9.1231,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1484,0.32813 a 21.88452,20.676565 0 0 0 28.7032,10.76562 21.88452,20.676565 0 0 0 11.5175,-27.07226 21.88452,20.676565 0 0 0 -19.4804,-12.59571 z m -327.22269,13.7754 c -7.41435,0 -13.38476,5.96846 -13.38476,13.38281 v 83.50976 c 0,7.41436 5.97041,13.38282 13.38476,13.38282 h 206.66799 c 7.4143,0 13.3828,-5.96846 13.3828,-13.38282 v -83.50976 c 0,-7.41435 -5.9685,-13.38281 -13.3828,-13.38281 z m -109.57617,13.80664 a 51.063881,48.245316 0 0 0 -21.28906,3.7246 51.063881,48.245316 0 0 0 -27.45313,62.94727 l 0.34375,0.76758 a 51.063881,48.245316 0 0 0 66.97657,25.11914 51.063881,48.245316 0 0 0 26.875,-63.16797 51.063881,48.245316 0 0 0 -45.45313,-29.39062 z m 394.48826,12.39257 a 21.88452,20.676565 0 0 0 -9.123,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1484,0.32813 a 21.88452,20.676565 0 0 0 28.7031,10.76562 21.88452,20.676565 0 0 0 11.5195,-27.07226 21.88452,20.676565 0 0 0 -19.4824,-12.59571 z m 87.5391,0 a 21.88452,20.676565 0 0 0 -9.1231,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1465,0.32813 a 21.88452,20.676565 0 0 0 28.7031,10.76562 21.88452,20.676565 0 0 0 11.5196,-27.07226 21.88452,20.676565 0 0 0 -19.4805,-12.59571 z m -43.7695,41.35352 a 21.88452,20.676565 0 0 0 -9.1231,1.5957 21.88452,20.676565 0 0 0 -11.7656,26.97852 l 0.1484,0.32812 a 21.88452,20.676565 0 0 0 28.7031,10.76563 21.88452,20.676565 0 0 0 11.5176,-27.07227 21.88452,20.676565 0 0 0 -19.4804,-12.5957 z m -358.91997,70.29101 c -7.63655,10e-6 -13.78515,6.14862 -13.78515,13.78516 v 22.05469 h -28.92579 c -7.41435,0 -13.38281,5.96845 -13.38281,13.38281 v 10.45117 c 0,7.41435 5.96846,13.38282 13.38281,13.38282 h 28.92579 v 23.43359 c 0,7.63654 6.1486,13.78516 13.78515,13.78516 h 8.90625 c 7.63655,0 13.7832,-6.14862 13.7832,-13.78516 v -23.43359 h 24.55079 c 7.41435,0 13.38281,-5.96847 13.38281,-13.38282 v -10.45117 c 0,-7.41436 -5.96846,-13.38281 -13.38281,-13.38281 h -24.55079 v -22.05469 c 0,-7.63654 -6.14665,-13.78516 -13.7832,-13.78516 z m 281.52147,2.25 a 51.063881,48.245316 0 0 0 -21.2871,3.72461 51.063881,48.245316 0 0 0 -27.4531,62.94727 l 0.3437,0.76758 a 51.063881,48.245316 0 0 0 66.9766,25.11914 51.063881,48.245316 0 0 0 26.875,-63.16797 51.063881,48.245316 0 0 0 -45.4551,-29.39063 z" />
|
||||||
|
</clipPath>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1152"
|
||||||
|
id="linearGradient894"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(398,-56)"
|
||||||
|
x1="-398"
|
||||||
|
y1="56"
|
||||||
|
x2="1522"
|
||||||
|
y2="1136" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient1154);fill-opacity:1"
|
||||||
|
id="rect1033"
|
||||||
|
width="1920"
|
||||||
|
height="1080"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
rx="0"
|
||||||
|
ry="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect2078"
|
||||||
|
width="671.12531"
|
||||||
|
height="330.82504"
|
||||||
|
x="576.42297"
|
||||||
|
y="227.78436"
|
||||||
|
ry="110.27502"
|
||||||
|
sodipodi:type="rect"
|
||||||
|
clip-path="url(#clipPath890)"
|
||||||
|
inkscape:path-effect="#path-effect904"
|
||||||
|
d="m 686.69799,227.78436 h 450.57531 c 61.0923,0 110.275,49.18266 110.275,110.27502 v 110.27501 c 0,61.09236 -49.1827,110.27502 -110.275,110.27502 H 686.69799 c -61.09236,0 -110.27502,-49.18266 -110.27502,-110.27502 V 338.05938 c 0,-61.09236 49.18266,-110.27502 110.27502,-110.27502 z" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41852"
|
||||||
|
id="rect2146"
|
||||||
|
width="199.30905"
|
||||||
|
height="504.61328"
|
||||||
|
x="917.35657"
|
||||||
|
y="488.93158"
|
||||||
|
ry="97.030388"
|
||||||
|
transform="matrix(0.97214881,-0.23436445,0.26615211,0.96393104,0,0)"
|
||||||
|
sodipodi:type="rect"
|
||||||
|
clip-path="url(#clipPath884)"
|
||||||
|
inkscape:path-effect="#path-effect900"
|
||||||
|
d="m 1014.387,488.93158 h 5.2482 c 53.7549,0 97.0304,43.27555 97.0304,97.03039 v 310.5525 c 0,53.75484 -43.2755,97.03039 -97.0304,97.03039 h -5.2482 c -53.75488,0 -97.03043,-43.27555 -97.03043,-97.03039 v -310.5525 c 0,-53.75484 43.27555,-97.03039 97.03043,-97.03039 z" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41852"
|
||||||
|
id="rect2146-3"
|
||||||
|
width="200.94308"
|
||||||
|
height="502.92538"
|
||||||
|
x="641.0108"
|
||||||
|
y="61.943474"
|
||||||
|
ry="97.050156"
|
||||||
|
transform="matrix(0.97237519,0.23342343,-0.26569554,0.96405699,0,0)"
|
||||||
|
sodipodi:type="rect"
|
||||||
|
clip-path="url(#clipPath878)"
|
||||||
|
inkscape:path-effect="#path-effect896"
|
||||||
|
d="m 738.06096,61.943474 h 6.84277 c 53.76579,0 97.05016,43.284366 97.05016,97.050156 V 467.8187 c 0,53.76579 -43.28437,97.05016 -97.05016,97.05016 h -6.84277 c -53.76579,0 -97.05016,-43.28437 -97.05016,-97.05016 V 158.99363 c 0,-53.76579 43.28437,-97.050156 97.05016,-97.050156 z" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect2384"
|
||||||
|
width="87.538078"
|
||||||
|
height="55.137505"
|
||||||
|
x="649.37134"
|
||||||
|
y="214"
|
||||||
|
ry="27.568752" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||||
|
id="rect2384-6"
|
||||||
|
width="87.538078"
|
||||||
|
height="55.137505"
|
||||||
|
x="1089.9797"
|
||||||
|
y="214"
|
||||||
|
ry="27.568752" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 24 KiB |
@@ -3,17 +3,28 @@ org.gradle.jvmargs=-Xmx1G
|
|||||||
|
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://fabricmc.net/use
|
# check these on https://fabricmc.net/use
|
||||||
minecraft_version=1.16.5
|
minecraft_version=1.18.2
|
||||||
yarn_mappings=1.16.5+build.5
|
yarn_mappings=1.18.2+build.3
|
||||||
loader_version=0.11.3
|
loader_version=0.14.8
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version = 1.6.0
|
mod_version = 1.5.0
|
||||||
maven_group = dev.lambdaurora.lambdacontrols
|
maven_group = eu.midnightdust
|
||||||
archives_base_name = lambdacontrols
|
archives_base_name = midnightcontrols
|
||||||
|
modrinth_id=bXX9h73M
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
|
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
|
||||||
fabric_version=0.32.0+1.16
|
fabric_version=0.57.0+1.18.2
|
||||||
spruceui_version=2.1.4-1.16
|
sodium_version=mc1.18.2-0.4.1
|
||||||
modmenu_version=1.16.8
|
spruceui_version=3.3.2+1.17
|
||||||
|
midnightlib_version=0.4.4
|
||||||
|
modmenu_version=2.0.2
|
||||||
|
emotecraft_version=2.1-MC1.18.1-fabric
|
||||||
|
bendylib_version=2.0.+
|
||||||
|
libgui_version=5.4.2+1.18.2
|
||||||
|
emi_version=0.2.0+1.18.2
|
||||||
|
|
||||||
|
# Ok Zoomer and LibZoomer are temporarily disabled for the time being, as we are currently using Reflection at runtime instead in OkZoomerCompat due to there being two major, completely incompatible API versions.
|
||||||
|
# ok_zoomer_version=5.0.0-beta.3+1.17.1
|
||||||
|
# libzoomer_version=0.3.0+1.17.1
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
269
gradlew
vendored
Normal file → Executable file
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright 2015 the original author or authors.
|
# Copyright © 2015-2021 the original authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -17,67 +17,101 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
#
|
||||||
## Gradle start up script for UN*X
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
##
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
app_path=$0
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
# Need this for daisy-chained symlinks.
|
||||||
ls=`ls -ld "$PRG"`
|
while
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
[ -h "$app_path" ]
|
||||||
PRG="$link"
|
do
|
||||||
else
|
ls=$( ls -ld "$app_path" )
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
link=${ls#*' -> '}
|
||||||
fi
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
APP_NAME="Gradle"
|
||||||
APP_BASE_NAME=`basename "$0"`
|
APP_BASE_NAME=${0##*/}
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD=maximum
|
||||||
|
|
||||||
warn () {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
die () {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "`uname`" in
|
case "$( uname )" in #(
|
||||||
CYGWIN* )
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
cygwin=true
|
Darwin* ) darwin=true ;; #(
|
||||||
;;
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
Darwin* )
|
NONSTOP* ) nonstop=true ;;
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
else
|
else
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD="java"
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
@@ -106,80 +140,95 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
case $MAX_FD in #(
|
||||||
if [ $? -eq 0 ] ; then
|
max*)
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
warn "Could not query maximum file descriptor limit"
|
||||||
fi
|
esac
|
||||||
ulimit -n $MAX_FD
|
case $MAX_FD in #(
|
||||||
if [ $? -ne 0 ] ; then
|
'' | soft) :;; #(
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
*)
|
||||||
fi
|
ulimit -n "$MAX_FD" ||
|
||||||
else
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Darwin, add options to specify how the application appears in the dock
|
|
||||||
if $darwin; then
|
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
||||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
|
||||||
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
||||||
SEP=""
|
|
||||||
for dir in $ROOTDIRSRAW ; do
|
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
||||||
SEP="|"
|
|
||||||
done
|
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
||||||
# Add a user-defined pattern to the cygpath arguments
|
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
||||||
fi
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
i=0
|
|
||||||
for arg in "$@" ; do
|
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
||||||
else
|
|
||||||
eval `echo args$i`="\"$arg\""
|
|
||||||
fi
|
|
||||||
i=`expr $i + 1`
|
|
||||||
done
|
|
||||||
case $i in
|
|
||||||
0) set -- ;;
|
|
||||||
1) set -- "$args0" ;;
|
|
||||||
2) set -- "$args0" "$args1" ;;
|
|
||||||
3) set -- "$args0" "$args1" "$args2" ;;
|
|
||||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
||||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
||||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
||||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
||||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
||||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
save () {
|
# * args from the command line
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
# * the main class name
|
||||||
echo " "
|
# * -classpath
|
||||||
}
|
# * -D...appname settings
|
||||||
APP_ARGS=`save "$@"`
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
BIN
icon.png
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 174 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 184 KiB |
@@ -1,11 +1,11 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
name = 'Fabric'
|
name 'Fabric'
|
||||||
url = 'https://maven.fabricmc.net/'
|
url 'https://maven.fabricmc.net/'
|
||||||
}
|
}
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.name = 'lambdacontrols'
|
rootProject.name = 'midnightcontrols'
|
||||||
|
|||||||
@@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.event.PlayerChangeControlsModeCallback;
|
|
||||||
import io.netty.buffer.Unpooled;
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
|
||||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
|
||||||
import net.fabricmc.loader.api.ModContainer;
|
|
||||||
import net.minecraft.network.PacketByteBuf;
|
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the LambdaControls mod.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.6.0
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public class LambdaControls implements ModInitializer {
|
|
||||||
private static LambdaControls INSTANCE;
|
|
||||||
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(LambdaControlsConstants.CONTROLS_MODE_CHANNEL.toString());
|
|
||||||
public static final Identifier FEATURE_CHANNEL = new Identifier(LambdaControlsConstants.FEATURE_CHANNEL.toString());
|
|
||||||
public static final Identifier HELLO_CHANNEL = new Identifier(LambdaControlsConstants.HELLO_CHANNEL.toString());
|
|
||||||
|
|
||||||
public static final TranslatableText NOT_BOUND_TEXT = new TranslatableText("lambdacontrols.not_bound");
|
|
||||||
|
|
||||||
public final Logger logger = LogManager.getLogger("LambdaControls");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInitialize() {
|
|
||||||
INSTANCE = this;
|
|
||||||
this.log("Initializing LambdaControls...");
|
|
||||||
|
|
||||||
ServerSidePacketRegistry.INSTANCE.register(HELLO_CHANNEL,
|
|
||||||
(context, attachedData) -> {
|
|
||||||
String version = attachedData.readString(32);
|
|
||||||
ControlsMode.byId(attachedData.readString(32))
|
|
||||||
.ifPresent(controlsMode -> context.getTaskQueue()
|
|
||||||
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.getPlayer(), controlsMode)));
|
|
||||||
context.getTaskQueue().execute(() ->
|
|
||||||
ServerSidePacketRegistry.INSTANCE.sendToPlayer(context.getPlayer(), FEATURE_CHANNEL, this.makeFeatureBuffer(LambdaControlsFeature.HORIZONTAL_REACHAROUND)));
|
|
||||||
});
|
|
||||||
ServerSidePacketRegistry.INSTANCE.register(CONTROLS_MODE_CHANNEL,
|
|
||||||
(context, attachedData) -> ControlsMode.byId(attachedData.readString(32))
|
|
||||||
.ifPresent(controlsMode -> context.getTaskQueue()
|
|
||||||
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.getPlayer(), controlsMode))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message to the terminal.
|
|
||||||
*
|
|
||||||
* @param info The message to print.
|
|
||||||
*/
|
|
||||||
public void log(String info) {
|
|
||||||
this.logger.info("[LambdaControls] " + info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a warning to the terminal.
|
|
||||||
*
|
|
||||||
* @param warning The warning to print.
|
|
||||||
*/
|
|
||||||
public void warn(String warning) {
|
|
||||||
this.logger.info("[LambdaControls] " + warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a packet byte buffer made for the lambdacontrols:controls_mode plugin message.
|
|
||||||
*
|
|
||||||
* @param controlsMode The controls mode to send.
|
|
||||||
* @return The packet byte buffer.
|
|
||||||
*/
|
|
||||||
public PacketByteBuf makeControlsModeBuffer(@NotNull ControlsMode controlsMode) {
|
|
||||||
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
|
|
||||||
return new PacketByteBuf(Unpooled.buffer()).writeString(controlsMode.getName(), 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a packet byte buffer made for the lambdacontrols:feature plugin message.
|
|
||||||
*
|
|
||||||
* @param feature The feature data to send.
|
|
||||||
* @return The packet byte buffer.
|
|
||||||
*/
|
|
||||||
public PacketByteBuf makeFeatureBuffer(@NotNull LambdaControlsFeature feature) {
|
|
||||||
Objects.requireNonNull(feature, "Feature cannot be null.");
|
|
||||||
PacketByteBuf buffer = new PacketByteBuf(Unpooled.buffer()).writeString(feature.getName(), 64);
|
|
||||||
buffer.writeBoolean(feature.isAllowed());
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketByteBuf makeHello(@NotNull ControlsMode controlsMode) {
|
|
||||||
String version = "";
|
|
||||||
Optional<ModContainer> container;
|
|
||||||
if ((container = FabricLoader.getInstance().getModContainer(LambdaControlsConstants.NAMESPACE)).isPresent()) {
|
|
||||||
version = container.get().getMetadata().getVersion().getFriendlyString();
|
|
||||||
}
|
|
||||||
return new PacketByteBuf(Unpooled.buffer()).writeString(version, 32).writeString(controlsMode.getName(), 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the LambdaControls instance.
|
|
||||||
*
|
|
||||||
* @return The LambdaControls instance.
|
|
||||||
*/
|
|
||||||
public static LambdaControls get() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControls;
|
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControlsConstants;
|
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControlsFeature;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsHud;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.ring.KeyBindingRingAction;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.ring.LambdaRing;
|
|
||||||
import me.lambdaurora.spruceui.event.OpenScreenCallback;
|
|
||||||
import me.lambdaurora.spruceui.hud.HudManager;
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
|
||||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
|
||||||
import net.minecraft.client.options.KeyBinding;
|
|
||||||
import net.minecraft.client.toast.SystemToast;
|
|
||||||
import net.minecraft.client.util.InputUtil;
|
|
||||||
import net.minecraft.text.LiteralText;
|
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the LambdaControls client mod.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.6.0
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
public class LambdaControlsClient extends LambdaControls implements ClientModInitializer {
|
|
||||||
private static LambdaControlsClient INSTANCE;
|
|
||||||
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "look_up"),
|
|
||||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement");
|
|
||||||
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "look_right"),
|
|
||||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.movement");
|
|
||||||
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "look_down"),
|
|
||||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.movement");
|
|
||||||
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "look_left"),
|
|
||||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.movement");
|
|
||||||
/*public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "ring"),
|
|
||||||
InputUtil.Type.MOUSE, GLFW.GLFW_MOUSE_BUTTON_5, "key.categories.misc");*/
|
|
||||||
public static final Identifier CONTROLLER_BUTTONS = new Identifier(LambdaControlsConstants.NAMESPACE, "textures/gui/controller_buttons.png");
|
|
||||||
public static final Identifier CONTROLLER_AXIS = new Identifier(LambdaControlsConstants.NAMESPACE, "textures/gui/controller_axis.png");
|
|
||||||
public static final Identifier CURSOR_TEXTURE = new Identifier(LambdaControlsConstants.NAMESPACE, "textures/gui/cursor.png");
|
|
||||||
public final static File MAPPINGS_FILE = new File("config/gamecontrollerdb.txt");
|
|
||||||
public final LambdaControlsConfig config = new LambdaControlsConfig(this);
|
|
||||||
public final LambdaInput input = new LambdaInput(this);
|
|
||||||
public final LambdaRing ring = new LambdaRing(this);
|
|
||||||
public final LambdaReacharound reacharound = new LambdaReacharound();
|
|
||||||
private LambdaControlsHud hud;
|
|
||||||
private ControlsMode previousControlsMode;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInitializeClient() {
|
|
||||||
INSTANCE = this;
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_UP);
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT);
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN);
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT);
|
|
||||||
//KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
|
||||||
|
|
||||||
this.ring.registerAction("keybinding", KeyBindingRingAction.FACTORY);
|
|
||||||
|
|
||||||
ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (client, handler, buf, responseSender) -> {
|
|
||||||
responseSender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(this.config.getControlsMode()));
|
|
||||||
});
|
|
||||||
ClientPlayNetworking.registerGlobalReceiver(FEATURE_CHANNEL, (client, handler, buf, responseSender) -> {
|
|
||||||
String name = buf.readString(64);
|
|
||||||
boolean allowed = buf.readBoolean();
|
|
||||||
LambdaControlsFeature.fromName(name).ifPresent(feature -> client.execute(() -> feature.setAllowed(allowed)));
|
|
||||||
});
|
|
||||||
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
|
||||||
sender.sendPacket(HELLO_CHANNEL, this.makeHello(this.config.getControlsMode()));
|
|
||||||
sender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(this.config.getControlsMode()));
|
|
||||||
});
|
|
||||||
ClientPlayConnectionEvents.DISCONNECT.register(this::onLeave);
|
|
||||||
|
|
||||||
ClientTickEvents.START_CLIENT_TICK.register(this.reacharound::tick);
|
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
|
|
||||||
|
|
||||||
OpenScreenCallback.EVENT.register((client, screen) -> {
|
|
||||||
if (screen == null && this.config.getControlsMode() == ControlsMode.TOUCHSCREEN) {
|
|
||||||
screen = new TouchscreenOverlay(this);
|
|
||||||
screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
|
||||||
client.skipGameRender = false;
|
|
||||||
client.currentScreen = screen;
|
|
||||||
} else if (screen != null) {
|
|
||||||
this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
HudManager.register(this.hud = new LambdaControlsHud(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called when Minecraft is initializing.
|
|
||||||
*/
|
|
||||||
public void onMcInit(@NotNull MinecraftClient client) {
|
|
||||||
ButtonBinding.init(client.options);
|
|
||||||
this.config.load();
|
|
||||||
this.hud.setVisible(this.config.isHudEnabled());
|
|
||||||
Controller.updateMappings();
|
|
||||||
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
|
||||||
if (event == GLFW.GLFW_CONNECTED) {
|
|
||||||
Controller controller = Controller.byId(jid);
|
|
||||||
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.connected", jid),
|
|
||||||
new LiteralText(controller.getName())));
|
|
||||||
} else if (event == GLFW.GLFW_DISCONNECTED) {
|
|
||||||
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.disconnected", jid),
|
|
||||||
null));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.switchControlsMode();
|
|
||||||
});
|
|
||||||
|
|
||||||
LambdaControlsCompat.init(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called every Minecraft tick.
|
|
||||||
*
|
|
||||||
* @param client the client instance
|
|
||||||
*/
|
|
||||||
public void onTick(@NotNull MinecraftClient client) {
|
|
||||||
this.input.tick(client);
|
|
||||||
if (this.config.getControlsMode() == ControlsMode.CONTROLLER && (client.isWindowFocused() || this.config.hasUnfocusedInput()))
|
|
||||||
this.input.tickController(client);
|
|
||||||
|
|
||||||
/*if (BINDING_RING.wasPressed()) {
|
|
||||||
client.openScreen(new RingScreen());
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onRender(MinecraftClient client) {
|
|
||||||
this.input.onRender(client.getTickDelta(), client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when leaving a server.
|
|
||||||
*/
|
|
||||||
public void onLeave(ClientPlayNetworkHandler handler, MinecraftClient client) {
|
|
||||||
LambdaControlsFeature.resetAllAllowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Switches the controls mode if the auto switch is enabled.
|
|
||||||
*/
|
|
||||||
public void switchControlsMode() {
|
|
||||||
if (this.config.hasAutoSwitchMode()) {
|
|
||||||
if (this.config.getController().isGamepad()) {
|
|
||||||
this.previousControlsMode = this.config.getControlsMode();
|
|
||||||
this.config.setControlsMode(ControlsMode.CONTROLLER);
|
|
||||||
} else {
|
|
||||||
if (this.previousControlsMode == null) {
|
|
||||||
this.previousControlsMode = ControlsMode.DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.config.setControlsMode(this.previousControlsMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the HUD is enabled or not.
|
|
||||||
*
|
|
||||||
* @param enabled True if the HUD is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setHudEnabled(boolean enabled) {
|
|
||||||
this.config.setHudEnabled(enabled);
|
|
||||||
this.hud.setVisible(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the LambdaControls client instance.
|
|
||||||
*
|
|
||||||
* @return The LambdaControls client instance.
|
|
||||||
*/
|
|
||||||
public static LambdaControlsClient get() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,839 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.file.FileConfig;
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControlsFeature;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_X;
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents LambdaControls configuration.
|
|
||||||
*/
|
|
||||||
public class LambdaControlsConfig {
|
|
||||||
// General
|
|
||||||
private static final ControlsMode DEFAULT_CONTROLS_MODE = ControlsMode.DEFAULT;
|
|
||||||
private static final boolean DEFAULT_AUTO_SWITCH_MODE = false;
|
|
||||||
private static final boolean DEFAULT_DEBUG = false;
|
|
||||||
// HUD
|
|
||||||
private static final boolean DEFAULT_HUD_ENABLE = true;
|
|
||||||
private static final HudSide DEFAULT_HUD_SIDE = HudSide.LEFT;
|
|
||||||
// Gameplay
|
|
||||||
private static final boolean DEFAULT_ANALOG_MOVEMENT = true;
|
|
||||||
private static final boolean DEFAULT_FAST_BLOCK_INTERACTION = true;
|
|
||||||
private static final boolean DEFAULT_FLY_DRIFTING = false;
|
|
||||||
private static final boolean DEFAULT_FLY_VERTICAL_DRIFTING = true;
|
|
||||||
private static final boolean DEFAULT_HORIZONTAL_REACHAROUND = false;
|
|
||||||
private static final boolean DEFAULT_VERTICAL_REACHAROUND = false;
|
|
||||||
private static final boolean DEFAULT_REACHAROUND_OUTLINE = true;
|
|
||||||
private static final int[] DEFAULT_REACHAROUND_OUTLINE_COLOR = new int[]{255, 255, 255, 102};
|
|
||||||
// Controller
|
|
||||||
private static final ControllerType DEFAULT_CONTROLLER_TYPE = ControllerType.DEFAULT;
|
|
||||||
private static final double DEFAULT_DEAD_ZONE = 0.25;
|
|
||||||
private static final double DEFAULT_MAX_VALUE = 1;
|
|
||||||
private static final double DEFAULT_ROTATION_SPEED = 40.0;
|
|
||||||
private static final double DEFAULT_MOUSE_SPEED = 25.0;
|
|
||||||
private static final boolean DEFAULT_UNFOCUSED_INPUT = false;
|
|
||||||
private static final boolean DEFAULT_VIRTUAL_MOUSE = false;
|
|
||||||
private static final VirtualMouseSkin DEFAULT_VIRTUAL_MOUSE_SKIN = VirtualMouseSkin.DEFAULT_LIGHT;
|
|
||||||
|
|
||||||
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
|
|
||||||
|
|
||||||
protected final FileConfig config = FileConfig.builder("config/lambdacontrols.toml").concurrent().defaultResource("/config.toml").build();
|
|
||||||
private final LambdaControlsClient mod;
|
|
||||||
private ControlsMode controlsMode;
|
|
||||||
private ControllerType controllerType;
|
|
||||||
// Gameplay.
|
|
||||||
private boolean analogMovement;
|
|
||||||
private boolean shouldRenderReacharoundOutline;
|
|
||||||
private int[] reacharoundOutlineColor;
|
|
||||||
// Controller settings
|
|
||||||
private double rightDeadZone;
|
|
||||||
private double leftDeadZone;
|
|
||||||
private double[] maxAnalogValues = new double[]{DEFAULT_MAX_VALUE, DEFAULT_MAX_VALUE, DEFAULT_MAX_VALUE, DEFAULT_MAX_VALUE};
|
|
||||||
private double rotationSpeed;
|
|
||||||
private double mouseSpeed;
|
|
||||||
private boolean unfocusedInput;
|
|
||||||
private boolean virtualMouse;
|
|
||||||
private VirtualMouseSkin virtualMouseSkin;
|
|
||||||
// HUD settings.
|
|
||||||
private boolean hudEnable;
|
|
||||||
private HudSide hudSide;
|
|
||||||
|
|
||||||
public LambdaControlsConfig(@NotNull LambdaControlsClient mod) {
|
|
||||||
this.mod = mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the configuration
|
|
||||||
*/
|
|
||||||
public void load() {
|
|
||||||
this.config.load();
|
|
||||||
this.checkAndFix();
|
|
||||||
this.mod.log("Configuration loaded.");
|
|
||||||
this.controlsMode = ControlsMode.byId(this.config.getOrElse("controls", DEFAULT_CONTROLS_MODE.getName())).orElse(DEFAULT_CONTROLS_MODE);
|
|
||||||
// HUD settings.
|
|
||||||
this.hudEnable = this.config.getOrElse("hud.enable", DEFAULT_HUD_ENABLE);
|
|
||||||
this.hudSide = HudSide.byId(this.config.getOrElse("hud.side", DEFAULT_HUD_SIDE.getName())).orElse(DEFAULT_HUD_SIDE);
|
|
||||||
// Gameplay
|
|
||||||
this.analogMovement = this.config.getOrElse("gameplay.analog_movement", DEFAULT_ANALOG_MOVEMENT);
|
|
||||||
LambdaControlsFeature.FAST_BLOCK_PLACING.setEnabled(this.config.getOrElse("gameplay.fast_block_placing", DEFAULT_FAST_BLOCK_INTERACTION));
|
|
||||||
LambdaControlsFeature.HORIZONTAL_REACHAROUND.setEnabled(this.config.getOrElse("gameplay.reacharound.horizontal", DEFAULT_HORIZONTAL_REACHAROUND));
|
|
||||||
LambdaControlsFeature.VERTICAL_REACHAROUND.setEnabled(this.config.getOrElse("gameplay.reacharound.vertical", DEFAULT_VERTICAL_REACHAROUND));
|
|
||||||
this.shouldRenderReacharoundOutline = this.config.getOrElse("gameplay.reacharound.outline", DEFAULT_REACHAROUND_OUTLINE);
|
|
||||||
this.reacharoundOutlineColor = this.config.getOptional("gameplay.reacharound.outline_color")
|
|
||||||
.map(hex -> parseColor((String) hex))
|
|
||||||
.orElse(DEFAULT_REACHAROUND_OUTLINE_COLOR);
|
|
||||||
// Controller settings.
|
|
||||||
this.controllerType = ControllerType.byId(this.config.getOrElse("controller.type", DEFAULT_CONTROLLER_TYPE.getName())).orElse(DEFAULT_CONTROLLER_TYPE);
|
|
||||||
this.rightDeadZone = this.config.getOrElse("controller.right_dead_zone", DEFAULT_DEAD_ZONE);
|
|
||||||
this.leftDeadZone = this.config.getOrElse("controller.left_dead_zone", DEFAULT_DEAD_ZONE);
|
|
||||||
this.rotationSpeed = this.config.getOrElse("controller.rotation_speed", DEFAULT_ROTATION_SPEED);
|
|
||||||
this.mouseSpeed = this.config.getOrElse("controller.mouse_speed", DEFAULT_MOUSE_SPEED);
|
|
||||||
this.unfocusedInput = this.config.getOrElse("controller.unfocused_input", DEFAULT_UNFOCUSED_INPUT);
|
|
||||||
this.virtualMouse = this.config.getOrElse("controller.virtual_mouse", DEFAULT_VIRTUAL_MOUSE);
|
|
||||||
this.virtualMouseSkin = VirtualMouseSkin.byId(this.config.getOrElse("controller.virtual_mouse_skin", DEFAULT_VIRTUAL_MOUSE_SKIN.getName())).orElse(DEFAULT_VIRTUAL_MOUSE_SKIN);
|
|
||||||
|
|
||||||
for (int i = 0; i < this.maxAnalogValues.length; i++) {
|
|
||||||
this.maxAnalogValues[i] = this.config.getOrElse("controller.max_value_" + i, DEFAULT_MAX_VALUE);
|
|
||||||
}
|
|
||||||
// Controller controls.
|
|
||||||
InputManager.loadButtonBindings(this);
|
|
||||||
|
|
||||||
this.mod.ring.load(this.config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the configuration.
|
|
||||||
*/
|
|
||||||
public void save() {
|
|
||||||
this.config.set("controller.right_dead_zone", this.rightDeadZone);
|
|
||||||
this.config.set("controller.left_dead_zone", this.leftDeadZone);
|
|
||||||
this.config.set("controller.rotation_speed", this.rotationSpeed);
|
|
||||||
this.config.set("controller.mouse_speed", this.mouseSpeed);
|
|
||||||
this.config.set("controller.unfocused_input", this.unfocusedInput);
|
|
||||||
this.config.set("controller.virtual_mouse", this.virtualMouse);
|
|
||||||
|
|
||||||
for (int i = 0; i < this.maxAnalogValues.length; i++) {
|
|
||||||
this.config.set("controller.max_value_" + i, this.maxAnalogValues[i]);
|
|
||||||
}
|
|
||||||
this.config.save();
|
|
||||||
this.mod.log("Configuration saved.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkAndFix() {
|
|
||||||
InputManager.streamBindings().forEach(binding -> {
|
|
||||||
String path = "controller.controls." + binding.getName();
|
|
||||||
Object raw = this.config.getRaw(path);
|
|
||||||
if (raw instanceof Number) {
|
|
||||||
this.mod.warn("Invalid data at \"" + path + "\", fixing...");
|
|
||||||
this.config.set(path, String.valueOf(raw));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.config.contains("gameplay.front_block_placing.enabled")) {
|
|
||||||
this.setFrontBlockPlacing(this.config.getOrElse("gameplay.front_block_placing.enabled", DEFAULT_HORIZONTAL_REACHAROUND));
|
|
||||||
this.config.remove("gameplay.front_block_placing.enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.contains("gameplay.front_block_placing.outline")) {
|
|
||||||
this.setRenderReacharoundOutline(this.config.getOrElse("gameplay.front_block_placing.outline", DEFAULT_REACHAROUND_OUTLINE));
|
|
||||||
this.config.remove("gameplay.front_block_placing.outline");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.config.contains("gameplay.front_block_placing.outline_color")) {
|
|
||||||
this.config.getOptional("gameplay.front_block_placing.outline_color").ifPresent(color -> this.config.set("gameplay.reacharound.outline_color", color));
|
|
||||||
this.config.remove("gameplay.front_block_placing.outline_color");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.renamed("controller.dead_zone", "controller.right_dead_zone");
|
|
||||||
this.renamed("controller.controls.tab_left", "controller.controls.tab_back");
|
|
||||||
this.renamed("controller.controls.tab_right", "controller.controls.tab_next");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renamed(String oldPath, String newPath) {
|
|
||||||
if (!this.config.contains(oldPath))
|
|
||||||
return;
|
|
||||||
Object raw = this.config.getRaw(oldPath);
|
|
||||||
this.config.remove(oldPath);
|
|
||||||
this.config.set(newPath, raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the configuration to default values.
|
|
||||||
*/
|
|
||||||
public void reset() {
|
|
||||||
// General
|
|
||||||
this.setControlsMode(DEFAULT_CONTROLS_MODE);
|
|
||||||
this.setAutoSwitchMode(DEFAULT_AUTO_SWITCH_MODE);
|
|
||||||
this.setDebug(DEFAULT_DEBUG);
|
|
||||||
// Gameplay
|
|
||||||
this.setAnalogMovement(DEFAULT_ANALOG_MOVEMENT);
|
|
||||||
this.setFastBlockPlacing(DEFAULT_FAST_BLOCK_INTERACTION);
|
|
||||||
this.setFlyDrifting(DEFAULT_FLY_DRIFTING);
|
|
||||||
this.setFlyVerticalDrifting(DEFAULT_FLY_VERTICAL_DRIFTING);
|
|
||||||
this.setFrontBlockPlacing(DEFAULT_HORIZONTAL_REACHAROUND);
|
|
||||||
this.setVerticalReacharound(DEFAULT_VERTICAL_REACHAROUND);
|
|
||||||
this.setRenderReacharoundOutline(DEFAULT_REACHAROUND_OUTLINE);
|
|
||||||
// Controller
|
|
||||||
this.setControllerType(DEFAULT_CONTROLLER_TYPE);
|
|
||||||
this.setRightDeadZone(DEFAULT_DEAD_ZONE);
|
|
||||||
this.setLeftDeadZone(DEFAULT_DEAD_ZONE);
|
|
||||||
this.setRotationSpeed(DEFAULT_ROTATION_SPEED);
|
|
||||||
this.setMouseSpeed(DEFAULT_MOUSE_SPEED);
|
|
||||||
this.setUnfocusedInput(DEFAULT_UNFOCUSED_INPUT);
|
|
||||||
this.setVirtualMouse(DEFAULT_VIRTUAL_MOUSE);
|
|
||||||
this.setVirtualMouseSkin(DEFAULT_VIRTUAL_MOUSE_SKIN);
|
|
||||||
|
|
||||||
Arrays.fill(this.maxAnalogValues, DEFAULT_MAX_VALUE);
|
|
||||||
// HUD
|
|
||||||
this.setHudEnabled(DEFAULT_HUD_ENABLE);
|
|
||||||
this.setHudSide(DEFAULT_HUD_SIDE);
|
|
||||||
|
|
||||||
// Collect prevents concurrent modification.
|
|
||||||
InputManager.streamBindings().collect(Collectors.toList()).forEach(binding -> this.setButtonBinding(binding, binding.getDefaultButton()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the controls mode from the configuration.
|
|
||||||
*
|
|
||||||
* @return The controls mode.
|
|
||||||
*/
|
|
||||||
public @NotNull ControlsMode getControlsMode() {
|
|
||||||
return this.controlsMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the controls mode in the configuration.
|
|
||||||
*
|
|
||||||
* @param controlsMode The controls mode.
|
|
||||||
*/
|
|
||||||
public void setControlsMode(@NotNull ControlsMode controlsMode) {
|
|
||||||
this.controlsMode = controlsMode;
|
|
||||||
this.config.set("controls", controlsMode.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the auto switch mode is enabled or not.
|
|
||||||
*
|
|
||||||
* @return True if the auto switch mode is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasAutoSwitchMode() {
|
|
||||||
return this.config.getOrElse("auto_switch_mode", DEFAULT_AUTO_SWITCH_MODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the auto switch mode is enabled or not.
|
|
||||||
*
|
|
||||||
* @param autoSwitchMode True if the auto switch mode is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setAutoSwitchMode(boolean autoSwitchMode) {
|
|
||||||
this.config.set("auto_switch_mode", autoSwitchMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the mod has debug enabled or not.
|
|
||||||
*
|
|
||||||
* @return True if debug is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasDebug() {
|
|
||||||
return this.config.getOrElse("debug", DEFAULT_DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the mod has debug enabled or not.
|
|
||||||
*
|
|
||||||
* @param debug True if debug is enabled, else false.
|
|
||||||
*/
|
|
||||||
protected void setDebug(boolean debug) {
|
|
||||||
this.config.set("debug", debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HUD settings
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the HUD is enabled.
|
|
||||||
*
|
|
||||||
* @return True if the HUD is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean isHudEnabled() {
|
|
||||||
return this.hudEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the HUD is enabled.
|
|
||||||
*
|
|
||||||
* @param enable True if the HUD is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setHudEnabled(boolean enable) {
|
|
||||||
this.hudEnable = enable;
|
|
||||||
this.config.set("hud.enable", this.hudEnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the HUD side from the configuration.
|
|
||||||
*
|
|
||||||
* @return The HUD side.
|
|
||||||
*/
|
|
||||||
public @NotNull HudSide getHudSide() {
|
|
||||||
return this.hudSide;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the HUD side in the configuration.
|
|
||||||
*
|
|
||||||
* @param hudSide The HUD side.
|
|
||||||
*/
|
|
||||||
public void setHudSide(@NotNull HudSide hudSide) {
|
|
||||||
this.hudSide = hudSide;
|
|
||||||
this.config.set("hud.side", hudSide.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Gameplay settings
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether analog movement is enabled.
|
|
||||||
*
|
|
||||||
* @return {@code true} if analog movement is enabled, else {@code false}
|
|
||||||
*/
|
|
||||||
public boolean hasAnalogMovement() {
|
|
||||||
return this.analogMovement;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether analog movement is enabled.
|
|
||||||
*
|
|
||||||
* @param analogMovement {@code true} if analog movement is enabled, else {@code false}
|
|
||||||
*/
|
|
||||||
public void setAnalogMovement(boolean analogMovement) {
|
|
||||||
this.config.set("gameplay.analog_movement", this.analogMovement = analogMovement);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether fast block placing is enabled or not.
|
|
||||||
*
|
|
||||||
* @return True if fast block placing is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasFastBlockPlacing() {
|
|
||||||
return LambdaControlsFeature.FAST_BLOCK_PLACING.isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether fast block placing is enabled or not.
|
|
||||||
*
|
|
||||||
* @param enable True if fast block placing is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setFastBlockPlacing(boolean enable) {
|
|
||||||
LambdaControlsFeature.FAST_BLOCK_PLACING.setEnabled(enable);
|
|
||||||
this.config.set("gameplay.fast_block_placing", enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether fly drifting is enabled or not.
|
|
||||||
*
|
|
||||||
* @return True if fly drifting is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasFlyDrifting() {
|
|
||||||
return this.config.getOrElse("gameplay.fly.drifting", DEFAULT_FLY_DRIFTING);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether fly drifting is enabled or not.
|
|
||||||
*
|
|
||||||
* @param flyDrifting True if fly drifting is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setFlyDrifting(boolean flyDrifting) {
|
|
||||||
this.config.set("gameplay.fly.drifting", flyDrifting);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether vertical fly drifting is enabled or not.
|
|
||||||
*
|
|
||||||
* @return True if vertical fly drifting is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasFlyVerticalDrifting() {
|
|
||||||
return this.config.getOrElse("gameplay.fly.vertical_drifting", DEFAULT_FLY_VERTICAL_DRIFTING);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether vertical fly drifting is enabled or not.
|
|
||||||
*
|
|
||||||
* @param flyDrifting True if vertical fly drifting is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setFlyVerticalDrifting(boolean flyDrifting) {
|
|
||||||
this.config.set("gameplay.fly.vertical_drifting", flyDrifting);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether front block placing is enabled or not.
|
|
||||||
*
|
|
||||||
* @return True if front block placing is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasFrontBlockPlacing() {
|
|
||||||
return LambdaControlsFeature.HORIZONTAL_REACHAROUND.isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether front block placing is enabled or not.
|
|
||||||
*
|
|
||||||
* @param enable True if front block placing is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setFrontBlockPlacing(boolean enable) {
|
|
||||||
LambdaControlsFeature.HORIZONTAL_REACHAROUND.setEnabled(enable);
|
|
||||||
this.config.set("gameplay.reacharound.horizontal", enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether vertical reacharound is enabled or not.
|
|
||||||
*
|
|
||||||
* @return True if vertical reacharound is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasVerticalReacharound() {
|
|
||||||
return LambdaControlsFeature.VERTICAL_REACHAROUND.isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether vertical reacharound is enabled or not.
|
|
||||||
*
|
|
||||||
* @param enable True if vertical reacharound is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setVerticalReacharound(boolean enable) {
|
|
||||||
LambdaControlsFeature.VERTICAL_REACHAROUND.setEnabled(enable);
|
|
||||||
this.config.set("gameplay.reacharound.vertical", enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether front block placing outline is enabled or not.
|
|
||||||
*
|
|
||||||
* @return True if front block placing outline is enabled, else false.
|
|
||||||
*/
|
|
||||||
public boolean shouldRenderReacharoundOutline() {
|
|
||||||
return this.shouldRenderReacharoundOutline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether front block placing outline is enabled or not.
|
|
||||||
*
|
|
||||||
* @param render True if front block placing outline is enabled, else false.
|
|
||||||
*/
|
|
||||||
public void setRenderReacharoundOutline(boolean render) {
|
|
||||||
this.config.set("gameplay.reacharound.outline", this.shouldRenderReacharoundOutline = render);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the front block placing outline color as an integer array.
|
|
||||||
* <p>
|
|
||||||
* The integer array has 4 elements: red, green, blue and alpha.
|
|
||||||
*
|
|
||||||
* @return The color as a RGBA integer array.
|
|
||||||
*/
|
|
||||||
public int[] getReacharoundOutlineColor() {
|
|
||||||
return this.reacharoundOutlineColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Controller settings
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the used controller.
|
|
||||||
*
|
|
||||||
* @return the controller
|
|
||||||
*/
|
|
||||||
public Controller getController() {
|
|
||||||
Object raw = this.config.getRaw("controller.id");
|
|
||||||
if (raw instanceof Number) {
|
|
||||||
return Controller.byId((Integer) raw);
|
|
||||||
} else if (raw instanceof String) {
|
|
||||||
return Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1));
|
|
||||||
}
|
|
||||||
return Controller.byId(GLFW.GLFW_JOYSTICK_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the used controller.
|
|
||||||
*
|
|
||||||
* @param controller the controller
|
|
||||||
*/
|
|
||||||
public void setController(Controller controller) {
|
|
||||||
this.config.set("controller.id", controller.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the second controller (for Joy-Con supports).
|
|
||||||
*
|
|
||||||
* @return the second controller
|
|
||||||
*/
|
|
||||||
public Optional<Controller> getSecondController() {
|
|
||||||
Object raw = this.config.getRaw("controller.id2");
|
|
||||||
if (raw instanceof Number) {
|
|
||||||
if ((int) raw == -1)
|
|
||||||
return Optional.empty();
|
|
||||||
return Optional.of(Controller.byId((Integer) raw));
|
|
||||||
} else if (raw instanceof String) {
|
|
||||||
return Optional.of(Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1)));
|
|
||||||
}
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the second controller.
|
|
||||||
*
|
|
||||||
* @param controller the second controller
|
|
||||||
*/
|
|
||||||
public void setSecondController(@Nullable Controller controller) {
|
|
||||||
this.config.set("controller.id2", controller == null ? -1 : controller.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the controller's type.
|
|
||||||
*
|
|
||||||
* @return The controller's type.
|
|
||||||
*/
|
|
||||||
public @NotNull ControllerType getControllerType() {
|
|
||||||
return this.controllerType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the controller's type.
|
|
||||||
*
|
|
||||||
* @param controllerType The controller's type.
|
|
||||||
*/
|
|
||||||
public void setControllerType(@NotNull ControllerType controllerType) {
|
|
||||||
this.controllerType = controllerType;
|
|
||||||
this.config.set("controller.type", controllerType.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the controller's right dead zone from the configuration.
|
|
||||||
*
|
|
||||||
* @return the controller's right dead zone value
|
|
||||||
*/
|
|
||||||
public double getRightDeadZone() {
|
|
||||||
return this.rightDeadZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the controller's right dead zone in the configuration.
|
|
||||||
*
|
|
||||||
* @param deadZone the controller's right dead zone value
|
|
||||||
*/
|
|
||||||
public void setRightDeadZone(double deadZone) {
|
|
||||||
this.rightDeadZone = deadZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the controller's left dead zone from the configuration.
|
|
||||||
*
|
|
||||||
* @return the controller's left dead zone value
|
|
||||||
*/
|
|
||||||
public double getLeftDeadZone() {
|
|
||||||
return this.leftDeadZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the controller's left dead zone in the configuration.
|
|
||||||
*
|
|
||||||
* @param deadZone the controller's left dead zone value
|
|
||||||
*/
|
|
||||||
public void setLeftDeadZone(double deadZone) {
|
|
||||||
this.leftDeadZone = deadZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the controller's rotation speed.
|
|
||||||
*
|
|
||||||
* @return The rotation speed.
|
|
||||||
*/
|
|
||||||
public double getRotationSpeed() {
|
|
||||||
return this.rotationSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the controller's rotation speed.
|
|
||||||
*
|
|
||||||
* @param rotationSpeed The rotation speed.
|
|
||||||
*/
|
|
||||||
public void setRotationSpeed(double rotationSpeed) {
|
|
||||||
this.rotationSpeed = rotationSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the controller's mouse speed.
|
|
||||||
*
|
|
||||||
* @return The mouse speed.
|
|
||||||
*/
|
|
||||||
public double getMouseSpeed() {
|
|
||||||
return this.mouseSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the controller's mouse speed.
|
|
||||||
*
|
|
||||||
* @param mouseSpeed The mouse speed.
|
|
||||||
*/
|
|
||||||
public void setMouseSpeed(double mouseSpeed) {
|
|
||||||
this.mouseSpeed = mouseSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the right X axis is inverted or not.
|
|
||||||
*
|
|
||||||
* @return True if the right X axis is inverted, else false.
|
|
||||||
*/
|
|
||||||
public boolean doesInvertRightXAxis() {
|
|
||||||
return this.config.getOrElse("controller.invert_right_x_axis", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the right X axis is inverted or not.
|
|
||||||
*
|
|
||||||
* @param invert True if the right X axis is inverted, else false.
|
|
||||||
*/
|
|
||||||
public void setInvertRightXAxis(boolean invert) {
|
|
||||||
this.config.set("controller.invert_right_x_axis", invert);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the right Y axis is inverted or not.
|
|
||||||
*
|
|
||||||
* @return True if the right Y axis is inverted, else false.
|
|
||||||
*/
|
|
||||||
public boolean doesInvertRightYAxis() {
|
|
||||||
return this.config.getOrElse("controller.invert_right_y_axis", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the right Y axis is inverted or not.
|
|
||||||
*
|
|
||||||
* @param invert True if the right Y axis is inverted, else false.
|
|
||||||
*/
|
|
||||||
public void setInvertRightYAxis(boolean invert) {
|
|
||||||
this.config.set("controller.invert_right_y_axis", invert);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether unfocused controller input is allowed or not.
|
|
||||||
*
|
|
||||||
* @return True if unfocused controller input is allowed, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasUnfocusedInput() {
|
|
||||||
return this.unfocusedInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether unfocused controller input is allowed or not.
|
|
||||||
*
|
|
||||||
* @param unfocusedInput True if unfocused controller input is allowed, else false.
|
|
||||||
*/
|
|
||||||
public void setUnfocusedInput(boolean unfocusedInput) {
|
|
||||||
this.unfocusedInput = unfocusedInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the mouse is virtual or not.
|
|
||||||
*
|
|
||||||
* @return True if the mouse is virtual, else false.
|
|
||||||
*/
|
|
||||||
public boolean hasVirtualMouse() {
|
|
||||||
return this.virtualMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the mouse is virtual or not.
|
|
||||||
*
|
|
||||||
* @param virtualMouse True if the mouse is virtual, else false.
|
|
||||||
*/
|
|
||||||
public void setVirtualMouse(boolean virtualMouse) {
|
|
||||||
this.virtualMouse = virtualMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the virtual mouse skin.
|
|
||||||
*
|
|
||||||
* @return The virtual mouse skin.
|
|
||||||
*/
|
|
||||||
public VirtualMouseSkin getVirtualMouseSkin() {
|
|
||||||
return this.virtualMouseSkin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the virtual mouse skin.
|
|
||||||
*
|
|
||||||
* @param skin The virtual mouse skin.
|
|
||||||
*/
|
|
||||||
public void setVirtualMouseSkin(VirtualMouseSkin skin) {
|
|
||||||
this.virtualMouseSkin = skin;
|
|
||||||
this.config.set("controller.virtual_mouse_skin", skin.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the right X axis sign.
|
|
||||||
*
|
|
||||||
* @return The right X axis sign.
|
|
||||||
*/
|
|
||||||
public double getRightXAxisSign() {
|
|
||||||
return this.doesInvertRightXAxis() ? -1.0 : 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the right Y axis sign.
|
|
||||||
*
|
|
||||||
* @return The right Y axis sign.
|
|
||||||
*/
|
|
||||||
public double getRightYAxisSign() {
|
|
||||||
return this.doesInvertRightYAxis() ? -1.0 : 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getAxisMaxValue(int axis) {
|
|
||||||
if (axis >= this.maxAnalogValues.length)
|
|
||||||
return DEFAULT_MAX_VALUE;
|
|
||||||
return this.maxAnalogValues[axis];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAxisMaxValue(int axis, double value) {
|
|
||||||
if (axis < this.maxAnalogValues.length)
|
|
||||||
this.maxAnalogValues[axis] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the button binding from configuration.
|
|
||||||
*
|
|
||||||
* @param button The button binding.
|
|
||||||
*/
|
|
||||||
public void loadButtonBinding(@NotNull ButtonBinding button) {
|
|
||||||
button.setButton(button.getDefaultButton());
|
|
||||||
String code = this.config.getOrElse("controller.controls." + button.getName(), button.getButtonCode());
|
|
||||||
|
|
||||||
Matcher matcher = BUTTON_BINDING_PATTERN.matcher(code);
|
|
||||||
|
|
||||||
try {
|
|
||||||
int[] buttons = new int[1];
|
|
||||||
int count = 0;
|
|
||||||
while (matcher.find()) {
|
|
||||||
count++;
|
|
||||||
if (count > buttons.length)
|
|
||||||
buttons = Arrays.copyOf(buttons, count);
|
|
||||||
String current;
|
|
||||||
if (!this.checkValidity(button, code, current = matcher.group(1)))
|
|
||||||
return;
|
|
||||||
buttons[count - 1] = Integer.parseInt(current);
|
|
||||||
}
|
|
||||||
if (count == 0) {
|
|
||||||
this.mod.warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
|
||||||
this.setButtonBinding(button, new int[]{-1});
|
|
||||||
}
|
|
||||||
|
|
||||||
button.setButton(buttons);
|
|
||||||
} catch (Exception e) {
|
|
||||||
this.mod.warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
|
||||||
this.config.set("controller.controls." + button.getName(), button.getButtonCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkValidity(@NotNull ButtonBinding binding, @NotNull String input, String group) {
|
|
||||||
if (group == null) {
|
|
||||||
this.mod.warn("Malformed config value \"" + input + "\" for binding \"" + binding.getName() + "\".");
|
|
||||||
this.config.set("controller.controls." + binding.getName(), binding.getButtonCode());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the button binding in configuration.
|
|
||||||
*
|
|
||||||
* @param binding The button binding.
|
|
||||||
* @param button The button.
|
|
||||||
*/
|
|
||||||
public void setButtonBinding(@NotNull ButtonBinding binding, int[] button) {
|
|
||||||
binding.setButton(button);
|
|
||||||
this.config.set("controller.controls." + binding.getName(), binding.getButtonCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBackButton(int btn, boolean isBtn, int state) {
|
|
||||||
if (!isBtn && state == 0)
|
|
||||||
return false;
|
|
||||||
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false) == ButtonBinding.axisAsButton(btn, state == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isForwardButton(int btn, boolean isBtn, int state) {
|
|
||||||
if (!isBtn && state == 0)
|
|
||||||
return false;
|
|
||||||
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true) == ButtonBinding.axisAsButton(btn, state == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLeftButton(int btn, boolean isBtn, int state) {
|
|
||||||
if (!isBtn && state == 0)
|
|
||||||
return false;
|
|
||||||
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false) == ButtonBinding.axisAsButton(btn, state == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRightButton(int btn, boolean isBtn, int state) {
|
|
||||||
if (!isBtn && state == 0)
|
|
||||||
return false;
|
|
||||||
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true) == ButtonBinding.axisAsButton(btn, state == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the specified axis is an axis used for movements.
|
|
||||||
*
|
|
||||||
* @param axis The axis index.
|
|
||||||
* @return True if the axis is used for movements, else false.
|
|
||||||
*/
|
|
||||||
public boolean isMovementAxis(int axis) {
|
|
||||||
return axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_X;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a color from a hexadecimal color string.
|
|
||||||
*
|
|
||||||
* @param hex The hexadecimal color.
|
|
||||||
* @return The color instance, null if invalid.
|
|
||||||
*/
|
|
||||||
private static int[] parseColor(String hex) {
|
|
||||||
hex = hex.replace("#", "");
|
|
||||||
switch (hex.length()) {
|
|
||||||
case 6:
|
|
||||||
return new int[]{
|
|
||||||
Integer.valueOf(hex.substring(0, 2), 16),
|
|
||||||
Integer.valueOf(hex.substring(2, 4), 16),
|
|
||||||
Integer.valueOf(hex.substring(4, 6), 16),
|
|
||||||
255
|
|
||||||
};
|
|
||||||
case 8:
|
|
||||||
return new int[]{
|
|
||||||
Integer.valueOf(hex.substring(0, 2), 16),
|
|
||||||
Integer.valueOf(hex.substring(2, 4), 16),
|
|
||||||
Integer.valueOf(hex.substring(4, 6), 16),
|
|
||||||
Integer.valueOf(hex.substring(6, 8), 16)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen;
|
|
||||||
import io.github.prospector.modmenu.api.ConfigScreenFactory;
|
|
||||||
import io.github.prospector.modmenu.api.ModMenuApi;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the API implementation of ModMenu for LambdaControls.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.3.0
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
public class LambdaControlsModMenu implements ModMenuApi {
|
|
||||||
@Override
|
|
||||||
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
|
||||||
return parent -> new LambdaControlsSettingsScreen(parent, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
|
||||||
import io.github.joaoh1.okzoomer.client.keybinds.ZoomKeybinds;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a compatibility handler for OkZoomer.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.4.3
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
public class OkZoomerCompat implements CompatHandler {
|
|
||||||
@Override
|
|
||||||
public void handle(@NotNull LambdaControlsClient mod) {
|
|
||||||
new ButtonBinding.Builder("zoom")
|
|
||||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
|
|
||||||
.onlyInGame()
|
|
||||||
.cooldown(true)
|
|
||||||
.category(ButtonBinding.MISC_CATEGORY)
|
|
||||||
.linkKeybind(ZoomKeybinds.zoomKey)
|
|
||||||
.register();
|
|
||||||
|
|
||||||
if (ZoomKeybinds.areExtraKeybindsEnabled()) {
|
|
||||||
new ButtonBinding.Builder("zoom_in")
|
|
||||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
|
||||||
.onlyInGame()
|
|
||||||
.cooldown(true)
|
|
||||||
.category(ButtonBinding.MISC_CATEGORY)
|
|
||||||
.linkKeybind(ZoomKeybinds.increaseZoomKey)
|
|
||||||
.register();
|
|
||||||
new ButtonBinding.Builder("zoom_out")
|
|
||||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
|
||||||
.onlyInGame()
|
|
||||||
.cooldown(true)
|
|
||||||
.category(ButtonBinding.MISC_CATEGORY)
|
|
||||||
.linkKeybind(ZoomKeybinds.decreaseZoomKey)
|
|
||||||
.register();
|
|
||||||
new ButtonBinding.Builder("zoom_reset")
|
|
||||||
.onlyInGame()
|
|
||||||
.cooldown(true)
|
|
||||||
.category(ButtonBinding.MISC_CATEGORY)
|
|
||||||
.linkKeybind(ZoomKeybinds.resetZoomKey)
|
|
||||||
.register();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,360 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.ButtonState;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.mixin.EntryListWidgetAccessor;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.mixin.EntryWidgetAccessor;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.mixin.RecipeViewingScreenAccessor;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.mixin.VillagerRecipeViewingScreenAccessor;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.InputHandlers;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.PressAction;
|
|
||||||
import me.shedaniel.rei.api.*;
|
|
||||||
import me.shedaniel.rei.gui.ContainerScreenOverlay;
|
|
||||||
import me.shedaniel.rei.gui.PreRecipeViewingScreen;
|
|
||||||
import me.shedaniel.rei.gui.RecipeViewingScreen;
|
|
||||||
import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
|
|
||||||
import me.shedaniel.rei.gui.widget.EntryListEntryWidget;
|
|
||||||
import me.shedaniel.rei.gui.widget.EntryListWidget;
|
|
||||||
import me.shedaniel.rei.gui.widget.EntryWidget;
|
|
||||||
import me.shedaniel.rei.gui.widget.WidgetWithBounds;
|
|
||||||
import me.shedaniel.rei.impl.ScreenHelper;
|
|
||||||
import me.shedaniel.rei.impl.widgets.ButtonWidget;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.gui.Element;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a compatibility handler for REI.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.5.0
|
|
||||||
* @since 1.2.0
|
|
||||||
*/
|
|
||||||
public class ReiCompat implements CompatHandler {
|
|
||||||
private static final Pair<Integer, Integer> INVALID_SLOT = new Pair<>(-1, -1);
|
|
||||||
private static EntryListWidget ENTRY_LIST_WIDGET;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(@NotNull LambdaControlsClient mod) {
|
|
||||||
ButtonBinding.builder(new Identifier("rei", "category_back"))
|
|
||||||
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
|
||||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
|
||||||
.action(handleTab(false))
|
|
||||||
.cooldown(true)
|
|
||||||
.register();
|
|
||||||
ButtonBinding.builder(new Identifier("rei", "category_next"))
|
|
||||||
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
|
||||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
|
||||||
.action(handleTab(true))
|
|
||||||
.cooldown(true)
|
|
||||||
.register();
|
|
||||||
|
|
||||||
ButtonBinding.builder(new Identifier("rei", "page_back"))
|
|
||||||
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, false))
|
|
||||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
|
||||||
.action(handlePage(false))
|
|
||||||
.cooldown(true)
|
|
||||||
.register();
|
|
||||||
ButtonBinding.builder(new Identifier("rei", "page_next"))
|
|
||||||
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, true))
|
|
||||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
|
||||||
.action(handlePage(true))
|
|
||||||
.cooldown(true)
|
|
||||||
.register();
|
|
||||||
|
|
||||||
ButtonBinding.builder(new Identifier("rei", "recipe_back"))
|
|
||||||
.buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP)
|
|
||||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
|
||||||
.action(handleRecipe(false))
|
|
||||||
.cooldown(true)
|
|
||||||
.register();
|
|
||||||
ButtonBinding.builder(new Identifier("rei", "recipe_next"))
|
|
||||||
.buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
|
||||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
|
||||||
.action(handleRecipe(true))
|
|
||||||
.cooldown(true)
|
|
||||||
.register();
|
|
||||||
|
|
||||||
// For some reasons this is broken.
|
|
||||||
ButtonBinding.builder(new Identifier("rei", "show_usage"))
|
|
||||||
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
|
||||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
|
||||||
.action(handleShowRecipeUsage(true))
|
|
||||||
.cooldown(true)
|
|
||||||
.register();
|
|
||||||
|
|
||||||
ButtonBinding.builder(new Identifier("rei", "show_recipe"))
|
|
||||||
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
|
||||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
|
||||||
.action(handleShowRecipeUsage(false))
|
|
||||||
.cooldown(true)
|
|
||||||
.register();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean requireMouseOnScreen(Screen screen) {
|
|
||||||
return isViewingScreen(screen) || screen instanceof PreRecipeViewingScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
|
|
||||||
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
|
|
||||||
if (overlay.isPresent() && overlay.get().isInside(mouseX, mouseY)) {
|
|
||||||
EntryListWidget widget = getEntryListWidget();
|
|
||||||
if (widget == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Pair<Integer, Integer> slot = this.getSlotAt(widget, mouseX, mouseY, false);
|
|
||||||
if (slot != null && slot != INVALID_SLOT)
|
|
||||||
return slot;
|
|
||||||
} else if (isViewingScreen(screen)) {
|
|
||||||
for (Element element : screen.children()) {
|
|
||||||
Pair<Integer, Integer> slot = this.getSlotAt(element, mouseX, mouseY, true);
|
|
||||||
if (slot != null && slot != INVALID_SLOT)
|
|
||||||
return slot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Element element, int mouseX, int mouseY, boolean allowEmpty) {
|
|
||||||
if (element instanceof EntryWidget) {
|
|
||||||
EntryWidget entry = (EntryWidget) element;
|
|
||||||
if (entry.containsMouse(mouseX, mouseY)) {
|
|
||||||
if (!allowEmpty && entry.entries().isEmpty())
|
|
||||||
return INVALID_SLOT;
|
|
||||||
return Pair.of(entry.getBounds().getX() + 1, entry.getBounds().getY() + 1);
|
|
||||||
}
|
|
||||||
} else if (element instanceof EntryListWidget) {
|
|
||||||
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
|
|
||||||
for (EntryListEntryWidget entry : entries) {
|
|
||||||
Pair<Integer, Integer> slot = this.getSlotAt(entry, mouseX, mouseY, allowEmpty);
|
|
||||||
if (slot != null && slot != INVALID_SLOT)
|
|
||||||
return slot;
|
|
||||||
}
|
|
||||||
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds) {
|
|
||||||
for (Element child : ((WidgetWithBounds) element).children()) {
|
|
||||||
Pair<Integer, Integer> slot = this.getSlotAt(child, mouseX, mouseY, allowEmpty);
|
|
||||||
if (slot != null && slot != INVALID_SLOT)
|
|
||||||
return slot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isViewingScreen(Screen screen) {
|
|
||||||
return screen instanceof RecipeViewingScreen || screen instanceof VillagerRecipeViewingScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
|
||||||
if (!isViewingScreen(screen))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
MinecraftClient.getInstance().openScreen(REIHelper.getInstance().getPreviousContainerScreen());
|
|
||||||
ScreenHelper.getLastOverlay().init();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static EntryListWidget getEntryListWidget() {
|
|
||||||
if (ENTRY_LIST_WIDGET == null) {
|
|
||||||
ENTRY_LIST_WIDGET = LambdaReflection.getFirstFieldOfType(ContainerScreenOverlay.class, EntryListWidget.class)
|
|
||||||
.map(field -> (EntryListWidget) LambdaReflection.getFieldValue(null, field))
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
return ENTRY_LIST_WIDGET;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @Nullable EntryStack getCurrentStack(@NotNull MinecraftClient client) {
|
|
||||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
|
||||||
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
|
||||||
|
|
||||||
if (isViewingScreen(client.currentScreen)) {
|
|
||||||
for (Element element : client.currentScreen.children()) {
|
|
||||||
EntryStack stack = getCurrentStack(element, x, y);
|
|
||||||
if (stack != null)
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
|
|
||||||
if (!overlay.isPresent())
|
|
||||||
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
|
||||||
EntryListWidget widget = getEntryListWidget();
|
|
||||||
if (widget == null)
|
|
||||||
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
|
||||||
|
|
||||||
return getCurrentStack(widget, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @Nullable EntryStack getCurrentStack(@NotNull Element element, double mouseX, double mouseY) {
|
|
||||||
if (element instanceof EntryWidget) {
|
|
||||||
EntryWidget entry = (EntryWidget) element;
|
|
||||||
if (entry.containsMouse(mouseX, mouseY))
|
|
||||||
return ((EntryWidgetAccessor) entry).lambdacontrols_getCurrentEntry();
|
|
||||||
} else if (element instanceof EntryListWidget) {
|
|
||||||
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
|
|
||||||
for (EntryListEntryWidget entry : entries) {
|
|
||||||
if (entry.containsMouse(mouseX, mouseY)) {
|
|
||||||
return ((EntryWidgetAccessor) entry).lambdacontrols_getCurrentEntry();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds) {
|
|
||||||
for (Element child : ((WidgetWithBounds) element).children()) {
|
|
||||||
EntryStack stack = getCurrentStack(child, mouseX, mouseY);
|
|
||||||
if (stack != null)
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PressAction handleShowRecipeUsage(boolean usage) {
|
|
||||||
return (client, button, value, action) -> {
|
|
||||||
if (action.isUnpressed())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
EntryStack stack = RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
|
||||||
if (stack == null) {
|
|
||||||
stack = getCurrentStack(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stack != null && !stack.isEmpty()) {
|
|
||||||
stack = stack.copy();
|
|
||||||
if (usage) {
|
|
||||||
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addUsagesFor(stack).setInputNotice(stack).fillPreferredOpenedCategory());
|
|
||||||
} else {
|
|
||||||
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addRecipesFor(stack).setOutputNotice(stack).fillPreferredOpenedCategory());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PressAction handlePage(boolean next) {
|
|
||||||
return (client, button, value, action) -> {
|
|
||||||
if (action == ButtonState.RELEASE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
|
|
||||||
if (!overlay.isPresent())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
EntryListWidget widget = getEntryListWidget();
|
|
||||||
if (widget == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (next)
|
|
||||||
widget.nextPage();
|
|
||||||
else
|
|
||||||
widget.previousPage();
|
|
||||||
widget.updateEntriesPosition();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the handler for category tabs buttons.
|
|
||||||
*
|
|
||||||
* @param next True if the action is to switch to the next tab.
|
|
||||||
* @return The handler.
|
|
||||||
*/
|
|
||||||
private static PressAction handleTab(boolean next) {
|
|
||||||
return (client, button, value, action) -> {
|
|
||||||
if (action != ButtonState.RELEASE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (client.currentScreen instanceof RecipeViewingScreen) {
|
|
||||||
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
|
|
||||||
if (next)
|
|
||||||
screen.getCategoryNext().onClick();
|
|
||||||
else
|
|
||||||
screen.getCategoryBack().onClick();
|
|
||||||
return true;
|
|
||||||
} else if (client.currentScreen instanceof VillagerRecipeViewingScreen) {
|
|
||||||
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
|
|
||||||
List<RecipeCategory<?>> categories = screen.getCategories();
|
|
||||||
int currentTab = screen.getSelectedCategoryIndex();
|
|
||||||
screen.setSelectedCategoryIndex(getNextIndex(currentTab, categories.size(), next));
|
|
||||||
screen.setSelectedRecipeIndex(0);
|
|
||||||
screen.lambdacontrols_init();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PressAction handleRecipe(boolean next) {
|
|
||||||
return (client, button, value, action) -> {
|
|
||||||
if (action.isUnpressed())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (client.currentScreen instanceof RecipeViewingScreen) {
|
|
||||||
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
|
|
||||||
if (next)
|
|
||||||
screen.getRecipeNext().onClick();
|
|
||||||
else
|
|
||||||
screen.getRecipeBack().onClick();
|
|
||||||
return true;
|
|
||||||
} else if (client.currentScreen instanceof VillagerRecipeViewingScreen) {
|
|
||||||
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
|
|
||||||
List<RecipeCategory<?>> categories = screen.getCategories();
|
|
||||||
int currentTab = screen.getSelectedCategoryIndex();
|
|
||||||
List<RecipeDisplay> recipes = screen.getCategoryMap().get(categories.get(currentTab));
|
|
||||||
|
|
||||||
if (recipes.size() == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
int currentRecipe = screen.getSelectedRecipeIndex();
|
|
||||||
int nextRecipe = getNextIndex(currentRecipe, recipes.size(), next);
|
|
||||||
|
|
||||||
if (nextRecipe == 0) {
|
|
||||||
screen.getScrolling().scrollTo(0.0, true);
|
|
||||||
} else if (nextRecipe == recipes.size() - 1) {
|
|
||||||
screen.getScrolling().scrollTo(screen.getScrolling().getMaxScroll(), true);
|
|
||||||
} else {
|
|
||||||
double scrollAmount = screen.getScrolling().getMaxScroll() / (float) recipes.size();
|
|
||||||
screen.getScrolling().offset(next ? scrollAmount : -scrollAmount, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
screen.setSelectedRecipeIndex(nextRecipe);
|
|
||||||
screen.lambdacontrols_init();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getNextIndex(int currentIndex, int size, boolean next) {
|
|
||||||
int nextIndex = currentIndex + (next ? 1 : -1);
|
|
||||||
if (nextIndex < 0)
|
|
||||||
nextIndex = size - 1;
|
|
||||||
else if (nextIndex >= size)
|
|
||||||
nextIndex = 0;
|
|
||||||
return nextIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat.mixin;
|
|
||||||
|
|
||||||
import me.shedaniel.rei.gui.widget.EntryListEntryWidget;
|
|
||||||
import me.shedaniel.rei.gui.widget.EntryListWidget;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an accessor to REI's EntryListWidget.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.5.0
|
|
||||||
* @since 1.5.0
|
|
||||||
*/
|
|
||||||
@Mixin(value = EntryListWidget.class, remap = false)
|
|
||||||
public interface EntryListWidgetAccessor {
|
|
||||||
@Accessor(value = "entries")
|
|
||||||
List<EntryListEntryWidget> getEntries();
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat.mixin;
|
|
||||||
|
|
||||||
import me.shedaniel.rei.api.EntryStack;
|
|
||||||
import me.shedaniel.rei.gui.widget.EntryWidget;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an accessor to REI's EntryWidget.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.5.0
|
|
||||||
* @since 1.5.0
|
|
||||||
*/
|
|
||||||
@Mixin(value = EntryWidget.class, remap = false)
|
|
||||||
public interface EntryWidgetAccessor {
|
|
||||||
@Invoker("getCurrentEntry")
|
|
||||||
EntryStack lambdacontrols_getCurrentEntry();
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat.mixin;
|
|
||||||
|
|
||||||
import me.shedaniel.rei.api.widgets.Button;
|
|
||||||
import me.shedaniel.rei.gui.RecipeViewingScreen;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an accessor to REI's RecipeViewingScreen.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.5.0
|
|
||||||
* @since 1.2.0
|
|
||||||
*/
|
|
||||||
@Mixin(value = RecipeViewingScreen.class, remap = false)
|
|
||||||
public interface RecipeViewingScreenAccessor {
|
|
||||||
@Accessor("categoryBack")
|
|
||||||
Button getCategoryBack();
|
|
||||||
|
|
||||||
@Accessor("categoryNext")
|
|
||||||
Button getCategoryNext();
|
|
||||||
|
|
||||||
@Accessor("recipeBack")
|
|
||||||
Button getRecipeBack();
|
|
||||||
|
|
||||||
@Accessor("recipeNext")
|
|
||||||
Button getRecipeNext();
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat.mixin;
|
|
||||||
|
|
||||||
import me.shedaniel.clothconfig2.api.ScrollingContainer;
|
|
||||||
import me.shedaniel.rei.api.RecipeCategory;
|
|
||||||
import me.shedaniel.rei.api.RecipeDisplay;
|
|
||||||
import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an accessor to REI's VillagerRecipeViewingScreen.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.5.0
|
|
||||||
* @since 1.2.0
|
|
||||||
*/
|
|
||||||
@Mixin(VillagerRecipeViewingScreen.class)
|
|
||||||
public interface VillagerRecipeViewingScreenAccessor {
|
|
||||||
@Accessor(value = "categoryMap", remap = false)
|
|
||||||
Map<RecipeCategory<?>, List<RecipeDisplay>> getCategoryMap();
|
|
||||||
|
|
||||||
@Accessor(value = "categories", remap = false)
|
|
||||||
List<RecipeCategory<?>> getCategories();
|
|
||||||
|
|
||||||
@Accessor(value = "selectedCategoryIndex", remap = false)
|
|
||||||
int getSelectedCategoryIndex();
|
|
||||||
|
|
||||||
@Accessor(value = "selectedCategoryIndex", remap = false)
|
|
||||||
void setSelectedCategoryIndex(int selectedCategoryIndex);
|
|
||||||
|
|
||||||
@Accessor(value = "selectedRecipeIndex", remap = false)
|
|
||||||
int getSelectedRecipeIndex();
|
|
||||||
|
|
||||||
@Accessor(value = "selectedRecipeIndex", remap = false)
|
|
||||||
void setSelectedRecipeIndex(int selectedRecipeIndex);
|
|
||||||
|
|
||||||
@Accessor(value = "scrolling", remap = false)
|
|
||||||
ScrollingContainer getScrolling();
|
|
||||||
|
|
||||||
@Invoker("init")
|
|
||||||
void lambdacontrols_init();
|
|
||||||
}
|
|
||||||
@@ -1,396 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControls;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.widget.ControllerControlsWidget;
|
|
||||||
import me.lambdaurora.spruceui.Position;
|
|
||||||
import me.lambdaurora.spruceui.SpruceTexts;
|
|
||||||
import me.lambdaurora.spruceui.option.*;
|
|
||||||
import me.lambdaurora.spruceui.screen.SpruceScreen;
|
|
||||||
import me.lambdaurora.spruceui.widget.AbstractSpruceWidget;
|
|
||||||
import me.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
|
||||||
import me.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
|
||||||
import me.lambdaurora.spruceui.widget.container.SpruceOptionListWidget;
|
|
||||||
import me.lambdaurora.spruceui.widget.container.tabbed.SpruceTabbedWidget;
|
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
|
||||||
import net.minecraft.client.resource.language.I18n;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.text.LiteralText;
|
|
||||||
import net.minecraft.text.MutableText;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import net.minecraft.util.Formatting;
|
|
||||||
import net.minecraft.util.Util;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the LambdaControls settings screen.
|
|
||||||
*/
|
|
||||||
public class LambdaControlsSettingsScreen extends SpruceScreen {
|
|
||||||
private static final Text SDL2_GAMEPAD_TOOL = new LiteralText("SDL2 Gamepad Tool").formatted(Formatting.GREEN);
|
|
||||||
public static final String GAMEPAD_TOOL_URL = "https://generalarcade.com/gamepadtool/";
|
|
||||||
final LambdaControlsClient mod = LambdaControlsClient.get();
|
|
||||||
private final LambdaControlsConfig config = this.mod.config;
|
|
||||||
private final Screen parent;
|
|
||||||
// General options
|
|
||||||
private final SpruceOption inputModeOption;
|
|
||||||
private final SpruceOption autoSwitchModeOption;
|
|
||||||
private final SpruceOption rotationSpeedOption;
|
|
||||||
private final SpruceOption mouseSpeedOption;
|
|
||||||
private final SpruceOption virtualMouseOption;
|
|
||||||
private final SpruceOption resetOption;
|
|
||||||
// Gameplay options
|
|
||||||
private final SpruceOption analogMovementOption;
|
|
||||||
private final SpruceOption autoJumpOption;
|
|
||||||
private final SpruceOption fastBlockPlacingOption;
|
|
||||||
private final SpruceOption frontBlockPlacingOption;
|
|
||||||
private final SpruceOption verticalReacharoundOption;
|
|
||||||
private final SpruceOption flyDriftingOption;
|
|
||||||
private final SpruceOption flyVerticalDriftingOption;
|
|
||||||
// Appearance options
|
|
||||||
private final SpruceOption controllerTypeOption;
|
|
||||||
private final SpruceOption virtualMouseSkinOption;
|
|
||||||
private final SpruceOption hudEnableOption;
|
|
||||||
private final SpruceOption hudSideOption;
|
|
||||||
// Controller options
|
|
||||||
private final SpruceOption controllerOption =
|
|
||||||
new SpruceCyclingOption("lambdacontrols.menu.controller",
|
|
||||||
amount -> {
|
|
||||||
int id = this.config.getController().getId();
|
|
||||||
id += amount;
|
|
||||||
if (id > GLFW.GLFW_JOYSTICK_LAST)
|
|
||||||
id = GLFW.GLFW_JOYSTICK_1;
|
|
||||||
id = searchNextAvailableController(id, false);
|
|
||||||
this.config.setController(Controller.byId(id));
|
|
||||||
},
|
|
||||||
option -> {
|
|
||||||
Controller controller = this.config.getController();
|
|
||||||
String controllerName = controller.getName();
|
|
||||||
if (!controller.isConnected())
|
|
||||||
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.RED));
|
|
||||||
else if (!controller.isGamepad())
|
|
||||||
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.GOLD));
|
|
||||||
else
|
|
||||||
return option.getDisplayText(new LiteralText(controllerName));
|
|
||||||
}, null);
|
|
||||||
private final SpruceOption secondControllerOption = new SpruceCyclingOption("lambdacontrols.menu.controller2",
|
|
||||||
amount -> {
|
|
||||||
int id = this.config.getSecondController().map(Controller::getId).orElse(-1);
|
|
||||||
id += amount;
|
|
||||||
if (id > GLFW.GLFW_JOYSTICK_LAST)
|
|
||||||
id = -1;
|
|
||||||
id = searchNextAvailableController(id, true);
|
|
||||||
this.config.setSecondController(id == -1 ? null : Controller.byId(id));
|
|
||||||
},
|
|
||||||
option -> this.config.getSecondController().map(controller -> {
|
|
||||||
String controllerName = controller.getName();
|
|
||||||
if (!controller.isConnected())
|
|
||||||
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.RED));
|
|
||||||
else if (!controller.isGamepad())
|
|
||||||
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.GOLD));
|
|
||||||
else
|
|
||||||
return option.getDisplayText(new LiteralText(controllerName));
|
|
||||||
}).orElse(option.getDisplayText(SpruceTexts.OPTIONS_OFF.shallowCopy().formatted(Formatting.RED))),
|
|
||||||
new TranslatableText("lambdacontrols.tooltip.controller2"));
|
|
||||||
private final SpruceOption unfocusedInputOption;
|
|
||||||
private final SpruceOption invertsRightXAxis;
|
|
||||||
private final SpruceOption invertsRightYAxis;
|
|
||||||
private final SpruceOption rightDeadZoneOption;
|
|
||||||
private final SpruceOption leftDeadZoneOption;
|
|
||||||
private final SpruceOption[] maxAnalogValueOptions = new SpruceOption[]{
|
|
||||||
maxAnalogValueOption(this.config, "lambdacontrols.menu.max_left_x_value", GLFW.GLFW_GAMEPAD_AXIS_LEFT_X),
|
|
||||||
maxAnalogValueOption(this.config, "lambdacontrols.menu.max_left_y_value", GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y),
|
|
||||||
maxAnalogValueOption(this.config, "lambdacontrols.menu.max_right_x_value", GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X),
|
|
||||||
maxAnalogValueOption(this.config, "lambdacontrols.menu.max_right_y_value", GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y)
|
|
||||||
};
|
|
||||||
|
|
||||||
private static SpruceOption maxAnalogValueOption(LambdaControlsConfig config, String key, int axis) {
|
|
||||||
return new SpruceDoubleOption(key, .25f, 1.f, 0.05f,
|
|
||||||
() -> config.getAxisMaxValue(axis),
|
|
||||||
newValue -> config.setAxisMaxValue(axis, newValue),
|
|
||||||
option -> option.getDisplayText(new LiteralText(String.format("%.2f", option.get()))),
|
|
||||||
new TranslatableText(key.replace("menu", "tooltip"))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final MutableText controllerMappingsUrlText = new LiteralText("(")
|
|
||||||
.append(new LiteralText(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
|
|
||||||
.append("),");
|
|
||||||
|
|
||||||
private static int searchNextAvailableController(int newId, boolean allowNone) {
|
|
||||||
if ((allowNone && newId == -1) || newId == 0) return newId;
|
|
||||||
|
|
||||||
boolean connected = Controller.byId(newId).isConnected();
|
|
||||||
if (!connected) {
|
|
||||||
newId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newId > GLFW.GLFW_JOYSTICK_LAST)
|
|
||||||
newId = allowNone ? -1 : GLFW.GLFW_JOYSTICK_1;
|
|
||||||
|
|
||||||
return connected ? newId : searchNextAvailableController(newId, allowNone);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LambdaControlsSettingsScreen(Screen parent, boolean hideControls) {
|
|
||||||
super(new TranslatableText("lambdacontrols.title.settings"));
|
|
||||||
this.parent = parent;
|
|
||||||
// General options
|
|
||||||
this.inputModeOption = new SpruceCyclingOption("lambdacontrols.menu.controls_mode",
|
|
||||||
amount -> {
|
|
||||||
ControlsMode next = this.config.getControlsMode().next();
|
|
||||||
this.config.setControlsMode(next);
|
|
||||||
this.config.save();
|
|
||||||
|
|
||||||
if (this.client.player != null) {
|
|
||||||
ClientPlayNetworking.getSender().sendPacket(LambdaControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next));
|
|
||||||
}
|
|
||||||
}, option -> option.getDisplayText(new TranslatableText(this.config.getControlsMode().getTranslationKey())),
|
|
||||||
new TranslatableText("lambdacontrols.tooltip.controls_mode"));
|
|
||||||
this.autoSwitchModeOption = new SpruceToggleBooleanOption("lambdacontrols.menu.auto_switch_mode", this.config::hasAutoSwitchMode,
|
|
||||||
this.config::setAutoSwitchMode, new TranslatableText("lambdacontrols.tooltip.auto_switch_mode"));
|
|
||||||
this.rotationSpeedOption = new SpruceDoubleOption("lambdacontrols.menu.rotation_speed", 0.0, 100.0, .5f,
|
|
||||||
this.config::getRotationSpeed,
|
|
||||||
newValue -> {
|
|
||||||
synchronized (this.config) {
|
|
||||||
this.config.setRotationSpeed(newValue);
|
|
||||||
}
|
|
||||||
}, option -> option.getDisplayText(new LiteralText(String.valueOf(option.get()))),
|
|
||||||
new TranslatableText("lambdacontrols.tooltip.rotation_speed"));
|
|
||||||
this.mouseSpeedOption = new SpruceDoubleOption("lambdacontrols.menu.mouse_speed", 0.0, 150.0, .5f,
|
|
||||||
this.config::getMouseSpeed,
|
|
||||||
newValue -> {
|
|
||||||
synchronized (this.config) {
|
|
||||||
this.config.setMouseSpeed(newValue);
|
|
||||||
}
|
|
||||||
}, option -> option.getDisplayText(new LiteralText(String.valueOf(option.get()))),
|
|
||||||
new TranslatableText("lambdacontrols.tooltip.mouse_speed"));
|
|
||||||
this.resetOption = SpruceSimpleActionOption.reset(btn -> {
|
|
||||||
this.config.reset();
|
|
||||||
MinecraftClient client = MinecraftClient.getInstance();
|
|
||||||
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
|
||||||
});
|
|
||||||
// Gameplay options
|
|
||||||
this.analogMovementOption = new SpruceToggleBooleanOption("lambdacontrols.menu.analog_movement",
|
|
||||||
this.config::hasAnalogMovement, this.config::setAnalogMovement,
|
|
||||||
new TranslatableText("lambdacontrols.tooltip.analog_movement"));
|
|
||||||
this.autoJumpOption = new SpruceToggleBooleanOption("options.autoJump",
|
|
||||||
() -> this.client.options.autoJump,
|
|
||||||
newValue -> this.client.options.autoJump = newValue,
|
|
||||||
null);
|
|
||||||
this.fastBlockPlacingOption = new SpruceToggleBooleanOption("lambdacontrols.menu.fast_block_placing", this.config::hasFastBlockPlacing,
|
|
||||||
this.config::setFastBlockPlacing, new TranslatableText("lambdacontrols.tooltip.fast_block_placing"));
|
|
||||||
this.frontBlockPlacingOption = new SpruceToggleBooleanOption("lambdacontrols.menu.reacharound.horizontal", this.config::hasFrontBlockPlacing,
|
|
||||||
this.config::setFrontBlockPlacing, new TranslatableText("lambdacontrols.tooltip.reacharound.horizontal"));
|
|
||||||
this.verticalReacharoundOption = new SpruceToggleBooleanOption("lambdacontrols.menu.reacharound.vertical", this.config::hasVerticalReacharound,
|
|
||||||
this.config::setVerticalReacharound, new TranslatableText("lambdacontrols.tooltip.reacharound.vertical"));
|
|
||||||
this.flyDriftingOption = new SpruceToggleBooleanOption("lambdacontrols.menu.fly_drifting", this.config::hasFlyDrifting,
|
|
||||||
this.config::setFlyDrifting, new TranslatableText("lambdacontrols.tooltip.fly_drifting"));
|
|
||||||
this.flyVerticalDriftingOption = new SpruceToggleBooleanOption("lambdacontrols.menu.fly_drifting_vertical", this.config::hasFlyVerticalDrifting,
|
|
||||||
this.config::setFlyVerticalDrifting, new TranslatableText("lambdacontrols.tooltip.fly_drifting_vertical"));
|
|
||||||
// Appearance options
|
|
||||||
this.controllerTypeOption = new SpruceCyclingOption("lambdacontrols.menu.controller_type",
|
|
||||||
amount -> this.config.setControllerType(this.config.getControllerType().next()),
|
|
||||||
option -> option.getDisplayText(this.config.getControllerType().getTranslatedText()),
|
|
||||||
new TranslatableText("lambdacontrols.tooltip.controller_type"));
|
|
||||||
this.virtualMouseSkinOption = new SpruceCyclingOption("lambdacontrols.menu.virtual_mouse.skin",
|
|
||||||
amount -> this.config.setVirtualMouseSkin(this.config.getVirtualMouseSkin().next()),
|
|
||||||
option -> option.getDisplayText(this.config.getVirtualMouseSkin().getTranslatedText()),
|
|
||||||
null);
|
|
||||||
this.hudEnableOption = new SpruceToggleBooleanOption("lambdacontrols.menu.hud_enable", this.config::isHudEnabled,
|
|
||||||
this.mod::setHudEnabled, new TranslatableText("lambdacontrols.tooltip.hud_enable"));
|
|
||||||
this.hudSideOption = new SpruceCyclingOption("lambdacontrols.menu.hud_side",
|
|
||||||
amount -> this.config.setHudSide(this.config.getHudSide().next()),
|
|
||||||
option -> option.getDisplayText(this.config.getHudSide().getTranslatedText()),
|
|
||||||
new TranslatableText("lambdacontrols.tooltip.hud_side"));
|
|
||||||
// Controller options
|
|
||||||
this.rightDeadZoneOption = new SpruceDoubleOption("lambdacontrols.menu.right_dead_zone", 0.05, 1.0, .05f,
|
|
||||||
this.config::getRightDeadZone,
|
|
||||||
newValue -> {
|
|
||||||
synchronized (this.config) {
|
|
||||||
this.config.setRightDeadZone(newValue);
|
|
||||||
}
|
|
||||||
}, option -> {
|
|
||||||
String value = String.valueOf(option.get());
|
|
||||||
return option.getDisplayText(new LiteralText(value.substring(0, Math.min(value.length(), 5))));
|
|
||||||
}, new TranslatableText("lambdacontrols.tooltip.right_dead_zone"));
|
|
||||||
this.leftDeadZoneOption = new SpruceDoubleOption("lambdacontrols.menu.left_dead_zone", 0.05, 1.0, .05f,
|
|
||||||
this.config::getLeftDeadZone,
|
|
||||||
newValue -> {
|
|
||||||
synchronized (this.config) {
|
|
||||||
this.config.setLeftDeadZone(newValue);
|
|
||||||
}
|
|
||||||
}, option -> {
|
|
||||||
String value = String.valueOf(option.get());
|
|
||||||
return option.getDisplayText(new LiteralText(value.substring(0, Math.min(value.length(), 5))));
|
|
||||||
}, new TranslatableText("lambdacontrols.tooltip.left_dead_zone"));
|
|
||||||
this.invertsRightXAxis = new SpruceToggleBooleanOption("lambdacontrols.menu.invert_right_x_axis", this.config::doesInvertRightXAxis,
|
|
||||||
newValue -> {
|
|
||||||
synchronized (this.config) {
|
|
||||||
this.config.setInvertRightXAxis(newValue);
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
this.invertsRightYAxis = new SpruceToggleBooleanOption("lambdacontrols.menu.invert_right_y_axis", this.config::doesInvertRightYAxis,
|
|
||||||
newValue -> {
|
|
||||||
synchronized (this.config) {
|
|
||||||
this.config.setInvertRightYAxis(newValue);
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
this.unfocusedInputOption = new SpruceToggleBooleanOption("lambdacontrols.menu.unfocused_input", this.config::hasUnfocusedInput,
|
|
||||||
this.config::setUnfocusedInput, new TranslatableText("lambdacontrols.tooltip.unfocused_input"));
|
|
||||||
this.virtualMouseOption = new SpruceToggleBooleanOption("lambdacontrols.menu.virtual_mouse", this.config::hasVirtualMouse,
|
|
||||||
this.config::setVirtualMouse, new TranslatableText("lambdacontrols.tooltip.virtual_mouse"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removed() {
|
|
||||||
this.config.save();
|
|
||||||
super.removed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClose() {
|
|
||||||
this.config.save();
|
|
||||||
super.onClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTextHeight() {
|
|
||||||
return (5 + this.textRenderer.fontHeight) * 3 + 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void init() {
|
|
||||||
super.init();
|
|
||||||
|
|
||||||
this.buildTabs();
|
|
||||||
|
|
||||||
this.addChild(this.resetOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 150));
|
|
||||||
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, 20, SpruceTexts.GUI_DONE,
|
|
||||||
btn -> this.client.openScreen(this.parent)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void buildTabs() {
|
|
||||||
SpruceTabbedWidget tabs = new SpruceTabbedWidget(Position.of(0, 24), this.width, this.height - 32 - 24,
|
|
||||||
null,
|
|
||||||
Math.max(116, this.width / 8), 0);
|
|
||||||
this.addChild(tabs);
|
|
||||||
|
|
||||||
tabs.addSeparatorEntry(new TranslatableText("lambdacontrols.menu.separator.general"));
|
|
||||||
tabs.addTabEntry(new TranslatableText("lambdacontrols.menu.title.general"), null,
|
|
||||||
this::buildGeneralTab);
|
|
||||||
tabs.addTabEntry(new TranslatableText("lambdacontrols.menu.title.gameplay"), null,
|
|
||||||
this::buildGameplayTab);
|
|
||||||
tabs.addTabEntry(new TranslatableText("lambdacontrols.menu.title.visual"), null,
|
|
||||||
this::buildVisualTab);
|
|
||||||
|
|
||||||
tabs.addSeparatorEntry(new TranslatableText("options.controls"));
|
|
||||||
tabs.addTabEntry(new TranslatableText("lambdacontrols.menu.title.controller_controls"), null,
|
|
||||||
this::buildControllerControlsTab);
|
|
||||||
|
|
||||||
tabs.addSeparatorEntry(new TranslatableText("lambdacontrols.menu.separator.controller"));
|
|
||||||
tabs.addTabEntry(new TranslatableText("lambdacontrols.menu.title.controller"), null,
|
|
||||||
this::buildControllerTab);
|
|
||||||
tabs.addTabEntry(new TranslatableText("lambdacontrols.menu.title.mappings.string"), null,
|
|
||||||
this::buildMappingsStringEditorTab);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpruceOptionListWidget buildGeneralTab(int width, int height) {
|
|
||||||
SpruceOptionListWidget list = new SpruceOptionListWidget(Position.origin(), width, height);
|
|
||||||
list.addSingleOptionEntry(this.inputModeOption);
|
|
||||||
list.addSingleOptionEntry(this.autoSwitchModeOption);
|
|
||||||
list.addSingleOptionEntry(this.rotationSpeedOption);
|
|
||||||
list.addSingleOptionEntry(this.mouseSpeedOption);
|
|
||||||
list.addSingleOptionEntry(this.virtualMouseOption);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpruceOptionListWidget buildGameplayTab(int width, int height) {
|
|
||||||
SpruceOptionListWidget list = new SpruceOptionListWidget(Position.origin(), width, height);
|
|
||||||
list.addSingleOptionEntry(this.analogMovementOption);
|
|
||||||
list.addSingleOptionEntry(this.fastBlockPlacingOption);
|
|
||||||
list.addSingleOptionEntry(this.frontBlockPlacingOption);
|
|
||||||
list.addSingleOptionEntry(this.verticalReacharoundOption);
|
|
||||||
list.addSingleOptionEntry(this.flyDriftingOption);
|
|
||||||
list.addSingleOptionEntry(this.flyVerticalDriftingOption);
|
|
||||||
list.addSingleOptionEntry(this.autoJumpOption);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpruceOptionListWidget buildVisualTab(int width, int height) {
|
|
||||||
SpruceOptionListWidget list = new SpruceOptionListWidget(Position.origin(), width, height);
|
|
||||||
list.addSingleOptionEntry(this.controllerTypeOption);
|
|
||||||
list.addSingleOptionEntry(this.virtualMouseSkinOption);
|
|
||||||
list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.hud", true, null));
|
|
||||||
list.addSingleOptionEntry(this.hudEnableOption);
|
|
||||||
list.addSingleOptionEntry(this.hudSideOption);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControllerControlsWidget buildControllerControlsTab(int width, int height) {
|
|
||||||
return new ControllerControlsWidget(Position.origin(), width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbstractSpruceWidget buildControllerTab(int width, int height) {
|
|
||||||
SpruceContainerWidget root = new SpruceContainerWidget(Position.origin(), width, height);
|
|
||||||
|
|
||||||
SpruceLabelWidget aboutMappings1 = new SpruceLabelWidget(Position.of(0, 2),
|
|
||||||
new TranslatableText("lambdacontrols.controller.mappings.1", SDL2_GAMEPAD_TOOL),
|
|
||||||
width, true);
|
|
||||||
|
|
||||||
SpruceLabelWidget gamepadToolUrlLabel = new SpruceLabelWidget(Position.of(0, aboutMappings1.getHeight() + 4),
|
|
||||||
this.controllerMappingsUrlText, width,
|
|
||||||
label -> Util.getOperatingSystem().open(GAMEPAD_TOOL_URL), true);
|
|
||||||
gamepadToolUrlLabel.setTooltip(new TranslatableText("chat.link.open"));
|
|
||||||
|
|
||||||
SpruceLabelWidget aboutMappings3 = new SpruceLabelWidget(Position.of(0,
|
|
||||||
aboutMappings1.getHeight() + gamepadToolUrlLabel.getHeight() + 6),
|
|
||||||
new TranslatableText("lambdacontrols.controller.mappings.3", Formatting.GREEN.toString(), Formatting.RESET.toString()),
|
|
||||||
width, true);
|
|
||||||
|
|
||||||
int listHeight = height - 8 - aboutMappings1.getHeight() - aboutMappings3.getHeight() - gamepadToolUrlLabel.getHeight();
|
|
||||||
SpruceContainerWidget labels = new SpruceContainerWidget(Position.of(0,
|
|
||||||
listHeight),
|
|
||||||
width, height - listHeight);
|
|
||||||
labels.addChild(aboutMappings1);
|
|
||||||
labels.addChild(gamepadToolUrlLabel);
|
|
||||||
labels.addChild(aboutMappings3);
|
|
||||||
|
|
||||||
SpruceOptionListWidget list = new SpruceOptionListWidget(Position.origin(), width, listHeight);
|
|
||||||
list.addSingleOptionEntry(this.controllerOption);
|
|
||||||
list.addSingleOptionEntry(this.secondControllerOption);
|
|
||||||
list.addSingleOptionEntry(this.unfocusedInputOption);
|
|
||||||
list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
|
|
||||||
list.addSingleOptionEntry(this.rightDeadZoneOption);
|
|
||||||
list.addSingleOptionEntry(this.leftDeadZoneOption);
|
|
||||||
for (SpruceOption option : this.maxAnalogValueOptions) {
|
|
||||||
list.addSingleOptionEntry(option);
|
|
||||||
}
|
|
||||||
|
|
||||||
root.addChild(list);
|
|
||||||
root.addChild(labels);
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpruceContainerWidget buildMappingsStringEditorTab(int width, int height) {
|
|
||||||
return new MappingsStringInputWidget(Position.origin(), width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderTitle(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
|
||||||
drawCenteredString(matrices, this.textRenderer, I18n.translate("lambdacontrols.menu.title"), this.width / 2, 8, 16777215);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,282 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.text.LiteralText;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the touchscreen overlay
|
|
||||||
*/
|
|
||||||
public class TouchscreenOverlay extends Screen {
|
|
||||||
public TouchscreenOverlay(@NotNull LambdaControlsClient mod) {
|
|
||||||
super(new LiteralText("Touchscreen overlay"));
|
|
||||||
}
|
|
||||||
/*public static final Identifier WIDGETS_LOCATION = new Identifier("lambdacontrols", "textures/gui/widgets.png");
|
|
||||||
private LambdaControlsClient mod;
|
|
||||||
private SpruceTexturedButtonWidget jumpButton;
|
|
||||||
private SpruceTexturedButtonWidget flyButton;
|
|
||||||
private SpruceTexturedButtonWidget flyUpButton;
|
|
||||||
private SpruceTexturedButtonWidget flyDownButton;
|
|
||||||
private int flyButtonEnableTicks = 0;
|
|
||||||
private int forwardButtonTick = 0;
|
|
||||||
private SpruceTexturedButtonWidget forwardLeftButton;
|
|
||||||
private SpruceTexturedButtonWidget forwardRightButton;
|
|
||||||
private SpruceTexturedButtonWidget startSneakButton;
|
|
||||||
private SpruceTexturedButtonWidget endSneakButton;
|
|
||||||
|
|
||||||
public TouchscreenOverlay(@NotNull LambdaControlsClient mod)
|
|
||||||
{
|
|
||||||
super(new LiteralText("Touchscreen overlay"));
|
|
||||||
this.mod = mod;
|
|
||||||
this.passEvents = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPauseScreen()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pauseGame(boolean bl)
|
|
||||||
{
|
|
||||||
if (this.client == null)
|
|
||||||
return;
|
|
||||||
boolean bl2 = this.client.isIntegratedServerRunning() && !this.client.getServer().isRemote();
|
|
||||||
if (bl2) {
|
|
||||||
this.client.openScreen(new GameMenuScreen(!bl));
|
|
||||||
this.client.getSoundManager().pauseAll();
|
|
||||||
} else {
|
|
||||||
this.client.openScreen(new GameMenuScreen(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the forward button ticks cooldown.
|
|
||||||
*
|
|
||||||
* @param state The button state.
|
|
||||||
*
|
|
||||||
private void updateForwardButtonsState(boolean state)
|
|
||||||
{
|
|
||||||
if (state)
|
|
||||||
this.forwardButtonTick = -1;
|
|
||||||
else
|
|
||||||
this.forwardButtonTick = 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the jump buttons.
|
|
||||||
*
|
|
||||||
private void updateJumpButtons()
|
|
||||||
{
|
|
||||||
if (this.client == null)
|
|
||||||
return;
|
|
||||||
if (this.client.player.abilities.allowFlying && this.client.player.abilities.flying) {
|
|
||||||
boolean oldStateFly = this.flyButton.visible;
|
|
||||||
this.jumpButton.visible = false;
|
|
||||||
this.flyButton.visible = true;
|
|
||||||
this.flyUpButton.visible = true;
|
|
||||||
this.flyDownButton.visible = true;
|
|
||||||
if (oldStateFly != this.flyButton.visible) {
|
|
||||||
this.flyButtonEnableTicks = 5;
|
|
||||||
this.handleJump(null, false);
|
|
||||||
} else if (this.flyButtonEnableTicks > 0)
|
|
||||||
this.flyButtonEnableTicks--;
|
|
||||||
} else {
|
|
||||||
this.jumpButton.visible = true;
|
|
||||||
this.flyButton.visible = false;
|
|
||||||
this.flyUpButton.visible = false;
|
|
||||||
this.flyDownButton.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the jump button.
|
|
||||||
*
|
|
||||||
* @param btn The pressed button.
|
|
||||||
* @param state The state of the jump button.
|
|
||||||
*
|
|
||||||
private void handleJump(ButtonWidget btn, boolean state)
|
|
||||||
{
|
|
||||||
((KeyBindingAccessor) this.client.options.keyJump).lambdacontrols_handlePressState(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick()
|
|
||||||
{
|
|
||||||
if (this.forwardButtonTick > 0) {
|
|
||||||
this.forwardButtonTick--;
|
|
||||||
} else if (this.forwardButtonTick == 0) {
|
|
||||||
if (this.forwardLeftButton.visible)
|
|
||||||
this.forwardLeftButton.visible = false;
|
|
||||||
if (this.forwardRightButton.visible)
|
|
||||||
this.forwardRightButton.visible = false;
|
|
||||||
}
|
|
||||||
this.updateJumpButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void init()
|
|
||||||
{
|
|
||||||
super.init();
|
|
||||||
int scaledWidth = this.client.getWindow().getScaledWidth();
|
|
||||||
int scaledHeight = this.client.getWindow().getScaledHeight();
|
|
||||||
this.addButton(new TexturedButtonWidget(scaledWidth / 2 - 20, 0, 20, 20, 0, 106, 20, ButtonWidget.WIDGETS_LOCATION, 256, 256,
|
|
||||||
btn -> this.client.openScreen(new ChatScreen("")), LiteralText.EMPTY));
|
|
||||||
this.addButton(new TexturedButtonWidget(scaledWidth / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256,
|
|
||||||
btn -> this.pauseGame(false)));
|
|
||||||
// Inventory buttons.
|
|
||||||
int inventoryButtonX = scaledWidth / 2;
|
|
||||||
int inventoryButtonY = scaledHeight - 16 - 5;
|
|
||||||
if (this.client.options.mainArm == Arm.LEFT) {
|
|
||||||
inventoryButtonX = inventoryButtonX - 91 - 24;
|
|
||||||
} else {
|
|
||||||
inventoryButtonX = inventoryButtonX + 91 + 4;
|
|
||||||
}
|
|
||||||
this.addButton(new TexturedButtonWidget(inventoryButtonX, inventoryButtonY, 20, 20, 20, 0, 20, WIDGETS_LOCATION, 256, 256,
|
|
||||||
btn -> {
|
|
||||||
if (this.client.interactionManager.hasRidingInventory()) {
|
|
||||||
this.client.player.openRidingInventory();
|
|
||||||
} else {
|
|
||||||
this.client.getTutorialManager().onInventoryOpened();
|
|
||||||
this.client.openScreen(new InventoryScreen(this.client.player));
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
int jumpButtonX, swapHandsX, sneakButtonX;
|
|
||||||
int sneakButtonY = scaledHeight - 10 - 40 - 5;
|
|
||||||
if (this.mod.config.getHudSide() == HudSide.LEFT) {
|
|
||||||
jumpButtonX = scaledWidth - 20 - 20;
|
|
||||||
swapHandsX = jumpButtonX - 5 - 40;
|
|
||||||
sneakButtonX = 10 + 20 + 5;
|
|
||||||
} else {
|
|
||||||
jumpButtonX = 20;
|
|
||||||
swapHandsX = jumpButtonX + 5 + 40;
|
|
||||||
sneakButtonX = scaledWidth - 10 - 40 - 5;
|
|
||||||
}
|
|
||||||
// Swap items hand.
|
|
||||||
this.addButton(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY, 20, 20, 0, 160, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> {
|
|
||||||
if (state) {
|
|
||||||
if (!this.client.player.isSpectator()) {
|
|
||||||
this.client.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
// Drop
|
|
||||||
this.addButton(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY + 5 + 20, 20, 20, 20, 160, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> ((KeyBindingAccessor) this.client.options.keyDrop).lambdacontrols_handlePressState(state)));
|
|
||||||
// Jump keys
|
|
||||||
this.addButton(this.jumpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 0, 40, 20, WIDGETS_LOCATION,
|
|
||||||
this::handleJump));
|
|
||||||
this.addButton(this.flyButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 20, 40, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> {
|
|
||||||
if (this.flyButtonEnableTicks == 0) this.client.player.abilities.flying = false;
|
|
||||||
}));
|
|
||||||
this.addButton(this.flyUpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY - 5 - 20, 20, 20, 40, 40, 20, WIDGETS_LOCATION,
|
|
||||||
this::handleJump));
|
|
||||||
this.addButton(this.flyDownButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY + 20 + 5, 20, 20, 60, 40, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> ((KeyBindingAccessor) this.client.options.keySneak).lambdacontrols_handlePressState(state)));
|
|
||||||
this.updateJumpButtons();
|
|
||||||
// Movements keys
|
|
||||||
this.addButton((this.startSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 0, 120, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> {
|
|
||||||
if (state) {
|
|
||||||
((KeyBindingAccessor) this.client.options.keySneak).lambdacontrols_handlePressState(true);
|
|
||||||
this.startSneakButton.visible = false;
|
|
||||||
this.endSneakButton.visible = true;
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
this.addButton((this.endSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 20, 120, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> {
|
|
||||||
if (state) {
|
|
||||||
((KeyBindingAccessor) this.client.options.keySneak).lambdacontrols_handlePressState(false);
|
|
||||||
this.endSneakButton.visible = false;
|
|
||||||
this.startSneakButton.visible = true;
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
this.endSneakButton.visible = false;
|
|
||||||
this.addButton(this.forwardLeftButton = new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20, 20, 20, 80, 80, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> {
|
|
||||||
((KeyBindingAccessor) this.client.options.keyForward).lambdacontrols_handlePressState(state);
|
|
||||||
((KeyBindingAccessor) this.client.options.keyLeft).lambdacontrols_handlePressState(state);
|
|
||||||
this.updateForwardButtonsState(state);
|
|
||||||
}));
|
|
||||||
this.forwardLeftButton.visible = false;
|
|
||||||
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY - 5 - 20, 20, 20, 0, 80, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> {
|
|
||||||
((KeyBindingAccessor) this.client.options.keyForward).lambdacontrols_handlePressState(state);
|
|
||||||
this.updateForwardButtonsState(state);
|
|
||||||
this.forwardLeftButton.visible = true;
|
|
||||||
this.forwardRightButton.visible = true;
|
|
||||||
}));
|
|
||||||
this.addButton(this.forwardRightButton = new SpruceTexturedButtonWidget(sneakButtonX + 20 + 5, sneakButtonY - 5 - 20, 20, 20, 100, 80, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> {
|
|
||||||
((KeyBindingAccessor) this.client.options.keyForward).lambdacontrols_handlePressState(state);
|
|
||||||
((KeyBindingAccessor) this.client.options.keyRight).lambdacontrols_handlePressState(state);
|
|
||||||
this.updateForwardButtonsState(state);
|
|
||||||
}));
|
|
||||||
this.forwardRightButton.visible = true;
|
|
||||||
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX + 20 + 5, sneakButtonY, 20, 20, 20, 80, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> ((KeyBindingAccessor) this.client.options.keyRight).lambdacontrols_handlePressState(state)));
|
|
||||||
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY + 20 + 5, 20, 20, 40, 80, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> ((KeyBindingAccessor) this.client.options.keyBack).lambdacontrols_handlePressState(state)));
|
|
||||||
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY, 20, 20, 60, 80, 20, WIDGETS_LOCATION,
|
|
||||||
(btn, state) -> ((KeyBindingAccessor) this.client.options.keyLeft).lambdacontrols_handlePressState(state)));
|
|
||||||
|
|
||||||
this.buttons.forEach(button -> {
|
|
||||||
if (button instanceof SpruceTexturedButtonWidget) {
|
|
||||||
((SpruceTexturedButtonWidget) button).setSilent(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mouseClicked(double mouseX, double mouseY, int button)
|
|
||||||
{
|
|
||||||
if (mouseY >= (double) (this.height - 22) && this.client != null && this.client.player != null) {
|
|
||||||
int centerX = this.width / 2;
|
|
||||||
if (mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) {
|
|
||||||
for (int slot = 0; slot < 9; ++slot) {
|
|
||||||
int slotX = centerX - 90 + slot * 20 + 2;
|
|
||||||
if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) {
|
|
||||||
this.client.player.inventory.selectedSlot = slot;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.mouseClicked(mouseX, mouseY, button);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY)
|
|
||||||
{
|
|
||||||
if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) {
|
|
||||||
if (deltaY > 0.01)
|
|
||||||
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 2);
|
|
||||||
else if (deltaY < 0.01)
|
|
||||||
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 1);
|
|
||||||
|
|
||||||
if (deltaX > 0.01)
|
|
||||||
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 2);
|
|
||||||
else if (deltaX < 0.01)
|
|
||||||
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 1);
|
|
||||||
}
|
|
||||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
|
|
||||||
import net.minecraft.client.gui.screen.options.GameOptionsScreen;
|
|
||||||
import net.minecraft.client.gui.widget.AbstractButtonWidget;
|
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
|
||||||
import net.minecraft.client.options.GameOptions;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Injects the new controls settings button.
|
|
||||||
*/
|
|
||||||
@Mixin(ControlsOptionsScreen.class)
|
|
||||||
public class ControlsOptionsScreenMixin extends GameOptionsScreen {
|
|
||||||
public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text text) {
|
|
||||||
super(parent, gameOptions, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/ControlsOptionsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 1))
|
|
||||||
private AbstractButtonWidget onInit(ControlsOptionsScreen screen, AbstractButtonWidget btn) {
|
|
||||||
/*if (this.parent instanceof ControllerControlsWidget)
|
|
||||||
return this.addButton(btn);
|
|
||||||
else*/
|
|
||||||
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).getHeight(), new TranslatableText("menu.options"),
|
|
||||||
b -> this.client.openScreen(new LambdaControlsSettingsScreen(this, true))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsRenderer;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.screen.slot.Slot;
|
|
||||||
import net.minecraft.screen.slot.SlotActionType;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the mixin for the class ContainerScreen.
|
|
||||||
*/
|
|
||||||
@Mixin(HandledScreen.class)
|
|
||||||
public abstract class HandledScreenMixin implements HandledScreenAccessor {
|
|
||||||
@Accessor("x")
|
|
||||||
public abstract int getX();
|
|
||||||
|
|
||||||
@Accessor("y")
|
|
||||||
public abstract int getY();
|
|
||||||
|
|
||||||
@Invoker("getSlotAt")
|
|
||||||
public abstract Slot lambdacontrols$getSlotAt(double posX, double posY);
|
|
||||||
|
|
||||||
@Invoker("isClickOutsideBounds")
|
|
||||||
public abstract boolean lambdacontrols$isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button);
|
|
||||||
|
|
||||||
@Invoker("onMouseClick")
|
|
||||||
public abstract void lambdacontrols$onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
|
|
||||||
|
|
||||||
@Inject(method = "render", at = @At("RETURN"))
|
|
||||||
public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
|
||||||
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
|
|
||||||
MinecraftClient client = MinecraftClient.getInstance();
|
|
||||||
int x = 2, y = client.getWindow().getScaledHeight() - 2 - LambdaControlsRenderer.ICON_SIZE;
|
|
||||||
|
|
||||||
x = LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "lambdacontrols.action.pickup_all", true, client) + 2;
|
|
||||||
x = LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_B}, "lambdacontrols.action.exit", true, client) + 2;
|
|
||||||
if (LambdaControlsCompat.isReiPresent()) {
|
|
||||||
x = 2;
|
|
||||||
y -= 24;
|
|
||||||
}
|
|
||||||
x = LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, "lambdacontrols.action.pickup", true, client) + 2;
|
|
||||||
LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, "lambdacontrols.action.quick_move", true, client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.MouseAccessor;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.Mouse;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds extra access to the mouse.
|
|
||||||
*/
|
|
||||||
@Mixin(Mouse.class)
|
|
||||||
public abstract class MouseMixin implements MouseAccessor
|
|
||||||
{
|
|
||||||
@Shadow
|
|
||||||
@Final
|
|
||||||
private MinecraftClient client;
|
|
||||||
|
|
||||||
@Invoker("onCursorPos")
|
|
||||||
public abstract void lambdacontrols$onCursorPos(long window, double x, double y);
|
|
||||||
|
|
||||||
@Inject(method = "method_1605", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/Screen;mouseReleased(DDI)Z"))
|
|
||||||
private void onMouseBackButton(boolean[] result, double mouseX, double mouseY, int button, CallbackInfo ci)
|
|
||||||
{
|
|
||||||
if (!result[0] && button == GLFW.GLFW_MOUSE_BUTTON_4 && this.client.currentScreen != null) {
|
|
||||||
if (LambdaControlsClient.get().input.tryGoBack(this.client.currentScreen)) {
|
|
||||||
result[0] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true)
|
|
||||||
private void isCursorLocked(CallbackInfoReturnable<Boolean> ci)
|
|
||||||
{
|
|
||||||
if (this.client.currentScreen == null) {
|
|
||||||
LambdaControlsConfig config = LambdaControlsClient.get().config;
|
|
||||||
if (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse()) {
|
|
||||||
ci.setReturnValue(true);
|
|
||||||
ci.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
|
|
||||||
private void onCursorLocked(CallbackInfo ci)
|
|
||||||
{
|
|
||||||
LambdaControlsConfig config = LambdaControlsClient.get().config;
|
|
||||||
if (config.getControlsMode() == ControlsMode.TOUCHSCREEN
|
|
||||||
|| (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse()))
|
|
||||||
ci.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.client.gui.screen.options.OptionsScreen;
|
|
||||||
import net.minecraft.client.gui.widget.AbstractButtonWidget;
|
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Injects the new controls settings button.
|
|
||||||
*/
|
|
||||||
@Mixin(OptionsScreen.class)
|
|
||||||
public class OptionsScreenMixin extends Screen {
|
|
||||||
protected OptionsScreenMixin(Text title) {
|
|
||||||
super(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/OptionsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 7))
|
|
||||||
private AbstractButtonWidget lambdacontrols$onInit(OptionsScreen screen, AbstractButtonWidget btn) {
|
|
||||||
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
|
|
||||||
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).getHeight(), btn.getMessage(),
|
|
||||||
b -> this.client.openScreen(new LambdaControlsSettingsScreen(this, false))));
|
|
||||||
} else {
|
|
||||||
return this.addButton(btn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.ring;
|
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.Config;
|
|
||||||
import net.minecraft.client.font.TextRenderer;
|
|
||||||
import net.minecraft.client.gui.DrawableHelper;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a ring page.
|
|
||||||
*
|
|
||||||
* @author LambdAurora
|
|
||||||
* @version 1.5.0
|
|
||||||
* @since 1.4.0
|
|
||||||
*/
|
|
||||||
public class RingPage extends DrawableHelper {
|
|
||||||
public static final RingPage DEFAULT = new RingPage("Default");
|
|
||||||
|
|
||||||
public final String name;
|
|
||||||
private RingAction[] actions = new RingAction[8];
|
|
||||||
|
|
||||||
public RingPage(@NotNull String name) {
|
|
||||||
this.name = name;
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
this.actions[i] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the ring page.
|
|
||||||
*
|
|
||||||
* @param matrices The matrices.
|
|
||||||
* @param width The screen width.
|
|
||||||
* @param height The screen height.
|
|
||||||
* @param mouseX The mouse X-coordinate.
|
|
||||||
* @param mouseY The mouse Y-coordinate.
|
|
||||||
* @param tickDelta The tick delta.
|
|
||||||
*/
|
|
||||||
public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int width, int height, int mouseX, int mouseY, float tickDelta) {
|
|
||||||
int centerX = width / 2;
|
|
||||||
int centerY = height / 2;
|
|
||||||
|
|
||||||
int offset = LambdaRing.ELEMENT_SIZE + (LambdaRing.ELEMENT_SIZE / 2) + 5;
|
|
||||||
|
|
||||||
int y = centerY - offset;
|
|
||||||
int x = centerX - offset;
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
RingAction ringAction = this.actions[i];
|
|
||||||
if (ringAction != null)
|
|
||||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
|
|
||||||
x += 55;
|
|
||||||
}
|
|
||||||
y += 55;
|
|
||||||
x = centerX - offset;
|
|
||||||
for (int i = 3; i < 5; i++) {
|
|
||||||
RingAction ringAction = this.actions[i];
|
|
||||||
if (ringAction != null)
|
|
||||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
|
|
||||||
x += 55 * 2;
|
|
||||||
}
|
|
||||||
y += 55;
|
|
||||||
x = centerX - offset;
|
|
||||||
for (int i = 5; i < 8; i++) {
|
|
||||||
RingAction ringAction = this.actions[i];
|
|
||||||
if (ringAction != null)
|
|
||||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
|
|
||||||
x += 55;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isHovered(int x, int y, int mouseX, int mouseY) {
|
|
||||||
return mouseX >= x && mouseY >= y && mouseX <= x + LambdaRing.ELEMENT_SIZE && mouseY <= y + LambdaRing.ELEMENT_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to parse a ring page configuration.
|
|
||||||
*
|
|
||||||
* @param config The configuration.
|
|
||||||
* @return An optional ring page.
|
|
||||||
*/
|
|
||||||
public static @NotNull Optional<RingPage> parseRingPage(@NotNull Config config) {
|
|
||||||
String name = config.get("name");
|
|
||||||
if (name == null)
|
|
||||||
return Optional.empty();
|
|
||||||
|
|
||||||
RingPage page = new RingPage(name);
|
|
||||||
|
|
||||||
List<Config> actionConfigs = config.get("actions");
|
|
||||||
|
|
||||||
|
|
||||||
return Optional.of(page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.util;
|
|
||||||
|
|
||||||
import net.minecraft.screen.slot.Slot;
|
|
||||||
import net.minecraft.screen.slot.SlotActionType;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an accessor to AbstractContainerScreen.
|
|
||||||
*/
|
|
||||||
public interface HandledScreenAccessor {
|
|
||||||
/**
|
|
||||||
* Gets the left coordinate of the GUI.
|
|
||||||
*
|
|
||||||
* @return The left coordinate of the GUI.
|
|
||||||
*/
|
|
||||||
int getX();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the top coordinate of the GUI.
|
|
||||||
*
|
|
||||||
* @return The top coordinate of the GUI.
|
|
||||||
*/
|
|
||||||
int getY();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the slot at position.
|
|
||||||
*
|
|
||||||
* @param pos_x The X position to check.
|
|
||||||
* @param pos_y The Y position to check.
|
|
||||||
* @return The slot at the specified position.
|
|
||||||
*/
|
|
||||||
Slot lambdacontrols$getSlotAt(double pos_x, double pos_y);
|
|
||||||
|
|
||||||
boolean lambdacontrols$isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a mouse click on the specified slot.
|
|
||||||
*
|
|
||||||
* @param slot The slot instance.
|
|
||||||
* @param slotId The slot id.
|
|
||||||
* @param clickData The click data.
|
|
||||||
* @param actionType The action type.
|
|
||||||
*/
|
|
||||||
void lambdacontrols$onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
||||||
*
|
|
||||||
* This file is part of LambdaControls.
|
|
||||||
*
|
|
||||||
* Licensed under the MIT license. For more information,
|
|
||||||
* see the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a Minecraft keybinding with extra access.
|
|
||||||
*/
|
|
||||||
public interface KeyBindingAccessor {
|
|
||||||
boolean lambdacontrols$press();
|
|
||||||
|
|
||||||
boolean lambdacontrols$unpress();
|
|
||||||
|
|
||||||
default boolean lambdacontrols_handlePressState(boolean pressed) {
|
|
||||||
if (pressed)
|
|
||||||
return this.lambdacontrols$press();
|
|
||||||
else
|
|
||||||
return this.lambdacontrols$unpress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols;
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
import dev.lambdaurora.spruceui.util.Nameable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -19,7 +19,7 @@ import java.util.Optional;
|
|||||||
* Represents the controls mode.
|
* Represents the controls mode.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.1.0
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum ControlsMode implements Nameable {
|
public enum ControlsMode implements Nameable {
|
||||||
@@ -30,10 +30,10 @@ public enum ControlsMode implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the next controls mode available.
|
* Returns the next controls mode available.
|
||||||
*
|
*
|
||||||
* @return The next available controls mode.
|
* @return the next available controls mode
|
||||||
*/
|
*/
|
||||||
public ControlsMode next() {
|
public ControlsMode next() {
|
||||||
ControlsMode[] v = values();
|
var v = values();
|
||||||
if (v.length == this.ordinal() + 1)
|
if (v.length == this.ordinal() + 1)
|
||||||
return v[0];
|
return v[0];
|
||||||
return v[this.ordinal() + 1];
|
return v[this.ordinal() + 1];
|
||||||
@@ -42,11 +42,11 @@ public enum ControlsMode implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the translation key of this controls mode.
|
* Gets the translation key of this controls mode.
|
||||||
*
|
*
|
||||||
* @return The translated key of this controls mode.
|
* @return the translated key of this controls mode
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public String getTranslationKey() {
|
public String getTranslationKey() {
|
||||||
return "lambdacontrols.controls_mode." + this.getName();
|
return "midnightcontrols.controls_mode." + this.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -57,8 +57,8 @@ public enum ControlsMode implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the controls mode from its identifier.
|
* Gets the controls mode from its identifier.
|
||||||
*
|
*
|
||||||
* @param id The identifier of the controls mode.
|
* @param id the identifier of the controls mode
|
||||||
* @return The controls mode if found, else empty.
|
* @return the controls mode if found, else empty
|
||||||
*/
|
*/
|
||||||
public static Optional<ControlsMode> byId(@NotNull String id) {
|
public static Optional<ControlsMode> byId(@NotNull String id) {
|
||||||
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.event.PlayerChangeControlsModeCallback;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.fabricmc.loader.api.ModContainer;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the MidnightControls mod.
|
||||||
|
*
|
||||||
|
* @author LambdAurora & Motschen
|
||||||
|
* @version 1.8.0
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class MidnightControls implements ModInitializer {
|
||||||
|
private static MidnightControls INSTANCE;
|
||||||
|
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(MidnightControlsConstants.CONTROLS_MODE_CHANNEL.toString());
|
||||||
|
public static final Identifier FEATURE_CHANNEL = new Identifier(MidnightControlsConstants.FEATURE_CHANNEL.toString());
|
||||||
|
public static final Identifier HELLO_CHANNEL = new Identifier(MidnightControlsConstants.HELLO_CHANNEL.toString());
|
||||||
|
public static boolean isExtrasLoaded;
|
||||||
|
|
||||||
|
public final Logger logger = LogManager.getLogger("MidnightControls");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitialize() {
|
||||||
|
INSTANCE = this;
|
||||||
|
isExtrasLoaded = FabricLoader.getInstance().isModLoaded("midnightcontrols-extra");
|
||||||
|
this.log("Initializing MidnightControls...");
|
||||||
|
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(HELLO_CHANNEL, (server, player, handler, buf, responseSender) -> {
|
||||||
|
String version = buf.readString(32);
|
||||||
|
ControlsMode.byId(buf.readString(32))
|
||||||
|
.ifPresent(controlsMode -> server
|
||||||
|
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode)));
|
||||||
|
server.execute(() -> {
|
||||||
|
ServerPlayNetworking.send(player, FEATURE_CHANNEL, this.makeFeatureBuffer(MidnightControlsFeature.HORIZONTAL_REACHAROUND));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL,
|
||||||
|
(server, player, handler, buf, responseSender) -> ControlsMode.byId(buf.readString(32))
|
||||||
|
.ifPresent(controlsMode -> server
|
||||||
|
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a message to the terminal.
|
||||||
|
*
|
||||||
|
* @param info the message to print
|
||||||
|
*/
|
||||||
|
public void log(String info) {
|
||||||
|
this.logger.info("[MidnightControls] " + info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a warning to the terminal.
|
||||||
|
*
|
||||||
|
* @param warning the warning to print
|
||||||
|
*/
|
||||||
|
public void warn(String warning) {
|
||||||
|
this.logger.info("[MidnightControls] " + warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a packet byte buffer made for the midnightcontrols:controls_mode plugin message.
|
||||||
|
*
|
||||||
|
* @param controlsMode the controls mode to send
|
||||||
|
* @return the packet byte buffer
|
||||||
|
*/
|
||||||
|
public PacketByteBuf makeControlsModeBuffer(@NotNull ControlsMode controlsMode) {
|
||||||
|
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
|
||||||
|
return new PacketByteBuf(Unpooled.buffer()).writeString(controlsMode.getName(), 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a packet byte buffer made for the midnightcontrols:feature plugin message.
|
||||||
|
*
|
||||||
|
* @param features the features data to send
|
||||||
|
* @return the packet byte buffer
|
||||||
|
*/
|
||||||
|
public PacketByteBuf makeFeatureBuffer(MidnightControlsFeature... features) {
|
||||||
|
if (features.length == 0)
|
||||||
|
throw new IllegalArgumentException("At least one feature must be provided.");
|
||||||
|
var buffer = new PacketByteBuf(Unpooled.buffer());
|
||||||
|
buffer.writeVarInt(features.length);
|
||||||
|
for (var feature : features) {
|
||||||
|
buffer.writeString(feature.getName(), 64);
|
||||||
|
buffer.writeBoolean(feature.isAllowed());
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketByteBuf makeHello(@NotNull ControlsMode controlsMode) {
|
||||||
|
var version = "";
|
||||||
|
Optional<ModContainer> container;
|
||||||
|
if ((container = FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE)).isPresent()) {
|
||||||
|
version = container.get().getMetadata().getVersion().getFriendlyString();
|
||||||
|
}
|
||||||
|
return new PacketByteBuf(Unpooled.buffer()).writeString(version, 32).writeString(controlsMode.getName(), 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the MidnightControls instance.
|
||||||
|
*
|
||||||
|
* @return the MidnightControls instance
|
||||||
|
*/
|
||||||
|
public static MidnightControls get() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols;
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
import org.aperlambda.lambdacommon.Identifier;
|
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the constants used by LambdaControls.
|
* Represents the constants used by MidnightControls.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.1.0
|
* @version 1.1.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class LambdaControlsConstants {
|
public class MidnightControlsConstants {
|
||||||
public static final String NAMESPACE = "lambdacontrols";
|
public static final String NAMESPACE = "midnightcontrols";
|
||||||
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(NAMESPACE, "controls_mode");
|
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(NAMESPACE, "controls_mode");
|
||||||
public static final Identifier FEATURE_CHANNEL = new Identifier(NAMESPACE, "feature");
|
public static final Identifier FEATURE_CHANNEL = new Identifier(NAMESPACE, "feature");
|
||||||
public static final Identifier HELLO_CHANNEL = new Identifier(NAMESPACE, "hello");
|
public static final Identifier HELLO_CHANNEL = new Identifier("lambdacontrols", "hello");
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols;
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
import dev.lambdaurora.spruceui.util.Nameable;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -24,11 +25,11 @@ import java.util.Optional;
|
|||||||
* @version 1.5.0
|
* @version 1.5.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class LambdaControlsFeature implements Nameable {
|
public class MidnightControlsFeature implements Nameable {
|
||||||
private static final List<LambdaControlsFeature> FEATURES = new ArrayList<>();
|
private static final List<MidnightControlsFeature> FEATURES = new ArrayList<>();
|
||||||
public static final LambdaControlsFeature FAST_BLOCK_PLACING = new LambdaControlsFeature("fast_block_placing", true, true);
|
public static final MidnightControlsFeature FAST_BLOCK_PLACING = new MidnightControlsFeature("fast_block_placing", true, MidnightControlsConfig.fastBlockPlacing);
|
||||||
public static final LambdaControlsFeature HORIZONTAL_REACHAROUND = new LambdaControlsFeature("horizontal_reacharound", true, false);
|
public static final MidnightControlsFeature HORIZONTAL_REACHAROUND = new MidnightControlsFeature("horizontal_reacharound", true, MidnightControlsConfig.horizontalReacharound);
|
||||||
public static final LambdaControlsFeature VERTICAL_REACHAROUND = new LambdaControlsFeature("vertical_reacharound", true, false);
|
public static final MidnightControlsFeature VERTICAL_REACHAROUND = new MidnightControlsFeature("vertical_reacharound", true, MidnightControlsConfig.verticalReacharound);
|
||||||
|
|
||||||
private final String key;
|
private final String key;
|
||||||
private final boolean defaultAllowed;
|
private final boolean defaultAllowed;
|
||||||
@@ -36,14 +37,14 @@ public class LambdaControlsFeature implements Nameable {
|
|||||||
private final boolean defaultEnabled;
|
private final boolean defaultEnabled;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
public LambdaControlsFeature(@NotNull String key, boolean allowed, boolean enabled) {
|
public MidnightControlsFeature(@NotNull String key, boolean allowed, boolean enabled) {
|
||||||
Objects.requireNonNull(key, "Feature key cannot be null.");
|
Objects.requireNonNull(key, "Feature key cannot be null.");
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.setAllowed(this.defaultAllowed = allowed);
|
this.setAllowed(this.defaultAllowed = allowed);
|
||||||
this.setEnabled(this.defaultEnabled = enabled);
|
this.setEnabled(this.defaultEnabled = enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LambdaControlsFeature(@NotNull String key) {
|
public MidnightControlsFeature(@NotNull String key) {
|
||||||
this(key, false, false);
|
this(key, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,16 +58,16 @@ public class LambdaControlsFeature implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this feature is allowed.
|
* Returns whether this feature is allowed.
|
||||||
*
|
*
|
||||||
* @return True if this feature is allowed, else false.
|
* @return {@code true} if this feature is allowed, else {@code false}
|
||||||
*/
|
*/
|
||||||
public boolean isAllowed() {
|
public boolean isAllowed() {
|
||||||
return this.allowed;
|
return MidnightControls.isExtrasLoaded && this.allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether this feature is allowed.
|
* Sets whether this feature is allowed.
|
||||||
*
|
*
|
||||||
* @param allowed True if this feature is allowed, else false.
|
* @param allowed {@code true} if this feature is allowed, else {@code false}
|
||||||
*/
|
*/
|
||||||
public void setAllowed(boolean allowed) {
|
public void setAllowed(boolean allowed) {
|
||||||
this.allowed = allowed;
|
this.allowed = allowed;
|
||||||
@@ -82,7 +83,7 @@ public class LambdaControlsFeature implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this feature is enabled.
|
* Returns whether this feature is enabled.
|
||||||
*
|
*
|
||||||
* @return True if this feature is enabled, else false.
|
* @return {@code true} if this feature is enabled, else {@code false}
|
||||||
*/
|
*/
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return this.enabled;
|
return this.enabled;
|
||||||
@@ -91,16 +92,25 @@ public class LambdaControlsFeature implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this feature is enabled.
|
* Returns whether this feature is enabled.
|
||||||
*
|
*
|
||||||
* @param enabled True if this feature is enabled, else false.
|
* @param enabled {@code true} if this feature is enabled, else {@code false}
|
||||||
*/
|
*/
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the enabled values from the config.
|
||||||
|
*/
|
||||||
|
public static void refreshEnabled() {
|
||||||
|
MidnightControlsFeature.VERTICAL_REACHAROUND.setEnabled(MidnightControlsConfig.verticalReacharound);
|
||||||
|
MidnightControlsFeature.FAST_BLOCK_PLACING.setEnabled(MidnightControlsConfig.fastBlockPlacing);
|
||||||
|
MidnightControlsFeature.HORIZONTAL_REACHAROUND.setEnabled(MidnightControlsConfig.horizontalReacharound);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether this feature is available or not.
|
* Returns whether this feature is available or not.
|
||||||
*
|
*
|
||||||
* @return True if this feature is available, else false.
|
* @return {@code true} if this feature is available, else {@code false}
|
||||||
* @see #isAllowed()
|
* @see #isAllowed()
|
||||||
* @see #isEnabled()
|
* @see #isEnabled()
|
||||||
*/
|
*/
|
||||||
@@ -121,7 +131,7 @@ public class LambdaControlsFeature implements Nameable {
|
|||||||
return this.key;
|
return this.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull Optional<LambdaControlsFeature> fromName(@NotNull String key) {
|
public static @NotNull Optional<MidnightControlsFeature> fromName(@NotNull String key) {
|
||||||
Objects.requireNonNull(key, "Cannot find features with a null name.");
|
Objects.requireNonNull(key, "Cannot find features with a null name.");
|
||||||
return FEATURES.parallelStream().filter(feature -> feature.getName().equals(key)).findFirst();
|
return FEATURES.parallelStream().filter(feature -> feature.getName().equals(key)).findFirst();
|
||||||
}
|
}
|
||||||
@@ -130,14 +140,14 @@ public class LambdaControlsFeature implements Nameable {
|
|||||||
* Resets all features to their default values.
|
* Resets all features to their default values.
|
||||||
*/
|
*/
|
||||||
public static void resetAll() {
|
public static void resetAll() {
|
||||||
FEATURES.parallelStream().forEach(LambdaControlsFeature::reset);
|
FEATURES.parallelStream().forEach(MidnightControlsFeature::reset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets all features to allow state.
|
* Resets all features to allow state.
|
||||||
*/
|
*/
|
||||||
public static void resetAllAllowed() {
|
public static void resetAllAllowed() {
|
||||||
FEATURES.parallelStream().forEach(LambdaControlsFeature::resetAllowed);
|
FEATURES.parallelStream().forEach(MidnightControlsFeature::resetAllowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a button state.
|
* Represents a button state.
|
||||||
@@ -31,7 +31,7 @@ public enum ButtonState {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this state is a pressed state.
|
* Returns whether this state is a pressed state.
|
||||||
*
|
*
|
||||||
* @return True if this state is a pressed state, else false.
|
* @return true if this state is a pressed state, else false
|
||||||
*/
|
*/
|
||||||
public boolean isPressed() {
|
public boolean isPressed() {
|
||||||
return this == PRESS || this == REPEAT;
|
return this == PRESS || this == REPEAT;
|
||||||
@@ -40,7 +40,7 @@ public enum ButtonState {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this state is an unpressed state.
|
* Returns whether this state is an unpressed state.
|
||||||
*
|
*
|
||||||
* @return True if this state is an unpressed state, else false.
|
* @return true if this state is an unpressed state, else false
|
||||||
*/
|
*/
|
||||||
public boolean isUnpressed() {
|
public boolean isUnpressed() {
|
||||||
return this == RELEASE || this == NONE;
|
return this == RELEASE || this == NONE;
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
import net.minecraft.text.LiteralText;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||||
@@ -28,18 +27,20 @@ import java.util.Optional;
|
|||||||
public enum ControllerType implements Nameable {
|
public enum ControllerType implements Nameable {
|
||||||
DEFAULT(0),
|
DEFAULT(0),
|
||||||
DUALSHOCK(1),
|
DUALSHOCK(1),
|
||||||
SWITCH(2),
|
DUALSENSE(2),
|
||||||
XBOX_360(3, new LiteralText("Xbox 360")),
|
SWITCH(3),
|
||||||
XBOX(4),
|
XBOX_360(4),
|
||||||
STEAM(5),
|
XBOX(5),
|
||||||
OUYA(6);
|
STEAM_DECK(6),
|
||||||
|
STEAM_CONTROLLER(7),
|
||||||
|
OUYA(8);
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
private final Text text;
|
private final Text text;
|
||||||
|
|
||||||
ControllerType(int id) {
|
ControllerType(int id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.text = new TranslatableText("lambdacontrols.controller_type." + this.getName());
|
this.text = new TranslatableText("midnightcontrols.controller_type." + this.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerType(int id, @NotNull Text text) {
|
ControllerType(int id, @NotNull Text text) {
|
||||||
@@ -50,7 +51,7 @@ public enum ControllerType implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the controller type's identifier.
|
* Returns the controller type's identifier.
|
||||||
*
|
*
|
||||||
* @return The controller type's identifier.
|
* @return the controller type's identifier
|
||||||
*/
|
*/
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
@@ -59,10 +60,10 @@ public enum ControllerType implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the next controller type available.
|
* Returns the next controller type available.
|
||||||
*
|
*
|
||||||
* @return The next available controller type.
|
* @return the next available controller type
|
||||||
*/
|
*/
|
||||||
public @NotNull ControllerType next() {
|
public @NotNull ControllerType next() {
|
||||||
ControllerType[] v = values();
|
var v = values();
|
||||||
if (v.length == this.ordinal() + 1)
|
if (v.length == this.ordinal() + 1)
|
||||||
return v[0];
|
return v[0];
|
||||||
return v[this.ordinal() + 1];
|
return v[this.ordinal() + 1];
|
||||||
@@ -71,7 +72,7 @@ public enum ControllerType implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the translated text of this controller type.
|
* Gets the translated text of this controller type.
|
||||||
*
|
*
|
||||||
* @return The translated text of this controller type.
|
* @return the translated text of this controller type
|
||||||
*/
|
*/
|
||||||
public @NotNull Text getTranslatedText() {
|
public @NotNull Text getTranslatedText() {
|
||||||
return this.text;
|
return this.text;
|
||||||
@@ -85,8 +86,8 @@ public enum ControllerType implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the controller type from its identifier.
|
* Gets the controller type from its identifier.
|
||||||
*
|
*
|
||||||
* @param id The identifier of the controller type.
|
* @param id the identifier of the controller type
|
||||||
* @return The controller type if found, else empty.
|
* @return the controller type if found, else empty
|
||||||
*/
|
*/
|
||||||
public static @NotNull Optional<ControllerType> byId(@NotNull String id) {
|
public static @NotNull Optional<ControllerType> byId(@NotNull String id) {
|
||||||
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
@@ -37,10 +37,10 @@ public enum HudSide implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the next side available.
|
* Returns the next side available.
|
||||||
*
|
*
|
||||||
* @return The next available side.
|
* @return the next available side
|
||||||
*/
|
*/
|
||||||
public @NotNull HudSide next() {
|
public @NotNull HudSide next() {
|
||||||
HudSide[] v = values();
|
var v = values();
|
||||||
if (v.length == this.ordinal() + 1)
|
if (v.length == this.ordinal() + 1)
|
||||||
return v[0];
|
return v[0];
|
||||||
return v[this.ordinal() + 1];
|
return v[this.ordinal() + 1];
|
||||||
@@ -49,16 +49,16 @@ public enum HudSide implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the translation key of this hud side.
|
* Returns the translation key of this hud side.
|
||||||
*
|
*
|
||||||
* @return The translation key of this hude side.
|
* @return the translation key of this hude side
|
||||||
*/
|
*/
|
||||||
public @NotNull String getTranslationKey() {
|
public @NotNull String getTranslationKey() {
|
||||||
return "lambdacontrols.hud_side." + this.getName();
|
return "midnightcontrols.hud_side." + this.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the translated text of this hud side.
|
* Gets the translated text of this hud side.
|
||||||
*
|
*
|
||||||
* @return The translated text of this hud side.
|
* @return the translated text of this hud side
|
||||||
*/
|
*/
|
||||||
public @NotNull Text getTranslatedText() {
|
public @NotNull Text getTranslatedText() {
|
||||||
return this.text;
|
return this.text;
|
||||||
@@ -72,8 +72,8 @@ public enum HudSide implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the hud side from its identifier.
|
* Gets the hud side from its identifier.
|
||||||
*
|
*
|
||||||
* @param id The identifier of the hud side.
|
* @param id the identifier of the hud side
|
||||||
* @return The hud side if found, else empty.
|
* @return the hud side if found, else empty
|
||||||
*/
|
*/
|
||||||
public static @NotNull Optional<HudSide> byId(@NotNull String id) {
|
public static @NotNull Optional<HudSide> byId(@NotNull String id) {
|
||||||
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
|
import dev.lambdaurora.spruceui.event.OpenScreenCallback;
|
||||||
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsHud;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingRegistryImplAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.ring.KeyBindingRingAction;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
||||||
|
import dev.lambdaurora.spruceui.hud.HudManager;
|
||||||
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||||
|
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
|
import net.minecraft.client.option.KeyBinding;
|
||||||
|
import net.minecraft.client.toast.SystemToast;
|
||||||
|
import net.minecraft.client.util.InputUtil;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the midnightcontrols client mod.
|
||||||
|
*
|
||||||
|
* @author LambdAurora
|
||||||
|
* @version 1.7.0
|
||||||
|
* @since 1.1.0
|
||||||
|
*/
|
||||||
|
public class MidnightControlsClient extends MidnightControls implements ClientModInitializer {
|
||||||
|
public static boolean lateInitDone = false;
|
||||||
|
private static MidnightControlsClient INSTANCE;
|
||||||
|
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_up"),
|
||||||
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement");
|
||||||
|
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_right"),
|
||||||
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.movement");
|
||||||
|
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_down"),
|
||||||
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.movement");
|
||||||
|
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_left"),
|
||||||
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.movement");
|
||||||
|
public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "ring"),
|
||||||
|
InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), "key.categories.misc");
|
||||||
|
public static final Identifier CONTROLLER_BUTTONS = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_buttons.png");
|
||||||
|
public static final Identifier CONTROLLER_EXPANDED = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_expanded.png");
|
||||||
|
public static final Identifier CONTROLLER_AXIS = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_axis.png");
|
||||||
|
public static final Identifier CURSOR_TEXTURE = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/cursor.png");
|
||||||
|
public final static File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt");
|
||||||
|
public final MidnightInput input = new MidnightInput();
|
||||||
|
public final MidnightRing ring = new MidnightRing(this);
|
||||||
|
public final MidnightReacharound reacharound = new MidnightReacharound();
|
||||||
|
private MidnightControlsHud hud;
|
||||||
|
private ControlsMode previousControlsMode;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitializeClient() {
|
||||||
|
INSTANCE = this;
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_UP);
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT);
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN);
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT);
|
||||||
|
//KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
||||||
|
|
||||||
|
this.ring.registerAction("keybinding", KeyBindingRingAction.FACTORY);
|
||||||
|
this.ring.load();
|
||||||
|
|
||||||
|
ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (client, handler, buf, responseSender) ->
|
||||||
|
responseSender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode)));
|
||||||
|
ClientPlayNetworking.registerGlobalReceiver(FEATURE_CHANNEL, (client, handler, buf, responseSender) -> {
|
||||||
|
int features = buf.readVarInt();
|
||||||
|
for (int i = 0; i < features; i++) {
|
||||||
|
var name = buf.readString(64);
|
||||||
|
boolean allowed = buf.readBoolean();
|
||||||
|
MidnightControlsFeature.fromName(name).ifPresent(feature -> client.execute(() -> feature.setAllowed(allowed)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
||||||
|
sender.sendPacket(HELLO_CHANNEL, this.makeHello(MidnightControlsConfig.controlsMode));
|
||||||
|
sender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode));
|
||||||
|
});
|
||||||
|
ClientPlayConnectionEvents.DISCONNECT.register(this::onLeave);
|
||||||
|
|
||||||
|
ClientTickEvents.START_CLIENT_TICK.register(this.reacharound::tick);
|
||||||
|
ClientTickEvents.START_CLIENT_TICK.register(this::onTick);
|
||||||
|
|
||||||
|
OpenScreenCallback.EVENT.register((client, screen) -> {
|
||||||
|
if (screen == null && MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) {
|
||||||
|
screen = new TouchscreenOverlay(this);
|
||||||
|
screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||||
|
client.skipGameRender = false;
|
||||||
|
client.currentScreen = screen;
|
||||||
|
} else if (screen != null) {
|
||||||
|
this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HudManager.register(this.hud = new MidnightControlsHud(this));
|
||||||
|
FabricLoader.getInstance().getModContainer("midnightcontrols").ifPresent(modContainer -> {
|
||||||
|
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","bedrock"), modContainer, ResourcePackActivationType.NORMAL);
|
||||||
|
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","legacy"), modContainer, ResourcePackActivationType.NORMAL);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when Minecraft is initializing.
|
||||||
|
*/
|
||||||
|
public void onMcInit(@NotNull MinecraftClient client) {
|
||||||
|
ButtonBinding.init(client.options);
|
||||||
|
MidnightControlsConfig.load();
|
||||||
|
this.hud.setVisible(MidnightControlsConfig.hudEnable);
|
||||||
|
Controller.updateMappings();
|
||||||
|
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
||||||
|
if (event == GLFW.GLFW_CONNECTED) {
|
||||||
|
var controller = Controller.byId(jid);
|
||||||
|
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("midnightcontrols.controller.connected", jid),
|
||||||
|
new LiteralText(controller.getName())));
|
||||||
|
} else if (event == GLFW.GLFW_DISCONNECTED) {
|
||||||
|
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("midnightcontrols.controller.disconnected", jid),
|
||||||
|
null));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.switchControlsMode();
|
||||||
|
});
|
||||||
|
|
||||||
|
MidnightControlsCompat.init(this);
|
||||||
|
}
|
||||||
|
ButtonCategory category;
|
||||||
|
/**
|
||||||
|
* This method is called to initialize keybindings
|
||||||
|
*/
|
||||||
|
public void initKeybindings() {
|
||||||
|
if (lateInitDone) return;
|
||||||
|
if (KeyBindingRegistryImplAccessor.getModdedKeyBindings() == null || KeyBindingRegistryImplAccessor.getModdedKeyBindings().isEmpty()) return;
|
||||||
|
for (int i = 0; i < KeyBindingRegistryImplAccessor.getModdedKeyBindings().size(); ++i) {
|
||||||
|
KeyBinding keyBinding = KeyBindingRegistryImplAccessor.getModdedKeyBindings().get(i);
|
||||||
|
if (!keyBinding.getTranslationKey().contains("midnightcontrols") && !keyBinding.getTranslationKey().contains("ok_zoomer") && !keyBinding.getTranslationKey().contains("okzoomer")) {
|
||||||
|
category = null;
|
||||||
|
InputManager.streamCategories().forEach(buttonCategory -> {
|
||||||
|
if (buttonCategory.getIdentifier().equals(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory())))
|
||||||
|
category = buttonCategory;
|
||||||
|
});
|
||||||
|
if (category == null) {
|
||||||
|
category = new ButtonCategory(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory()));
|
||||||
|
InputManager.registerCategory(category);
|
||||||
|
}
|
||||||
|
ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getTranslationKey()).category(category).linkKeybind(keyBinding).register();
|
||||||
|
if (MidnightControlsConfig.debug) {
|
||||||
|
logger.info(keyBinding.getTranslationKey());
|
||||||
|
logger.info(buttonBinding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InputManager.loadButtonBindings();
|
||||||
|
lateInitDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called every Minecraft tick.
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
*/
|
||||||
|
public void onTick(@NotNull MinecraftClient client) {
|
||||||
|
this.initKeybindings();
|
||||||
|
this.input.tick(client);
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput))
|
||||||
|
this.input.tickController(client);
|
||||||
|
|
||||||
|
// if (BINDING_RING.wasPressed()) {
|
||||||
|
// client.setScreen(new RingScreen());
|
||||||
|
// }
|
||||||
|
if (client.world != null && MidnightControlsConfig.enableHints && !MidnightControlsConfig.autoSwitchMode && MidnightControlsConfig.controlsMode == ControlsMode.DEFAULT && MidnightControlsConfig.getController().isGamepad()) {
|
||||||
|
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION, new TranslatableText("midnightcontrols.controller.tutorial.title"),
|
||||||
|
new TranslatableText("midnightcontrols.controller.tutorial.description", new TranslatableText("options.title"), new TranslatableText("controls.title"),
|
||||||
|
new TranslatableText("midnightcontrols.menu.title.controller"))));
|
||||||
|
MidnightControlsConfig.enableHints = false;
|
||||||
|
MidnightControlsConfig.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void onRender(MinecraftClient client) {
|
||||||
|
this.input.onRender(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when leaving a server.
|
||||||
|
*/
|
||||||
|
public void onLeave(ClientPlayNetworkHandler handler, MinecraftClient client) {
|
||||||
|
MidnightControlsFeature.resetAllAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches the controls mode if the auto switch is enabled.
|
||||||
|
*/
|
||||||
|
public void switchControlsMode() {
|
||||||
|
if (MidnightControlsConfig.autoSwitchMode) {
|
||||||
|
if (MidnightControlsConfig.getController().isGamepad()) {
|
||||||
|
this.previousControlsMode = MidnightControlsConfig.controlsMode;
|
||||||
|
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||||
|
} else {
|
||||||
|
if (this.previousControlsMode == null) {
|
||||||
|
this.previousControlsMode = ControlsMode.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
MidnightControlsConfig.controlsMode = this.previousControlsMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the HUD is enabled or not.
|
||||||
|
*
|
||||||
|
* @param enabled true if the HUD is enabled, else false
|
||||||
|
*/
|
||||||
|
public void setHudEnabled(boolean enabled) {
|
||||||
|
MidnightControlsConfig.hudEnable = enabled;
|
||||||
|
this.hud.setVisible(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the midnightcontrols client instance.
|
||||||
|
*
|
||||||
|
* @return the midnightcontrols client instance
|
||||||
|
*/
|
||||||
|
public static MidnightControlsClient get() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,325 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import eu.midnightdust.lib.config.MidnightConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents MidnightControls configuration.
|
||||||
|
*/
|
||||||
|
public class MidnightControlsConfig extends MidnightConfig {
|
||||||
|
public static boolean isEditing = false;
|
||||||
|
// General
|
||||||
|
@Entry(name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT;
|
||||||
|
@Entry(name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true;
|
||||||
|
@Entry(name = "Debug") public static boolean debug = false;
|
||||||
|
// HUD
|
||||||
|
@Entry(name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true;
|
||||||
|
@Entry(name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT;
|
||||||
|
// Gameplay
|
||||||
|
@Entry(name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true;
|
||||||
|
@Entry(name = "midnightcontrols.menu.double_tap_to_sprint") public static boolean doubleTapToSprint = true;
|
||||||
|
@Entry(name = "midnightcontrols.menu.fast_block_placing") public static boolean fastBlockPlacing = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
|
||||||
|
@Entry(name = "midnightcontrols.menu.fly_drifting") public static boolean flyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. It can also conflict with some other mods.
|
||||||
|
@Entry(name = "midnightcontrols.menu.fly_drifting_vertical") public static boolean verticalFlyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers.
|
||||||
|
@Entry(name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
|
||||||
|
@Entry(name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
|
||||||
|
@Entry(name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true;
|
||||||
|
@Entry(name = "Reacharound Outline Color") public static int[] reacharoundOutlineColor = new int[]{255, 255, 255, 102};
|
||||||
|
@Entry(name = "midnightcontrols.menu.right_dead_zone") public static double rightDeadZone = 0.25;
|
||||||
|
@Entry(name = "midnightcontrols.menu.left_dead_zone") public static double leftDeadZone = 0.25;
|
||||||
|
@Entry(name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false;
|
||||||
|
@Entry(name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false;
|
||||||
|
@Entry(name = "midnightcontrols.menu.rotation_speed") public static double rotationSpeed = 40.0; //used for x axis, name kept for compatability
|
||||||
|
@Entry(name = "midnightcontrols.menu.y_axis_rotation_speed") public static double yAxisRotationSpeed = rotationSpeed;
|
||||||
|
@Entry(name = "midnightcontrols.menu.mouse_speed") public static double mouseSpeed = 25.0;
|
||||||
|
@Entry(name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false;
|
||||||
|
@Entry(name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false;
|
||||||
|
@Entry(name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
|
||||||
|
@Entry(name = "Controller ID") public static Object controllerID = 0;
|
||||||
|
@Entry(name = "2nd Controller ID") public static Object secondControllerID = -1;
|
||||||
|
@Entry(name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT;
|
||||||
|
@Entry(name = "Mouse screens") public static List<String> mouseScreens = Lists.newArrayList("me.jellysquid.mods.sodium.client.gui",
|
||||||
|
"net.coderbot.iris.gui", "net.minecraft.client.gui.screen.advancement", "net.minecraft.client.gui.screen.pack.PackScreen", "net.minecraft.class_5375",
|
||||||
|
"net.minecraft.class_457", "net.minecraft.class_408", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen",
|
||||||
|
"hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen",
|
||||||
|
"io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen");
|
||||||
|
@Entry(name = "Keybindings") public static Map<String, String> BINDINGS = new HashMap<>();
|
||||||
|
|
||||||
|
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
|
||||||
|
@Entry(name = "Max analog values") public static double[] maxAnalogValues = new double[]{1, 1, 1, 1};
|
||||||
|
@Entry(name = "Trigger button fix") public static boolean triggerFix = true;
|
||||||
|
@Entry(name = "Enable Hints") public static boolean enableHints = true;
|
||||||
|
@Entry(name = "Command Keybinds") public static List<String> commandKeybinds = Lists.newArrayList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the configuration
|
||||||
|
*/
|
||||||
|
public static void load() {
|
||||||
|
MidnightControlsConfig.init("midnightcontrols", MidnightControlsConfig.class);
|
||||||
|
MidnightControlsClient.get().log("Configuration loaded.");
|
||||||
|
// Controller controls.
|
||||||
|
InputManager.loadButtonBindings();
|
||||||
|
//this.mod.ring.load(this.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the configuration.
|
||||||
|
*/
|
||||||
|
public static void save() {
|
||||||
|
MidnightControlsConfig.write("midnightcontrols");
|
||||||
|
MidnightControlsClient.get().log("Configuration saved.");
|
||||||
|
MidnightControlsFeature.refreshEnabled();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the used controller.
|
||||||
|
*
|
||||||
|
* @return the controller
|
||||||
|
*/
|
||||||
|
public static Controller getController() {
|
||||||
|
var raw = MidnightControlsConfig.controllerID;
|
||||||
|
Controller controller = Controller.byId(GLFW.GLFW_JOYSTICK_1);
|
||||||
|
if (raw instanceof Number) {
|
||||||
|
controller = Controller.byId(((Number) raw).intValue());
|
||||||
|
} else if (raw instanceof String) {
|
||||||
|
controller = Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1));
|
||||||
|
}
|
||||||
|
if ((!controller.isConnected() || !controller.isGamepad()) && MidnightControlsConfig.autoSwitchMode && !isEditing) {
|
||||||
|
for (int i = 0; i < GLFW.GLFW_JOYSTICK_LAST; ++i) {
|
||||||
|
Controller gamepad = Controller.byId(i);
|
||||||
|
if (gamepad.isConnected() && gamepad.isGamepad()) {
|
||||||
|
controller = gamepad;
|
||||||
|
i = GLFW_JOYSTICK_LAST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (controller.isConnected() && controller.isGamepad() && MidnightControlsConfig.autoSwitchMode && !isEditing) MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the used controller.
|
||||||
|
*
|
||||||
|
* @param controller the controller
|
||||||
|
*/
|
||||||
|
public static void setController(Controller controller) {
|
||||||
|
MidnightControlsConfig.controllerID = controller.id();
|
||||||
|
MidnightControlsConfig.write("midnightcontrols");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the second controller (for Joy-Con supports).
|
||||||
|
*
|
||||||
|
* @return the second controller
|
||||||
|
*/
|
||||||
|
public static Optional<Controller> getSecondController() {
|
||||||
|
var raw = MidnightControlsConfig.secondControllerID;
|
||||||
|
if (raw instanceof Number) {
|
||||||
|
if (((Number) raw).intValue() == -1)
|
||||||
|
return Optional.empty();
|
||||||
|
return Optional.of(Controller.byId(((Number) raw).intValue()));
|
||||||
|
} else if (raw instanceof String) {
|
||||||
|
return Optional.of(Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1)));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the second controller.
|
||||||
|
*
|
||||||
|
* @param controller the second controller
|
||||||
|
*/
|
||||||
|
public static void setSecondController(@Nullable Controller controller) {
|
||||||
|
MidnightControlsConfig.secondControllerID = controller == null ? -1 : controller.id();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the right X axis sign.
|
||||||
|
*
|
||||||
|
* @return the right X axis sign
|
||||||
|
*/
|
||||||
|
public static double getRightXAxisSign() {
|
||||||
|
return MidnightControlsConfig.invertRightXAxis ? -1.0 : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the right Y axis sign.
|
||||||
|
*
|
||||||
|
* @return the right Y axis sign
|
||||||
|
*/
|
||||||
|
public static double getRightYAxisSign() {
|
||||||
|
return MidnightControlsConfig.invertRightYAxis ? -1.0 : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getAxisMaxValue(int axis) {
|
||||||
|
if (axis >= MidnightControlsConfig.maxAnalogValues.length)
|
||||||
|
return 1;
|
||||||
|
return MidnightControlsConfig.maxAnalogValues[axis];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAxisMaxValue(int axis, double value) {
|
||||||
|
if (axis < MidnightControlsConfig.maxAnalogValues.length)
|
||||||
|
MidnightControlsConfig.maxAnalogValues[axis] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the button binding from configuration.
|
||||||
|
*
|
||||||
|
* @param button the button binding
|
||||||
|
*/
|
||||||
|
public static void loadButtonBinding(@NotNull ButtonBinding button) {
|
||||||
|
button.setButton(button.getDefaultButton());
|
||||||
|
var code = MidnightControlsConfig.BINDINGS.getOrDefault("controller.controls." + button.getName(), button.getButtonCode());
|
||||||
|
|
||||||
|
var matcher = BUTTON_BINDING_PATTERN.matcher(code);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var buttons = new int[1];
|
||||||
|
int count = 0;
|
||||||
|
while (matcher.find()) {
|
||||||
|
count++;
|
||||||
|
if (count > buttons.length)
|
||||||
|
buttons = Arrays.copyOf(buttons, count);
|
||||||
|
String current;
|
||||||
|
if (!MidnightControlsConfig.checkValidity(button, code, current = matcher.group(1)))
|
||||||
|
return;
|
||||||
|
buttons[count - 1] = Integer.parseInt(current);
|
||||||
|
}
|
||||||
|
if (count == 0) {
|
||||||
|
MidnightControlsClient.get().warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
||||||
|
MidnightControlsConfig.setButtonBinding(button, new int[]{-1});
|
||||||
|
}
|
||||||
|
|
||||||
|
button.setButton(buttons);
|
||||||
|
} catch (Exception e) {
|
||||||
|
MidnightControlsClient.get().warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
||||||
|
MidnightControlsConfig.BINDINGS.put("controller.controls." + button.getName(), button.getButtonCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkValidity(@NotNull ButtonBinding binding, @NotNull String input, String group) {
|
||||||
|
if (group == null) {
|
||||||
|
MidnightControlsClient.get().warn("Malformed config value \"" + input + "\" for binding \"" + binding.getName() + "\".");
|
||||||
|
MidnightControlsConfig.BINDINGS.put("controller.controls." + binding.getName(), binding.getButtonCode());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the button binding in configuration.
|
||||||
|
*
|
||||||
|
* @param binding the button binding
|
||||||
|
* @param button the button
|
||||||
|
*/
|
||||||
|
public static void setButtonBinding(@NotNull ButtonBinding binding, int[] button) {
|
||||||
|
binding.setButton(button);
|
||||||
|
MidnightControlsConfig.BINDINGS.put("controller.controls." + binding.getName(), binding.getButtonCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isBackButton(int btn, boolean isBtn, int state) {
|
||||||
|
if (!isBtn && state == 0)
|
||||||
|
return false;
|
||||||
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false) == ButtonBinding.axisAsButton(btn, state == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isForwardButton(int btn, boolean isBtn, int state) {
|
||||||
|
if (!isBtn && state == 0)
|
||||||
|
return false;
|
||||||
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true) == ButtonBinding.axisAsButton(btn, state == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isLeftButton(int btn, boolean isBtn, int state) {
|
||||||
|
if (!isBtn && state == 0)
|
||||||
|
return false;
|
||||||
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false) == ButtonBinding.axisAsButton(btn, state == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRightButton(int btn, boolean isBtn, int state) {
|
||||||
|
if (!isBtn && state == 0)
|
||||||
|
return false;
|
||||||
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true) == ButtonBinding.axisAsButton(btn, state == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the specified axis is an axis used for movements.
|
||||||
|
*
|
||||||
|
* @param axis the axis index
|
||||||
|
* @return true if the axis is used for movements, else false
|
||||||
|
*/
|
||||||
|
public static boolean isMovementAxis(int axis) {
|
||||||
|
return axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_X;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reset() {
|
||||||
|
controlsMode = ControlsMode.DEFAULT;
|
||||||
|
autoSwitchMode = true;
|
||||||
|
debug = false;
|
||||||
|
hudEnable = true;
|
||||||
|
hudSide = HudSide.LEFT;
|
||||||
|
analogMovement = true;
|
||||||
|
doubleTapToSprint = true;
|
||||||
|
fastBlockPlacing = false;
|
||||||
|
flyDrifting = true;
|
||||||
|
verticalFlyDrifting = true;
|
||||||
|
horizontalReacharound = false;
|
||||||
|
verticalReacharound = false;
|
||||||
|
shouldRenderReacharoundOutline = true;
|
||||||
|
reacharoundOutlineColor = new int[]{255, 255, 255, 102};
|
||||||
|
rightDeadZone = 0.25;
|
||||||
|
leftDeadZone = 0.25;
|
||||||
|
invertRightYAxis = false;
|
||||||
|
invertRightXAxis = false;
|
||||||
|
rotationSpeed = 40.0;
|
||||||
|
yAxisRotationSpeed = rotationSpeed;
|
||||||
|
mouseSpeed = 25.0;
|
||||||
|
unfocusedInput = false;
|
||||||
|
virtualMouse = false;
|
||||||
|
virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
|
||||||
|
controllerID = 0;
|
||||||
|
secondControllerID = -1;
|
||||||
|
controllerType = ControllerType.DEFAULT;
|
||||||
|
mouseScreens = Lists.newArrayList("me.jellysquid.mods.sodium.client.gui", "net.coderbot.iris.gui", "net.minecraft.client.gui.screen.advancement", "net.minecraft.client.gui.screen.pack.PackScreen", "net.minecraft.class_5375", "net.minecraft.class_457", "net.minecraft.class_408", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen");
|
||||||
|
BINDINGS = new HashMap<>();
|
||||||
|
maxAnalogValues = new double[]{1, 1, 1, 1};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the controller type from the controller's identifier.
|
||||||
|
*
|
||||||
|
* @return the controller name matches a type, else empty
|
||||||
|
*/
|
||||||
|
public static @NotNull ControllerType matchControllerToType() {
|
||||||
|
String controller = getController().getName().toLowerCase();
|
||||||
|
if (controller.contains("xbox 360")) return ControllerType.XBOX_360;
|
||||||
|
else if (controller.contains("xbox") || controller.contains("afterglow")) return ControllerType.XBOX;
|
||||||
|
else if (controller.contains("steam deck")) return ControllerType.STEAM_DECK;
|
||||||
|
else if (controller.contains("steam")) return ControllerType.STEAM_CONTROLLER;
|
||||||
|
else if (controller.contains("dualsense")) return ControllerType.DUALSENSE;
|
||||||
|
else if (controller.contains("dualshock") || controller.contains("ps4")) return ControllerType.DUALSHOCK;
|
||||||
|
else if (controller.contains("switch") || controller.contains("joy-con")) return ControllerType.SWITCH;
|
||||||
|
else if (controller.contains("ouya")) return ControllerType.OUYA;
|
||||||
|
else return ControllerType.DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
|
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||||
|
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the API implementation of ModMenu for midnightcontrols.
|
||||||
|
*
|
||||||
|
* @author LambdAurora
|
||||||
|
* @version 1.7.0
|
||||||
|
* @since 1.1.0
|
||||||
|
*/
|
||||||
|
public class MidnightControlsModMenu implements ModMenuApi {
|
||||||
|
@Override
|
||||||
|
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||||
|
return parent -> new MidnightControlsSettingsScreen(parent, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,52 +1,51 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
|
import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
import dev.lambdaurora.spruceui.widget.container.SpruceEntryListWidget;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.compat.LibGuiCompat;
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.widget.ControllerControlsWidget;
|
import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat;
|
||||||
import dev.lambdaurora.lambdacontrols.client.mixin.AdvancementsScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import dev.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import dev.lambdaurora.lambdacontrols.client.mixin.EntryListWidgetAccessor;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.MouseAccessor;
|
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
||||||
import me.lambdaurora.spruceui.navigation.NavigationDirection;
|
import eu.midnightdust.midnightcontrols.client.mixin.*;
|
||||||
import me.lambdaurora.spruceui.screen.SpruceScreen;
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
import me.lambdaurora.spruceui.widget.AbstractSprucePressableButtonWidget;
|
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
|
||||||
import me.lambdaurora.spruceui.widget.SpruceElement;
|
import dev.lambdaurora.spruceui.navigation.NavigationDirection;
|
||||||
import me.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
import dev.lambdaurora.spruceui.screen.SpruceScreen;
|
||||||
import me.lambdaurora.spruceui.widget.container.SpruceParentWidget;
|
import dev.lambdaurora.spruceui.widget.AbstractSprucePressableButtonWidget;
|
||||||
|
import dev.lambdaurora.spruceui.widget.SpruceElement;
|
||||||
|
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
||||||
|
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.Element;
|
import net.minecraft.client.gui.Element;
|
||||||
import net.minecraft.client.gui.ParentElement;
|
import net.minecraft.client.gui.ParentElement;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.TitleScreen;
|
||||||
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
||||||
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.MerchantScreen;
|
||||||
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
|
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
|
||||||
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
|
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
|
||||||
import net.minecraft.client.gui.screen.pack.PackScreen;
|
|
||||||
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
||||||
import net.minecraft.client.gui.widget.AbstractPressableButtonWidget;
|
import net.minecraft.client.gui.widget.*;
|
||||||
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget;
|
|
||||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
|
||||||
import net.minecraft.client.gui.widget.SliderWidget;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
import net.minecraft.screen.slot.SlotActionType;
|
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
import org.aperlambda.lambdacommon.utils.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -54,30 +53,22 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
import org.lwjgl.glfw.GLFWGamepadState;
|
import org.lwjgl.glfw.GLFWGamepadState;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.util.*;
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding.axisAsButton;
|
|
||||||
import static dev.lambdaurora.lambdacontrols.client.controller.InputManager.INPUT_MANAGER;
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the LambdaControls' input handler.
|
* Represents the midnightcontrols' input handler.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.6.0
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public class LambdaInput {
|
public class MidnightInput {
|
||||||
private static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
private static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
||||||
private final LambdaControlsConfig config;
|
|
||||||
// Cooldowns
|
// Cooldowns
|
||||||
private int actionGuiCooldown = 0;
|
public int actionGuiCooldown = 0;
|
||||||
private boolean ignoreNextARelease = false;
|
public boolean ignoreNextARelease = false;
|
||||||
private double targetYaw = 0.0;
|
private double targetYaw = 0.0;
|
||||||
private double targetPitch = 0.0;
|
private double targetPitch = 0.0;
|
||||||
private float prevXAxis = 0.f;
|
private float prevXAxis = 0.f;
|
||||||
@@ -86,80 +77,79 @@ public class LambdaInput {
|
|||||||
private int targetMouseY = 0;
|
private int targetMouseY = 0;
|
||||||
private float mouseSpeedX = 0.f;
|
private float mouseSpeedX = 0.f;
|
||||||
private float mouseSpeedY = 0.f;
|
private float mouseSpeedY = 0.f;
|
||||||
private int inventoryInteractionCooldown = 0;
|
public int inventoryInteractionCooldown = 0;
|
||||||
|
public int screenCloseCooldown = 0;
|
||||||
|
|
||||||
private ControllerControlsWidget controlsInput = null;
|
private ControllerControlsWidget controlsInput = null;
|
||||||
|
|
||||||
public LambdaInput(@NotNull LambdaControlsClient mod) {
|
public MidnightInput() {}
|
||||||
this.config = mod.config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called every Minecraft tick.
|
* This method is called every Minecraft tick.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
*/
|
*/
|
||||||
public void tick(@NotNull MinecraftClient client) {
|
public void tick(@NotNull MinecraftClient client) {
|
||||||
this.targetYaw = 0.F;
|
this.targetYaw = 0.F;
|
||||||
this.targetPitch = 0.F;
|
this.targetPitch = 0.F;
|
||||||
|
|
||||||
// Handles the key bindings.
|
// Handles the key bindings.
|
||||||
if (LambdaControlsClient.BINDING_LOOK_UP.isPressed()) {
|
if (MidnightControlsClient.BINDING_LOOK_UP.isPressed()) {
|
||||||
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 2);
|
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 2);
|
||||||
} else if (LambdaControlsClient.BINDING_LOOK_DOWN.isPressed()) {
|
} else if (MidnightControlsClient.BINDING_LOOK_DOWN.isPressed()) {
|
||||||
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 1);
|
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 1);
|
||||||
}
|
}
|
||||||
if (LambdaControlsClient.BINDING_LOOK_LEFT.isPressed()) {
|
if (MidnightControlsClient.BINDING_LOOK_LEFT.isPressed()) {
|
||||||
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 2);
|
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 2);
|
||||||
} else if (LambdaControlsClient.BINDING_LOOK_RIGHT.isPressed()) {
|
} else if (MidnightControlsClient.BINDING_LOOK_RIGHT.isPressed()) {
|
||||||
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 1);
|
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
INPUT_MANAGER.tick(client);
|
InputManager.INPUT_MANAGER.tick(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called every Minecraft tick for controller input update.
|
* This method is called every Minecraft tick for controller input update.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
*/
|
*/
|
||||||
public void tickController(@NotNull MinecraftClient client) {
|
public void tickController(@NotNull MinecraftClient client) {
|
||||||
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0).forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
|
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0)
|
||||||
|
.forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
|
||||||
// Decreases the cooldown for GUI actions.
|
// Decreases the cooldown for GUI actions.
|
||||||
if (this.actionGuiCooldown > 0)
|
if (this.actionGuiCooldown > 0)
|
||||||
--this.actionGuiCooldown;
|
--this.actionGuiCooldown;
|
||||||
|
if (this.screenCloseCooldown > 0)
|
||||||
|
--this.screenCloseCooldown;
|
||||||
|
|
||||||
InputManager.updateStates();
|
InputManager.updateStates();
|
||||||
|
|
||||||
Controller controller = this.config.getController();
|
var controller = MidnightControlsConfig.getController();
|
||||||
|
|
||||||
if (controller.isConnected()) {
|
if (controller.isConnected()) {
|
||||||
GLFWGamepadState state = controller.getState();
|
var state = controller.getState();
|
||||||
this.fetchButtonInput(client, state, false);
|
this.fetchButtonInput(client, state, false);
|
||||||
this.fetchAxeInput(client, state, false);
|
this.fetchAxeInput(client, state, false);
|
||||||
}
|
}
|
||||||
this.config.getSecondController().filter(Controller::isConnected)
|
MidnightControlsConfig.getSecondController().filter(Controller::isConnected)
|
||||||
.ifPresent(joycon -> {
|
.ifPresent(joycon -> {
|
||||||
GLFWGamepadState state = joycon.getState();
|
GLFWGamepadState state = joycon.getState();
|
||||||
this.fetchButtonInput(client, state, true);
|
this.fetchButtonInput(client, state, true);
|
||||||
this.fetchAxeInput(client, state, true);
|
this.fetchAxeInput(client, state, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
boolean allowInput = true;
|
boolean allowInput = this.controlsInput == null || this.controlsInput.focusedBinding == null;
|
||||||
|
|
||||||
if (this.controlsInput != null && this.controlsInput.focusedBinding != null)
|
|
||||||
allowInput = false;
|
|
||||||
|
|
||||||
if (allowInput)
|
if (allowInput)
|
||||||
InputManager.updateBindings(client);
|
InputManager.updateBindings(client);
|
||||||
|
|
||||||
if (this.controlsInput != null
|
if (this.controlsInput != null
|
||||||
&& InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
|
&& InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
|
||||||
if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) {
|
if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) {
|
||||||
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
||||||
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
||||||
buttons[i] = this.controlsInput.currentButtons.get(i);
|
buttons[i] = this.controlsInput.currentButtons.get(i);
|
||||||
this.controlsInput.focusedBinding.setButton(buttons);
|
this.controlsInput.finishBindingEdit(buttons);
|
||||||
this.controlsInput.focusedBinding = null;
|
|
||||||
this.controlsInput = null;
|
this.controlsInput = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,34 +161,34 @@ public class LambdaInput {
|
|||||||
/**
|
/**
|
||||||
* This method is called before the screen is rendered.
|
* This method is called before the screen is rendered.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param screen The screen to render.
|
* @param screen the screen to render
|
||||||
*/
|
*/
|
||||||
public void onPreRenderScreen(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
public void onPreRenderScreen(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
||||||
if (!isScreenInteractive(screen)) {
|
if (!isScreenInteractive(screen)) {
|
||||||
INPUT_MANAGER.updateMousePosition(client);
|
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when Minecraft renders.
|
* This method is called when Minecraft renders.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
*/
|
*/
|
||||||
public void onRender(float tickDelta, @NotNull MinecraftClient client) {
|
public void onRender(@NotNull MinecraftClient client) {
|
||||||
if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
|
if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PlayerEntity player = client.player;
|
var player = client.player;
|
||||||
if (player == null)
|
if (player == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.targetYaw != 0.f || this.targetPitch != 0.f) {
|
if (this.targetYaw != 0.f || this.targetPitch != 0.f) {
|
||||||
float rotationYaw = (float) (player.prevYaw + (this.targetYaw / 0.10) * tickDelta);
|
float rotationYaw = (float) (player.prevYaw + (this.targetYaw / 0.10) * client.getTickDelta());
|
||||||
float rotationPitch = (float) (player.prevPitch + (this.targetPitch / 0.10) * tickDelta);
|
float rotationPitch = (float) (player.prevPitch + (this.targetPitch / 0.10) * client.getTickDelta());
|
||||||
client.player.yaw = rotationYaw;
|
client.player.setYaw(rotationYaw);
|
||||||
client.player.pitch = MathHelper.clamp(rotationPitch, -90.f, 90.f);
|
client.player.setPitch(MathHelper.clamp(rotationPitch, -90.f, 90.f));
|
||||||
if (client.player.isRiding()) {
|
if (client.player.isRiding() && client.player.getVehicle() != null) {
|
||||||
client.player.getVehicle().onPassengerLookAround(client.player);
|
client.player.getVehicle().onPassengerLookAround(client.player);
|
||||||
}
|
}
|
||||||
client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw);
|
client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw);
|
||||||
@@ -208,17 +198,17 @@ public class LambdaInput {
|
|||||||
/**
|
/**
|
||||||
* This method is called when a Screen is opened.
|
* This method is called when a Screen is opened.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param windowWidth The window width.
|
* @param windowWidth the window width
|
||||||
* @param windowHeight The window height.
|
* @param windowHeight the window height
|
||||||
*/
|
*/
|
||||||
public void onScreenOpen(@NotNull MinecraftClient client, int windowWidth, int windowHeight) {
|
public void onScreenOpen(@NotNull MinecraftClient client, int windowWidth, int windowHeight) {
|
||||||
if (client.currentScreen == null) {
|
if (client.currentScreen == null) {
|
||||||
this.mouseSpeedX = this.mouseSpeedY = 0.0F;
|
this.mouseSpeedX = this.mouseSpeedY = 0.0F;
|
||||||
INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight);
|
InputManager.INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight);
|
||||||
} else if (isScreenInteractive(client.currentScreen) && this.config.hasVirtualMouse()) {
|
} else if (isScreenInteractive(client.currentScreen) && MidnightControlsConfig.virtualMouse) {
|
||||||
((MouseAccessor) client.mouse).lambdacontrols$onCursorPos(client.getWindow().getHandle(), 0, 0);
|
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), 0, 0);
|
||||||
INPUT_MANAGER.resetMouseTarget(client);
|
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
||||||
}
|
}
|
||||||
this.inventoryInteractionCooldown = 5;
|
this.inventoryInteractionCooldown = 5;
|
||||||
}
|
}
|
||||||
@@ -232,12 +222,12 @@ public class LambdaInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void fetchButtonInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
private void fetchButtonInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
||||||
ByteBuffer buffer = gamepadState.buttons();
|
var buffer = gamepadState.buttons();
|
||||||
for (int i = 0; i < buffer.limit(); i++) {
|
for (int i = 0; i < buffer.limit(); i++) {
|
||||||
int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||||
boolean btnState = buffer.get() == (byte) 1;
|
boolean btnState = buffer.get() == (byte) 1;
|
||||||
ButtonState state = ButtonState.NONE;
|
var state = ButtonState.NONE;
|
||||||
ButtonState previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
|
var previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
|
||||||
|
|
||||||
if (btnState != previousState.isPressed()) {
|
if (btnState != previousState.isPressed()) {
|
||||||
state = btnState ? ButtonState.PRESS : ButtonState.RELEASE;
|
state = btnState ? ButtonState.PRESS : ButtonState.RELEASE;
|
||||||
@@ -257,7 +247,7 @@ public class LambdaInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void fetchAxeInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
private void fetchAxeInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
||||||
FloatBuffer buffer = gamepadState.axes();
|
var buffer = gamepadState.axes();
|
||||||
for (int i = 0; i < buffer.limit(); i++) {
|
for (int i = 0; i < buffer.limit(); i++) {
|
||||||
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||||
float value = buffer.get();
|
float value = buffer.get();
|
||||||
@@ -266,17 +256,17 @@ public class LambdaInput {
|
|||||||
if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y)
|
if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y)
|
||||||
value *= -1.0F;
|
value *= -1.0F;
|
||||||
|
|
||||||
int state = value > this.config.getRightDeadZone() ? 1 : (value < -this.config.getRightDeadZone() ? 2 : 0);
|
int state = value > MidnightControlsConfig.rightDeadZone ? 1 : (value < -MidnightControlsConfig.rightDeadZone ? 2 : 0);
|
||||||
this.handleAxe(client, axis, value, absValue, state);
|
this.handleAxe(client, axis, value, absValue, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleButton(@NotNull MinecraftClient client, int button, int action, boolean state) {
|
public void handleButton(@NotNull MinecraftClient client, int button, int action, boolean state) {
|
||||||
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
||||||
if (action == 0 && !this.controlsInput.currentButtons.contains(button)) {
|
if (action == 0 && !this.controlsInput.currentButtons.contains(button)) {
|
||||||
this.controlsInput.currentButtons.add(button);
|
this.controlsInput.currentButtons.add(button);
|
||||||
|
|
||||||
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
var buttons = new int[this.controlsInput.currentButtons.size()];
|
||||||
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
||||||
buttons[i] = this.controlsInput.currentButtons.get(i);
|
buttons[i] = this.controlsInput.currentButtons.get(i);
|
||||||
this.controlsInput.focusedBinding.setButton(buttons);
|
this.controlsInput.focusedBinding.setButton(buttons);
|
||||||
@@ -287,7 +277,7 @@ public class LambdaInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (action == 0 || action == 2) {
|
if (action == 0 || action == 2) {
|
||||||
if (client.currentScreen != null && isScreenInteractive(client.currentScreen)
|
if (client.currentScreen != null
|
||||||
&& (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN
|
&& (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN
|
||||||
|| button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT)) {
|
|| button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT)) {
|
||||||
if (this.actionGuiCooldown == 0) {
|
if (this.actionGuiCooldown == 0) {
|
||||||
@@ -295,11 +285,7 @@ public class LambdaInput {
|
|||||||
this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||||
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN) {
|
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN) {
|
||||||
this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||||
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT) {
|
} else this.handleLeftRight(client.currentScreen, button != GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT);
|
||||||
this.handleLeftRight(client.currentScreen, false);
|
|
||||||
} else {
|
|
||||||
this.handleLeftRight(client.currentScreen, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -308,32 +294,32 @@ public class LambdaInput {
|
|||||||
if (action == 1) {
|
if (action == 1) {
|
||||||
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
|
||||||
if (this.actionGuiCooldown == 0) {
|
if (this.actionGuiCooldown == 0) {
|
||||||
Element focused = client.currentScreen.getFocused();
|
var focused = client.currentScreen.getFocused();
|
||||||
if (focused != null && isScreenInteractive(client.currentScreen)) {
|
if (focused != null && isScreenInteractive(client.currentScreen)) {
|
||||||
if (this.handleAButton(client.currentScreen, focused)) {
|
if (this.handleAButton(client.currentScreen, focused)) {
|
||||||
this.actionGuiCooldown = 5; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
this.actionGuiCooldown = 5; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (FabricLoader.getInstance().isModLoaded("libgui")) LibGuiCompat.handlePress(client.currentScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.handleInventory(client, button)) {
|
|
||||||
this.ignoreNextARelease = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
|
||||||
if (client.currentScreen != null) {
|
if (client.currentScreen != null && client.currentScreen.getClass() != TitleScreen.class) {
|
||||||
if (!LambdaControlsCompat.handleMenuBack(client, client.currentScreen))
|
if (!MidnightControlsCompat.handleMenuBack(client, client.currentScreen))
|
||||||
if (!this.tryGoBack(client.currentScreen))
|
if (!this.tryGoBack(client.currentScreen))
|
||||||
client.currentScreen.onClose();
|
client.currentScreen.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0) {
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen)
|
||||||
|
&& this.actionGuiCooldown == 0) {
|
||||||
|
if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt(
|
||||||
|
client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(),
|
||||||
|
client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()) != null) return;
|
||||||
if (!this.ignoreNextARelease) {
|
if (!this.ignoreNextARelease) {
|
||||||
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||||
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||||
@@ -344,88 +330,27 @@ public class LambdaInput {
|
|||||||
Screen.wrapScreenError(() -> client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1),
|
Screen.wrapScreenError(() -> client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1),
|
||||||
"mouseReleased event handler", client.currentScreen.getClass().getCanonicalName());
|
"mouseReleased event handler", client.currentScreen.getClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
this.actionGuiCooldown = 5;
|
this.screenCloseCooldown = 5;
|
||||||
} else {
|
} else {
|
||||||
this.ignoreNextARelease = false;
|
this.ignoreNextARelease = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles inventory interaction.
|
|
||||||
*
|
|
||||||
* @param client The client instance.
|
|
||||||
* @param button The button pressed.
|
|
||||||
* @return True if an inventory interaction was done.
|
|
||||||
*/
|
|
||||||
private boolean handleInventory(@NotNull MinecraftClient client, int button) {
|
|
||||||
if (!(client.currentScreen instanceof HandledScreen))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (client.interactionManager == null || client.player == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (this.inventoryInteractionCooldown > 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
|
|
||||||
client.player.closeHandledScreen();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
|
||||||
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
|
||||||
|
|
||||||
HandledScreen screen = (HandledScreen) client.currentScreen;
|
|
||||||
HandledScreenAccessor accessor = (HandledScreenAccessor) screen;
|
|
||||||
Slot slot = ((HandledScreenAccessor) client.currentScreen).lambdacontrols$getSlotAt(x, y);
|
|
||||||
|
|
||||||
int slotId;
|
|
||||||
if (slot == null) {
|
|
||||||
if (client.player.inventory.getCursorStack().isEmpty())
|
|
||||||
return false;
|
|
||||||
slotId = accessor.lambdacontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1;
|
|
||||||
} else {
|
|
||||||
slotId = slot.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
SlotActionType actionType = SlotActionType.PICKUP;
|
|
||||||
int clickData = GLFW.GLFW_MOUSE_BUTTON_1;
|
|
||||||
switch (button) {
|
|
||||||
case GLFW_GAMEPAD_BUTTON_A:
|
|
||||||
if (screen instanceof CreativeInventoryScreen)
|
|
||||||
if (((CreativeInventoryScreenAccessor) screen).lambdacontrols$isCreativeInventorySlot(slot))
|
|
||||||
actionType = SlotActionType.CLONE;
|
|
||||||
if (slot != null && LambdaControlsCompat.streamCompatHandlers().anyMatch(handler -> handler.isCreativeSlot(screen, slot)))
|
|
||||||
actionType = SlotActionType.CLONE;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_X:
|
|
||||||
clickData = GLFW_MOUSE_BUTTON_2;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_Y:
|
|
||||||
actionType = SlotActionType.QUICK_MOVE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
accessor.lambdacontrols$onMouseClick(slot, slotId, clickData, actionType);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to go back.
|
* Tries to go back.
|
||||||
*
|
*
|
||||||
* @param screen The current screen.
|
* @param screen the current screen
|
||||||
* @return True if successful, else false.
|
* @return true if successful, else false
|
||||||
*/
|
*/
|
||||||
public boolean tryGoBack(@NotNull Screen screen) {
|
public boolean tryGoBack(@NotNull Screen screen) {
|
||||||
ImmutableSet<String> set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
|
var set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
|
||||||
return screen.children().stream().filter(element -> element instanceof AbstractPressableButtonWidget)
|
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||||
.map(element -> (AbstractPressableButtonWidget) element)
|
.map(element -> (PressableWidget) element)
|
||||||
.filter(element -> element.getMessage() instanceof TranslatableText)
|
.filter(element -> element.getMessage() != null)
|
||||||
.anyMatch(element -> {
|
.anyMatch(element -> {
|
||||||
if (set.stream().anyMatch(key -> key.equals(((TranslatableText) element.getMessage()).getKey()))) {
|
if (set.stream().anyMatch(key -> element.getMessage().toString().equals(key))) {
|
||||||
element.onPress();
|
element.onPress();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -434,44 +359,57 @@ public class LambdaInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private double getDeadZoneValue(int axis) {
|
private double getDeadZoneValue(int axis) {
|
||||||
return (axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y) ? this.config.getLeftDeadZone()
|
return (axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y) ? MidnightControlsConfig.leftDeadZone
|
||||||
: this.config.getRightDeadZone();
|
: MidnightControlsConfig.rightDeadZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) {
|
private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) {
|
||||||
int asButtonState = value > .5f ? 1 : (value < -.5f ? 2 : 0);
|
int asButtonState = value > .5f ? 1 : (value < -.5f ? 2 : 0);
|
||||||
|
|
||||||
|
|
||||||
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
|
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
|
||||||
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER)
|
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER)
|
||||||
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER))
|
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) {
|
||||||
if (asButtonState == 2)
|
if (asButtonState == 2) {
|
||||||
asButtonState = 0;
|
asButtonState = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Fixes Triggers not working correctly on some controllers
|
||||||
|
if (MidnightControlsConfig.triggerFix) {
|
||||||
|
value = 1.0f;
|
||||||
|
absValue = 1.0f;
|
||||||
|
state = 1;
|
||||||
|
asButtonState = 1;
|
||||||
|
}
|
||||||
|
if (MidnightControlsConfig.debug) System.out.println(axis + " "+ value + " " + absValue + " " + state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
boolean currentPlusState = asButtonState == 1;
|
boolean currentPlusState = asButtonState == 1;
|
||||||
boolean currentMinusState = asButtonState == 2;
|
boolean currentMinusState = asButtonState == 2;
|
||||||
ButtonState previousPlusState = InputManager.STATES.getOrDefault(axisAsButton(axis, true), ButtonState.NONE);
|
var previousPlusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, true), ButtonState.NONE);
|
||||||
ButtonState previousMinusState = InputManager.STATES.getOrDefault(axisAsButton(axis, false), ButtonState.NONE);
|
var previousMinusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, false), ButtonState.NONE);
|
||||||
|
|
||||||
if (currentPlusState != previousPlusState.isPressed()) {
|
if (currentPlusState != previousPlusState.isPressed()) {
|
||||||
InputManager.STATES.put(axisAsButton(axis, true), currentPlusState ? ButtonState.PRESS : ButtonState.RELEASE);
|
InputManager.STATES.put(ButtonBinding.axisAsButton(axis, true), currentPlusState ? ButtonState.PRESS : ButtonState.RELEASE);
|
||||||
if (currentPlusState)
|
if (currentPlusState)
|
||||||
BUTTON_COOLDOWNS.put(axisAsButton(axis, true), 5);
|
BUTTON_COOLDOWNS.put(ButtonBinding.axisAsButton(axis, true), 5);
|
||||||
} else if (currentPlusState) {
|
} else if (currentPlusState) {
|
||||||
InputManager.STATES.put(axisAsButton(axis, true), ButtonState.REPEAT);
|
InputManager.STATES.put(ButtonBinding.axisAsButton(axis, true), ButtonState.REPEAT);
|
||||||
if (BUTTON_COOLDOWNS.getOrDefault(axisAsButton(axis, true), 0) == 0) {
|
if (BUTTON_COOLDOWNS.getOrDefault(ButtonBinding.axisAsButton(axis, true), 0) == 0) {
|
||||||
BUTTON_COOLDOWNS.put(axisAsButton(axis, true), 5);
|
BUTTON_COOLDOWNS.put(ButtonBinding.axisAsButton(axis, true), 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentMinusState != previousMinusState.isPressed()) {
|
if (currentMinusState != previousMinusState.isPressed()) {
|
||||||
InputManager.STATES.put(axisAsButton(axis, false), currentMinusState ? ButtonState.PRESS : ButtonState.RELEASE);
|
InputManager.STATES.put(ButtonBinding.axisAsButton(axis, false), currentMinusState ? ButtonState.PRESS : ButtonState.RELEASE);
|
||||||
if (currentMinusState)
|
if (currentMinusState)
|
||||||
BUTTON_COOLDOWNS.put(axisAsButton(axis, false), 5);
|
BUTTON_COOLDOWNS.put(ButtonBinding.axisAsButton(axis, false), 5);
|
||||||
} else if (currentMinusState) {
|
} else if (currentMinusState) {
|
||||||
InputManager.STATES.put(axisAsButton(axis, false), ButtonState.REPEAT);
|
InputManager.STATES.put(ButtonBinding.axisAsButton(axis, false), ButtonState.REPEAT);
|
||||||
if (BUTTON_COOLDOWNS.getOrDefault(axisAsButton(axis, false), 0) == 0) {
|
if (BUTTON_COOLDOWNS.getOrDefault(ButtonBinding.axisAsButton(axis, false), 0) == 0) {
|
||||||
BUTTON_COOLDOWNS.put(axisAsButton(axis, false), 5);
|
BUTTON_COOLDOWNS.put(ButtonBinding.axisAsButton(axis, false), 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,23 +417,23 @@ public class LambdaInput {
|
|||||||
float axisValue = absValue < deadZone ? 0.f : (float) (absValue - deadZone);
|
float axisValue = absValue < deadZone ? 0.f : (float) (absValue - deadZone);
|
||||||
axisValue /= (1.0 - deadZone);
|
axisValue /= (1.0 - deadZone);
|
||||||
|
|
||||||
axisValue = (float) Math.min(axisValue / this.config.getAxisMaxValue(axis), 1);
|
axisValue = (float) Math.min(axisValue / MidnightControlsConfig.getAxisMaxValue(axis), 1);
|
||||||
if (currentPlusState)
|
if (currentPlusState)
|
||||||
InputManager.BUTTON_VALUES.put(axisAsButton(axis, true), axisValue);
|
InputManager.BUTTON_VALUES.put(ButtonBinding.axisAsButton(axis, true), axisValue);
|
||||||
else
|
else
|
||||||
InputManager.BUTTON_VALUES.put(axisAsButton(axis, true), 0.f);
|
InputManager.BUTTON_VALUES.put(ButtonBinding.axisAsButton(axis, true), 0.f);
|
||||||
if (currentMinusState)
|
if (currentMinusState)
|
||||||
InputManager.BUTTON_VALUES.put(axisAsButton(axis, false), axisValue);
|
InputManager.BUTTON_VALUES.put(ButtonBinding.axisAsButton(axis, false), axisValue);
|
||||||
else
|
else
|
||||||
InputManager.BUTTON_VALUES.put(axisAsButton(axis, false), 0.f);
|
InputManager.BUTTON_VALUES.put(ButtonBinding.axisAsButton(axis, false), 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
double deadZone = this.getDeadZoneValue(axis);
|
double deadZone = this.getDeadZoneValue(axis);
|
||||||
|
|
||||||
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
||||||
if (asButtonState != 0 && !this.controlsInput.currentButtons.contains(axisAsButton(axis, asButtonState == 1))) {
|
if (asButtonState != 0 && !this.controlsInput.currentButtons.contains(ButtonBinding.axisAsButton(axis, asButtonState == 1))) {
|
||||||
|
|
||||||
this.controlsInput.currentButtons.add(axisAsButton(axis, asButtonState == 1));
|
this.controlsInput.currentButtons.add(ButtonBinding.axisAsButton(axis, asButtonState == 1));
|
||||||
|
|
||||||
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
||||||
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
||||||
@@ -505,45 +443,71 @@ public class LambdaInput {
|
|||||||
this.controlsInput.waiting = false;
|
this.controlsInput.waiting = false;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (client.currentScreen instanceof CreativeInventoryScreen) {
|
} else if (client.currentScreen instanceof CreativeInventoryScreen creativeInventoryScreen) {
|
||||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||||
CreativeInventoryScreen screen = (CreativeInventoryScreen) client.currentScreen;
|
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
||||||
CreativeInventoryScreenAccessor accessor = (CreativeInventoryScreenAccessor) screen;
|
|
||||||
// @TODO allow rebinding to left stick
|
// @TODO allow rebinding to left stick
|
||||||
if (accessor.lambdacontrols$hasScrollbar() && absValue >= deadZone) {
|
if (accessor.midnightcontrols$hasScrollbar() && absValue >= deadZone) {
|
||||||
screen.mouseScrolled(0.0, 0.0, -value);
|
creativeInventoryScreen.mouseScrolled(0.0, 0.0, -value);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (client.currentScreen instanceof AdvancementsScreen) {
|
} else if (client.currentScreen instanceof MerchantScreen merchantScreen) {
|
||||||
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||||
|
// @TODO allow rebinding to left stick
|
||||||
|
if (absValue >= deadZone) {
|
||||||
|
merchantScreen.mouseScrolled(0.0, 0.0, -(value * 1.5f));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (client.currentScreen instanceof AdvancementsScreen advancementsScreen) {
|
||||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X || axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X || axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||||
AdvancementsScreen screen = (AdvancementsScreen) client.currentScreen;
|
var accessor = (AdvancementsScreenAccessor) advancementsScreen;
|
||||||
AdvancementsScreenAccessor accessor = (AdvancementsScreenAccessor) screen;
|
|
||||||
if (absValue >= deadZone) {
|
if (absValue >= deadZone) {
|
||||||
AdvancementTab tab = accessor.getSelectedTab();
|
AdvancementTab tab = accessor.getSelectedTab();
|
||||||
tab.move(axis == GLFW_GAMEPAD_AXIS_RIGHT_X ? -value * 5.0 : 0.0, axis == GLFW_GAMEPAD_AXIS_RIGHT_Y ? -value * 5.0 : 0.0);
|
tab.move(axis == GLFW_GAMEPAD_AXIS_RIGHT_X ? -value * 5.0 : 0.0, axis == GLFW_GAMEPAD_AXIS_RIGHT_Y ? -value * 5.0 : 0.0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (client.currentScreen != null) {
|
||||||
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y && absValue >= deadZone) {
|
||||||
|
float finalValue = value;
|
||||||
|
client.currentScreen.children().stream().filter(element -> element instanceof SpruceEntryListWidget)
|
||||||
|
.map(element -> (SpruceEntryListWidget<?>) element)
|
||||||
|
.filter(AbstractSpruceWidget::isFocusedOrHovered)
|
||||||
|
.anyMatch(element -> {
|
||||||
|
MidnightControls.get().log(String.valueOf(finalValue));
|
||||||
|
element.mouseScrolled(0.0, 0.0, -finalValue);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
client.currentScreen.children().stream().filter(element -> element instanceof EntryListWidget)
|
||||||
|
.map(element -> (EntryListWidget<?>) element)
|
||||||
|
.filter(element -> element.getType().isFocused())
|
||||||
|
.anyMatch(element -> {
|
||||||
|
element.mouseScrolled(0.0, 0.0, -finalValue);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
absValue -= deadZone;
|
absValue -= deadZone;
|
||||||
absValue /= (1.0 - deadZone);
|
absValue /= (1.0 - deadZone);
|
||||||
absValue = (float) MathHelper.clamp(absValue / this.config.getAxisMaxValue(axis), 0.f, 1.f);
|
absValue = (float) MathHelper.clamp(absValue / MidnightControlsConfig.getAxisMaxValue(axis), 0.f, 1.f);
|
||||||
if (client.currentScreen == null) {
|
if (client.currentScreen == null) {
|
||||||
// Handles the look direction.
|
// Handles the look direction.
|
||||||
this.handleLook(client, axis, absValue, state);
|
this.handleLook(client, axis, absValue, state);
|
||||||
} else {
|
} else {
|
||||||
boolean allowMouseControl = true;
|
boolean allowMouseControl = true;
|
||||||
|
|
||||||
if (this.actionGuiCooldown == 0 && this.config.isMovementAxis(axis) && isScreenInteractive(client.currentScreen)) {
|
if (this.actionGuiCooldown == 0 && MidnightControlsConfig.isMovementAxis(axis) && isScreenInteractive(client.currentScreen)) {
|
||||||
if (this.config.isForwardButton(axis, false, asButtonState)) {
|
if (MidnightControlsConfig.isForwardButton(axis, false, asButtonState)) {
|
||||||
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||||
} else if (this.config.isBackButton(axis, false, asButtonState)) {
|
} else if (MidnightControlsConfig.isBackButton(axis, false, asButtonState)) {
|
||||||
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||||
} else if (this.config.isLeftButton(axis, false, asButtonState)) {
|
} else if (MidnightControlsConfig.isLeftButton(axis, false, asButtonState)) {
|
||||||
allowMouseControl = this.handleLeftRight(client.currentScreen, false);
|
allowMouseControl = this.handleLeftRight(client.currentScreen, false);
|
||||||
} else if (this.config.isRightButton(axis, false, asButtonState)) {
|
} else if (MidnightControlsConfig.isRightButton(axis, false, asButtonState)) {
|
||||||
allowMouseControl = this.handleLeftRight(client.currentScreen, true);
|
allowMouseControl = this.handleLeftRight(client.currentScreen, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -551,13 +515,13 @@ public class LambdaInput {
|
|||||||
float movementX = 0.f;
|
float movementX = 0.f;
|
||||||
float movementY = 0.f;
|
float movementY = 0.f;
|
||||||
|
|
||||||
if (this.config.isBackButton(axis, false, (value > 0 ? 1 : 2))) {
|
if (MidnightControlsConfig.isBackButton(axis, false, (value > 0 ? 1 : 2))) {
|
||||||
movementY = absValue;
|
movementY = absValue;
|
||||||
} else if (this.config.isForwardButton(axis, false, (value > 0 ? 1 : 2))) {
|
} else if (MidnightControlsConfig.isForwardButton(axis, false, (value > 0 ? 1 : 2))) {
|
||||||
movementY = -absValue;
|
movementY = -absValue;
|
||||||
} else if (this.config.isLeftButton(axis, false, (value > 0 ? 1 : 2))) {
|
} else if (MidnightControlsConfig.isLeftButton(axis, false, (value > 0 ? 1 : 2))) {
|
||||||
movementX = -absValue;
|
movementX = -absValue;
|
||||||
} else if (this.config.isRightButton(axis, false, (value > 0 ? 1 : 2))) {
|
} else if (MidnightControlsConfig.isRightButton(axis, false, (value > 0 ? 1 : 2))) {
|
||||||
movementX = absValue;
|
movementX = absValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,7 +533,7 @@ public class LambdaInput {
|
|||||||
It prevents the cursor to jump to the old target mouse position if the user moves the cursor with the mouse.
|
It prevents the cursor to jump to the old target mouse position if the user moves the cursor with the mouse.
|
||||||
*/
|
*/
|
||||||
if (Math.abs(prevXAxis) < deadZone && Math.abs(prevYAxis) < deadZone) {
|
if (Math.abs(prevXAxis) < deadZone && Math.abs(prevYAxis) < deadZone) {
|
||||||
INPUT_MANAGER.resetMouseTarget(client);
|
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mouseSpeedX = movementX;
|
this.mouseSpeedX = movementX;
|
||||||
@@ -581,8 +545,8 @@ public class LambdaInput {
|
|||||||
|
|
||||||
if (Math.abs(this.mouseSpeedX) >= .05f || Math.abs(this.mouseSpeedY) >= .05f) {
|
if (Math.abs(this.mouseSpeedX) >= .05f || Math.abs(this.mouseSpeedY) >= .05f) {
|
||||||
InputManager.queueMoveMousePosition(
|
InputManager.queueMoveMousePosition(
|
||||||
this.mouseSpeedX * this.config.getMouseSpeed(),
|
this.mouseSpeedX * MidnightControlsConfig.mouseSpeed,
|
||||||
this.mouseSpeedY * this.config.getMouseSpeed()
|
this.mouseSpeedY * MidnightControlsConfig.mouseSpeed
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,37 +558,33 @@ public class LambdaInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
|
public boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
|
||||||
if (focused instanceof AbstractPressableButtonWidget) {
|
if (focused instanceof PressableWidget widget) {
|
||||||
AbstractPressableButtonWidget widget = (AbstractPressableButtonWidget) focused;
|
|
||||||
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
|
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
|
||||||
widget.onPress();
|
widget.onPress();
|
||||||
return true;
|
return true;
|
||||||
} else if (focused instanceof AbstractSprucePressableButtonWidget) {
|
} else if (focused instanceof AbstractSprucePressableButtonWidget widget) {
|
||||||
AbstractSprucePressableButtonWidget widget = (AbstractSprucePressableButtonWidget) focused;
|
|
||||||
widget.playDownSound();
|
widget.playDownSound();
|
||||||
widget.onPress();
|
widget.onPress();
|
||||||
return true;
|
return true;
|
||||||
} else if (focused instanceof SpruceLabelWidget) {
|
} else if (focused instanceof SpruceLabelWidget labelWidget) {
|
||||||
((SpruceLabelWidget) focused).onPress();
|
labelWidget.onPress();
|
||||||
return true;
|
return true;
|
||||||
} else if (focused instanceof WorldListWidget) {
|
} else if (focused instanceof WorldListWidget list) {
|
||||||
WorldListWidget list = (WorldListWidget) focused;
|
|
||||||
list.getSelectedAsOptional().ifPresent(WorldListWidget.Entry::play);
|
list.getSelectedAsOptional().ifPresent(WorldListWidget.Entry::play);
|
||||||
return true;
|
return true;
|
||||||
} else if (focused instanceof MultiplayerServerListWidget) {
|
} else if (focused instanceof MultiplayerServerListWidget list) {
|
||||||
MultiplayerServerListWidget list = (MultiplayerServerListWidget) focused;
|
var entry = list.getSelectedOrNull();
|
||||||
MultiplayerServerListWidget.Entry entry = list.getSelected();
|
|
||||||
if (entry instanceof MultiplayerServerListWidget.LanServerEntry || entry instanceof MultiplayerServerListWidget.ServerEntry) {
|
if (entry instanceof MultiplayerServerListWidget.LanServerEntry || entry instanceof MultiplayerServerListWidget.ServerEntry) {
|
||||||
((MultiplayerScreen) screen).select(entry);
|
((MultiplayerScreen) screen).select(entry);
|
||||||
((MultiplayerScreen) screen).connect();
|
((MultiplayerScreen) screen).connect();
|
||||||
}
|
}
|
||||||
} else if (focused instanceof SpruceParentWidget) {
|
} else if (focused instanceof SpruceParentWidget) {
|
||||||
Element childFocused = ((SpruceParentWidget<?>) focused).getFocused();
|
var childFocused = ((SpruceParentWidget<?>) focused).getFocused();
|
||||||
if (childFocused != null)
|
if (childFocused != null)
|
||||||
return this.handleAButton(screen, childFocused);
|
return this.handleAButton(screen, childFocused);
|
||||||
} else if (focused instanceof ParentElement) {
|
} else if (focused instanceof ParentElement widget) {
|
||||||
Element childFocused = ((ParentElement) focused).getFocused();
|
var childFocused = widget.getFocused();
|
||||||
if (childFocused != null)
|
if (childFocused != null)
|
||||||
return this.handleAButton(screen, childFocused);
|
return this.handleAButton(screen, childFocused);
|
||||||
}
|
}
|
||||||
@@ -634,16 +594,16 @@ public class LambdaInput {
|
|||||||
/**
|
/**
|
||||||
* Handles the left and right buttons.
|
* Handles the left and right buttons.
|
||||||
*
|
*
|
||||||
* @param screen The current screen.
|
* @param screen the current screen
|
||||||
* @param right True if the right button is pressed, else false.
|
* @param right true if the right button is pressed, else false
|
||||||
*/
|
*/
|
||||||
private boolean handleLeftRight(@NotNull Screen screen, boolean right) {
|
private boolean handleLeftRight(@NotNull Screen screen, boolean right) {
|
||||||
if (screen instanceof SpruceScreen) {
|
if (screen instanceof SpruceScreen spruceScreen) {
|
||||||
((SpruceScreen) screen).onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
spruceScreen.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
||||||
this.actionGuiCooldown = 5;
|
this.actionGuiCooldown = 5;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Element focused = screen.getFocused();
|
var focused = screen.getFocused();
|
||||||
if (focused != null)
|
if (focused != null)
|
||||||
if (this.handleRightLeftElement(focused, right))
|
if (this.handleRightLeftElement(focused, right))
|
||||||
return this.changeFocus(screen, right ? NavigationDirection.RIGHT : NavigationDirection.LEFT);
|
return this.changeFocus(screen, right ? NavigationDirection.RIGHT : NavigationDirection.LEFT);
|
||||||
@@ -651,22 +611,20 @@ public class LambdaInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleRightLeftElement(@NotNull Element element, boolean right) {
|
private boolean handleRightLeftElement(@NotNull Element element, boolean right) {
|
||||||
if (element instanceof SpruceElement) {
|
if (element instanceof SpruceElement spruceElement) {
|
||||||
if (((SpruceElement) element).requiresCursor())
|
if (spruceElement.requiresCursor())
|
||||||
return true;
|
return true;
|
||||||
return !((SpruceElement) element).onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
return !spruceElement.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
||||||
}
|
}
|
||||||
if (element instanceof SliderWidget) {
|
if (element instanceof SliderWidget slider) {
|
||||||
SliderWidget slider = (SliderWidget) element;
|
|
||||||
slider.keyPressed(right ? 262 : 263, 0, 0);
|
slider.keyPressed(right ? 262 : 263, 0, 0);
|
||||||
this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
||||||
return false;
|
return false;
|
||||||
} else if (element instanceof AlwaysSelectedEntryListWidget) {
|
} else if (element instanceof AlwaysSelectedEntryListWidget) {
|
||||||
((EntryListWidgetAccessor) element).lambdacontrols$moveSelection(right ? EntryListWidget.MoveDirection.UP : EntryListWidget.MoveDirection.DOWN);
|
((EntryListWidgetAccessor) element).midnightcontrols$moveSelection(right ? EntryListWidget.MoveDirection.DOWN : EntryListWidget.MoveDirection.UP);
|
||||||
return false;
|
return false;
|
||||||
} else if (element instanceof ParentElement) {
|
} else if (element instanceof ParentElement entryList) {
|
||||||
ParentElement entryList = (ParentElement) element;
|
var focused = entryList.getFocused();
|
||||||
Element focused = entryList.getFocused();
|
|
||||||
if (focused == null)
|
if (focused == null)
|
||||||
return true;
|
return true;
|
||||||
return this.handleRightLeftElement(focused, right);
|
return this.handleRightLeftElement(focused, right);
|
||||||
@@ -677,10 +635,10 @@ public class LambdaInput {
|
|||||||
/**
|
/**
|
||||||
* Handles the look direction input.
|
* Handles the look direction input.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param axis The axis to change.
|
* @param axis the axis to change
|
||||||
* @param value The value of the look.
|
* @param value the value of the look
|
||||||
* @param state The state.
|
* @param state the state
|
||||||
*/
|
*/
|
||||||
public void handleLook(@NotNull MinecraftClient client, int axis, float value, int state) {
|
public void handleLook(@NotNull MinecraftClient client, int axis, float value, int state) {
|
||||||
// Handles the look direction.
|
// Handles the look direction.
|
||||||
@@ -688,52 +646,120 @@ public class LambdaInput {
|
|||||||
double powValue = Math.pow(value, 2.0);
|
double powValue = Math.pow(value, 2.0);
|
||||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||||
if (state == 2) {
|
if (state == 2) {
|
||||||
this.targetPitch = -this.config.getRightYAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.11D;
|
this.targetPitch = -MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powValue) * 0.11D;
|
||||||
} else if (state == 1) {
|
} else if (state == 1) {
|
||||||
this.targetPitch = this.config.getRightYAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.11D;
|
this.targetPitch = MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powValue) * 0.11D;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
|
||||||
if (state == 2) {
|
if (state == 2) {
|
||||||
this.targetYaw = -this.config.getRightXAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.11D;
|
this.targetYaw = -MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
|
||||||
} else if (state == 1) {
|
} else if (state == 1) {
|
||||||
this.targetYaw = this.config.getRightXAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.11D;
|
this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean changeFocus(@NotNull Screen screen, NavigationDirection direction) {
|
private boolean changeFocus(@NotNull Screen screen, NavigationDirection direction) {
|
||||||
if (screen instanceof SpruceScreen) {
|
if (!isScreenInteractive(screen) && !screen.getClass().getCanonicalName().contains("me.jellysquid.mods.sodium.client.gui")) return false;
|
||||||
if (((SpruceScreen) screen).onNavigation(direction, false)) {
|
try {
|
||||||
this.actionGuiCooldown = 5;
|
if (screen instanceof SpruceScreen spruceScreen) {
|
||||||
|
if (spruceScreen.onNavigation(direction, false)) {
|
||||||
|
this.actionGuiCooldown = 5;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
if (FabricLoader.getInstance().isModLoaded("sodium"))
|
||||||
}
|
SodiumCompat.handleInput(screen, direction.isLookingForward());
|
||||||
if (!screen.changeFocus(direction.isLookingForward())) {
|
// This still needs some work
|
||||||
if (screen.changeFocus(direction.isLookingForward())) {
|
// ScreenAccessor accessor = (ScreenAccessor) screen;
|
||||||
|
// if (accessor.getSelected() != null && accessor.getSelected() instanceof ClickableWidget selected && accessor.getSelectables() != null) {
|
||||||
|
// //System.out.println(direction);
|
||||||
|
// if (accessor.getSelectables().size() >= 2) {
|
||||||
|
// //System.out.println(direction + " 2");
|
||||||
|
// int xDifference = Integer.MAX_VALUE;
|
||||||
|
// int yDifference = Integer.MAX_VALUE;
|
||||||
|
// ClickableWidget newWidget = null;
|
||||||
|
// for (int i = 0; i < accessor.getSelectables().size(); ++i) {
|
||||||
|
// if (accessor.getSelectables().get(i) instanceof ClickableWidget candidate) {
|
||||||
|
// if (!(candidate.x == selected.x && candidate.y == selected.y)) {
|
||||||
|
// int canXDifference = Math.abs(candidate.x - selected.x);
|
||||||
|
// int canYDifference = Math.abs(candidate.y - selected.y);
|
||||||
|
// if (direction.isHorizontal()) {
|
||||||
|
// if (direction.isLookingForward()) {
|
||||||
|
// if (candidate.x >= selected.x && canYDifference <= yDifference && canXDifference <= xDifference) {
|
||||||
|
// System.out.println(direction + " forward horizontal " + candidate);
|
||||||
|
// newWidget = candidate;
|
||||||
|
// xDifference = canXDifference;
|
||||||
|
// yDifference = canYDifference;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (candidate.x <= selected.x && canYDifference <= yDifference && canXDifference >= xDifference) {
|
||||||
|
// System.out.println(direction + " backward horizontal " + candidate);
|
||||||
|
// newWidget = candidate;
|
||||||
|
// xDifference = canXDifference;
|
||||||
|
// yDifference = canYDifference;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (direction.isLookingForward()) {
|
||||||
|
// if (candidate.y >= selected.y && canYDifference <= yDifference && canXDifference <= xDifference) {
|
||||||
|
// System.out.println(direction + " forward vertical " + candidate);
|
||||||
|
// newWidget = candidate;
|
||||||
|
// xDifference = canXDifference;
|
||||||
|
// yDifference = canYDifference;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (candidate.y <= selected.y && canYDifference >= yDifference && canXDifference <= xDifference) {
|
||||||
|
// System.out.println(direction + " backward vertical " + candidate);
|
||||||
|
// newWidget = candidate;
|
||||||
|
// xDifference = canXDifference;
|
||||||
|
// yDifference = canYDifference;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (newWidget != null) {
|
||||||
|
// //selected.changeFocus(true);
|
||||||
|
// ((ClickableWidgetAccessor) selected).setFocused(false);
|
||||||
|
// ((ClickableWidgetAccessor) newWidget).setFocused(true);
|
||||||
|
// screen.setFocused(newWidget);
|
||||||
|
// screen.changeFocus(false);
|
||||||
|
// screen.changeFocus(true);
|
||||||
|
// this.actionGuiCooldown = 5;
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (!screen.changeFocus(direction.isLookingForward())) {
|
||||||
|
if (screen.changeFocus(direction.isLookingForward())) {
|
||||||
|
this.actionGuiCooldown = 5;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
this.actionGuiCooldown = 5;
|
this.actionGuiCooldown = 5;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
} catch (Exception exception) {MidnightControls.get().warn("Unknown exception encountered while trying to change focus: "+exception);}
|
||||||
} else {
|
return false;
|
||||||
this.actionGuiCooldown = 5;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isScreenInteractive(@NotNull Screen screen) {
|
public static boolean isScreenInteractive(@NotNull Screen screen) {
|
||||||
return !(screen instanceof AdvancementsScreen || screen instanceof HandledScreen || screen instanceof PackScreen
|
return !(screen instanceof HandledScreen || MidnightControlsConfig.mouseScreens.stream().anyMatch(a -> screen.getClass().toString().contains(a))
|
||||||
|| (screen instanceof SpruceScreen && ((SpruceScreen) screen).requiresCursor())
|
|| (screen instanceof SpruceScreen && ((SpruceScreen) screen).requiresCursor())
|
||||||
|| LambdaControlsCompat.requireMouseOnScreen(screen));
|
|| MidnightControlsCompat.requireMouseOnScreen(screen));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
|
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
|
||||||
private void moveMouseToClosestSlot(@NotNull MinecraftClient client, @Nullable Screen screen) {
|
private void moveMouseToClosestSlot(@NotNull MinecraftClient client, @Nullable Screen screen) {
|
||||||
// Makes the mouse attracted to slots. This helps with selecting items when using a controller.
|
// Makes the mouse attracted to slots. This helps with selecting items when using a controller.
|
||||||
if (screen instanceof HandledScreen) {
|
if (screen instanceof HandledScreen inventoryScreen) {
|
||||||
HandledScreen inventoryScreen = (HandledScreen) screen;
|
var accessor = (HandledScreenAccessor) inventoryScreen;
|
||||||
HandledScreenAccessor accessor = (HandledScreenAccessor) inventoryScreen;
|
|
||||||
int guiLeft = accessor.getX();
|
int guiLeft = accessor.getX();
|
||||||
int guiTop = accessor.getY();
|
int guiTop = accessor.getY();
|
||||||
int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
||||||
@@ -752,8 +778,8 @@ public class LambdaInput {
|
|||||||
.min(Comparator.comparingDouble(p -> p.value));
|
.min(Comparator.comparingDouble(p -> p.value));
|
||||||
|
|
||||||
if (closestSlot.isPresent()) {
|
if (closestSlot.isPresent()) {
|
||||||
Slot slot = closestSlot.get().key;
|
var slot = closestSlot.get().key;
|
||||||
if (slot.hasStack() || !client.player.inventory.getMainHandStack().isEmpty()) {
|
if (slot.hasStack() || !client.player.getInventory().getMainHandStack().isEmpty()) {
|
||||||
int slotCenterXScaled = guiLeft + slot.x + 8;
|
int slotCenterXScaled = guiLeft + slot.x + 8;
|
||||||
int slotCenterYScaled = guiTop + slot.y + 8;
|
int slotCenterYScaled = guiTop + slot.y + 8;
|
||||||
int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
|
int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControlsFeature;
|
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.FluidBlock;
|
import net.minecraft.block.FluidBlock;
|
||||||
@@ -28,12 +28,12 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the reach-around API of LambdaControls.
|
* Represents the reach-around API of midnightcontrols.
|
||||||
*
|
*
|
||||||
* @version 1.5.0
|
* @version 1.7.0
|
||||||
* @since 1.3.2
|
* @since 1.3.2
|
||||||
*/
|
*/
|
||||||
public class LambdaReacharound {
|
public class MidnightReacharound {
|
||||||
private BlockHitResult lastReacharoundResult = null;
|
private BlockHitResult lastReacharoundResult = null;
|
||||||
private boolean lastReacharoundVertical = false;
|
private boolean lastReacharoundVertical = false;
|
||||||
private boolean onSlab = false;
|
private boolean onSlab = false;
|
||||||
@@ -49,7 +49,7 @@ public class LambdaReacharound {
|
|||||||
/**
|
/**
|
||||||
* Returns the last reach around result.
|
* Returns the last reach around result.
|
||||||
*
|
*
|
||||||
* @return The last reach around result.
|
* @return the last reach around result
|
||||||
*/
|
*/
|
||||||
public @Nullable BlockHitResult getLastReacharoundResult() {
|
public @Nullable BlockHitResult getLastReacharoundResult() {
|
||||||
return this.lastReacharoundResult;
|
return this.lastReacharoundResult;
|
||||||
@@ -58,7 +58,7 @@ public class LambdaReacharound {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the last reach around is vertical.
|
* Returns whether the last reach around is vertical.
|
||||||
*
|
*
|
||||||
* @return True if the reach around is vertical.
|
* @return {@code true} if the reach around is vertical
|
||||||
*/
|
*/
|
||||||
public boolean isLastReacharoundVertical() {
|
public boolean isLastReacharoundVertical() {
|
||||||
return this.lastReacharoundVertical;
|
return this.lastReacharoundVertical;
|
||||||
@@ -67,10 +67,10 @@ public class LambdaReacharound {
|
|||||||
/**
|
/**
|
||||||
* Returns whether reacharound is available or not.
|
* Returns whether reacharound is available or not.
|
||||||
*
|
*
|
||||||
* @return True if reacharound is available, else false.
|
* @return {@code true} if reacharound is available, else {@code false}
|
||||||
*/
|
*/
|
||||||
public boolean isReacharoundAvailable() {
|
public boolean isReacharoundAvailable() {
|
||||||
return LambdaControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || LambdaControlsFeature.VERTICAL_REACHAROUND.isAvailable();
|
return MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getPlayerRange(@NotNull MinecraftClient client) {
|
private float getPlayerRange(@NotNull MinecraftClient client) {
|
||||||
@@ -80,22 +80,22 @@ public class LambdaReacharound {
|
|||||||
/**
|
/**
|
||||||
* Returns a nullable block hit result if vertical reach-around is possible.
|
* Returns a nullable block hit result if vertical reach-around is possible.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @return A block hit result if vertical reach-around is possible, else null.
|
* @return a block hit result if vertical reach-around is possible, else {@code null}
|
||||||
*/
|
*/
|
||||||
public @Nullable BlockHitResult tryVerticalReachAround(@NotNull MinecraftClient client) {
|
public @Nullable BlockHitResult tryVerticalReachAround(@NotNull MinecraftClient client) {
|
||||||
if (!LambdaControlsFeature.VERTICAL_REACHAROUND.isAvailable())
|
if (!MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable())
|
||||||
return null;
|
return null;
|
||||||
if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.MISS
|
if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.MISS
|
||||||
|| !client.player.isOnGround() || client.player.pitch < 80.0F
|
|| !client.player.isOnGround() || client.player.getPitch(0.f) < 80.0F
|
||||||
|| client.player.isRiding())
|
|| client.player.isRiding())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Vec3d pos = client.player.getCameraPosVec(1.0F);
|
Vec3d pos = client.player.getCameraPosVec(1.0F);
|
||||||
Vec3d rotationVec = client.player.getRotationVec(1.0F);
|
Vec3d rotationVec = client.player.getRotationVec(1.0F);
|
||||||
float range = getPlayerRange(client);
|
float range = getPlayerRange(client);
|
||||||
Vec3d rayVec = pos.add(rotationVec.x * range, rotationVec.y * range, rotationVec.z * range).add(0, 0.75, 0);
|
var rayVec = pos.add(rotationVec.x * range, rotationVec.y * range, rotationVec.z * range).add(0, 0.75, 0);
|
||||||
BlockHitResult result = client.world.raycast(new RaycastContext(pos, rayVec, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player));
|
var result = client.world.raycast(new RaycastContext(pos, rayVec, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player));
|
||||||
|
|
||||||
if (result.getType() == HitResult.Type.BLOCK) {
|
if (result.getType() == HitResult.Type.BLOCK) {
|
||||||
BlockPos blockPos = result.getBlockPos().down();
|
BlockPos blockPos = result.getBlockPos().down();
|
||||||
@@ -112,38 +112,39 @@ public class LambdaReacharound {
|
|||||||
/**
|
/**
|
||||||
* Returns a nullable block hit result if horizontal reach-around is possible.
|
* Returns a nullable block hit result if horizontal reach-around is possible.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @return A block hit result if horizontal reach-around is possible.
|
* @return a block hit result if horizontal reach-around is possible
|
||||||
*/
|
*/
|
||||||
public @Nullable BlockHitResult tryHorizontalReachAround(@NotNull MinecraftClient client) {
|
public @Nullable BlockHitResult tryHorizontalReachAround(@NotNull MinecraftClient client) {
|
||||||
if (!LambdaControlsFeature.HORIZONTAL_REACHAROUND.isAvailable())
|
if (!MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS && client.player.isOnGround() && client.player.pitch > 35.0F) {
|
if (client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS
|
||||||
|
&& client.player.isOnGround() && client.player.getPitch(0.f) > 35.f) {
|
||||||
if (client.player.isRiding())
|
if (client.player.isRiding())
|
||||||
return null;
|
return null;
|
||||||
BlockPos playerPos = client.player.getBlockPos().down();
|
var playerPos = client.player.getBlockPos().down();
|
||||||
if (client.player.getY() - playerPos.getY() - 1.0 >= 0.25) {
|
if (client.player.getY() - playerPos.getY() - 1.0 >= 0.25) {
|
||||||
playerPos = playerPos.up();
|
playerPos = playerPos.up();
|
||||||
this.onSlab = true;
|
this.onSlab = true;
|
||||||
} else {
|
} else {
|
||||||
this.onSlab = false;
|
this.onSlab = false;
|
||||||
}
|
}
|
||||||
BlockPos targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
|
var targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
|
||||||
BlockPos vector = new BlockPos(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
|
var vector = new BlockPos.Mutable(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
|
||||||
BlockPos blockPos = playerPos.add(vector);
|
var blockPos = playerPos.add(vector);
|
||||||
|
|
||||||
Direction direction = client.player.getHorizontalFacing();
|
var direction = client.player.getHorizontalFacing();
|
||||||
|
|
||||||
BlockState state = client.world.getBlockState(blockPos);
|
var state = client.world.getBlockState(blockPos);
|
||||||
if (!state.isAir())
|
if (!state.isAir())
|
||||||
return null;
|
return null;
|
||||||
BlockState adjacentBlockState = client.world.getBlockState(blockPos.offset(direction.getOpposite()));
|
var adjacentBlockState = client.world.getBlockState(blockPos.offset(direction.getOpposite()));
|
||||||
if (adjacentBlockState.isAir() || adjacentBlockState.getBlock() instanceof FluidBlock || (vector.getX() == 0 && vector.getZ() == 0)) {
|
if (adjacentBlockState.isAir() || adjacentBlockState.getBlock() instanceof FluidBlock || (vector.getX() == 0 && vector.getZ() == 0)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BlockHitResult(client.crosshairTarget.getPos(), direction, blockPos, false);
|
return new BlockHitResult(new Vec3d(blockPos.getX(),blockPos.getY(),blockPos.getZ()), direction, blockPos, false);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client;
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
@@ -20,7 +20,7 @@ import java.util.Optional;
|
|||||||
/**
|
/**
|
||||||
* Represents the virtual mouse skins.
|
* Represents the virtual mouse skins.
|
||||||
*
|
*
|
||||||
* @version 1.4.0
|
* @version 1.7.0
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public enum VirtualMouseSkin implements Nameable {
|
public enum VirtualMouseSkin implements Nameable {
|
||||||
@@ -40,10 +40,10 @@ public enum VirtualMouseSkin implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the next virtual mouse skin available.
|
* Returns the next virtual mouse skin available.
|
||||||
*
|
*
|
||||||
* @return The next available virtual mouse skin.
|
* @return the next available virtual mouse skin
|
||||||
*/
|
*/
|
||||||
public @NotNull VirtualMouseSkin next() {
|
public @NotNull VirtualMouseSkin next() {
|
||||||
VirtualMouseSkin[] v = values();
|
var v = values();
|
||||||
if (v.length == this.ordinal() + 1)
|
if (v.length == this.ordinal() + 1)
|
||||||
return v[0];
|
return v[0];
|
||||||
return v[this.ordinal() + 1];
|
return v[this.ordinal() + 1];
|
||||||
@@ -52,16 +52,16 @@ public enum VirtualMouseSkin implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the translation key of this virtual mouse skin.
|
* Returns the translation key of this virtual mouse skin.
|
||||||
*
|
*
|
||||||
* @return The virtual mouse skin's translation key.
|
* @return the virtual mouse skin's translation key
|
||||||
*/
|
*/
|
||||||
public @NotNull String getTranslationKey() {
|
public @NotNull String getTranslationKey() {
|
||||||
return "lambdacontrols.virtual_mouse.skin." + this.getName();
|
return "midnightcontrols.virtual_mouse.skin." + this.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the translated text of this virtual mouse skin.
|
* Gets the translated text of this virtual mouse skin.
|
||||||
*
|
*
|
||||||
* @return The translated text of this virtual mouse skin.
|
* @return the translated text of this virtual mouse skin
|
||||||
*/
|
*/
|
||||||
public @NotNull Text getTranslatedText() {
|
public @NotNull Text getTranslatedText() {
|
||||||
return this.text;
|
return this.text;
|
||||||
@@ -75,8 +75,8 @@ public enum VirtualMouseSkin implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the virtual mouse skin from its identifier.
|
* Gets the virtual mouse skin from its identifier.
|
||||||
*
|
*
|
||||||
* @param id The identifier of the virtual mouse skin.
|
* @param id the identifier of the virtual mouse skin
|
||||||
* @return The virtual mouse skin if found, else empty.
|
* @return the virtual mouse skin if found, else empty
|
||||||
*/
|
*/
|
||||||
public static @NotNull Optional<VirtualMouseSkin> byId(@NotNull String id) {
|
public static @NotNull Optional<VirtualMouseSkin> byId(@NotNull String id) {
|
||||||
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -23,22 +22,22 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
* Represents a compatibility handler for a mod.
|
* Represents a compatibility handler for a mod.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.5.0
|
* @version 1.7.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public interface CompatHandler {
|
public interface CompatHandler {
|
||||||
/**
|
/**
|
||||||
* Handles compatibility of a mod.
|
* Handles compatibility of a mod.
|
||||||
*
|
*
|
||||||
* @param mod This mod instance.
|
* @param mod this mod instance
|
||||||
*/
|
*/
|
||||||
void handle(@NotNull LambdaControlsClient mod);
|
void handle(@NotNull MidnightControlsClient mod);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the mouse is required on the specified screen.
|
* Returns whether the mouse is required on the specified screen.
|
||||||
*
|
*
|
||||||
* @param screen The screen.
|
* @param screen the screen
|
||||||
* @return True if the mouse is required on the specified screen, else false.
|
* @return true if the mouse is required on the specified screen, else false
|
||||||
*/
|
*/
|
||||||
default boolean requireMouseOnScreen(Screen screen) {
|
default boolean requireMouseOnScreen(Screen screen) {
|
||||||
return false;
|
return false;
|
||||||
@@ -47,22 +46,22 @@ public interface CompatHandler {
|
|||||||
/**
|
/**
|
||||||
* Returns a slot at the specified location if possible.
|
* Returns a slot at the specified location if possible.
|
||||||
*
|
*
|
||||||
* @param screen The screen.
|
* @param screen the screen
|
||||||
* @param mouseX The mouse X-coordinate.
|
* @param mouseX the mouse X-coordinate
|
||||||
* @param mouseY The mouse Y-coordinate.
|
* @param mouseY the mouse Y-coordinate
|
||||||
* @return A slot if present, else null.
|
* @return a slot if present, else null
|
||||||
* @since 1.5.0
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
default @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
|
default @Nullable CompatHandler.SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the current slot is a creative slot or not.
|
* Returns whether the current slot is a creative slot or not.
|
||||||
*
|
*
|
||||||
* @param screen The screen.
|
* @param screen the screen
|
||||||
* @param slot The slot to check.
|
* @param slot the slot to check
|
||||||
* @return True if the slot is a creative slot, else false.
|
* @return true if the slot is a creative slot, else false
|
||||||
*/
|
*/
|
||||||
default boolean isCreativeSlot(@NotNull HandledScreen screen, @NotNull Slot slot) {
|
default boolean isCreativeSlot(@NotNull HandledScreen screen, @NotNull Slot slot) {
|
||||||
return false;
|
return false;
|
||||||
@@ -71,9 +70,9 @@ public interface CompatHandler {
|
|||||||
/**
|
/**
|
||||||
* Returns a custom translation key to make custom attack action strings on the HUD.
|
* Returns a custom translation key to make custom attack action strings on the HUD.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param placeResult The last place block result.
|
* @param placeResult the last place block result
|
||||||
* @return Null if untouched, else a translation key.
|
* @return null if untouched, else a translation key
|
||||||
*/
|
*/
|
||||||
default String getAttackActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
|
default String getAttackActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
|
||||||
return null;
|
return null;
|
||||||
@@ -82,9 +81,9 @@ public interface CompatHandler {
|
|||||||
/**
|
/**
|
||||||
* Returns a custom translation key to make custom use action strings on the HUD.
|
* Returns a custom translation key to make custom use action strings on the HUD.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param placeResult The last place block result.
|
* @param placeResult the last place block result
|
||||||
* @return Null if untouched, else a translation key.
|
* @return null if untouched, else a translation key
|
||||||
*/
|
*/
|
||||||
default String getUseActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
|
default String getUseActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
|
||||||
return null;
|
return null;
|
||||||
@@ -93,11 +92,15 @@ public interface CompatHandler {
|
|||||||
/**
|
/**
|
||||||
* Handles the menu back button.
|
* Handles the menu back button.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param screen The screen.
|
* @param screen the screen
|
||||||
* @return True if the handle was fired and succeed, else false.
|
* @return true if the handle was fired and succeed, else false
|
||||||
*/
|
*/
|
||||||
default boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
default boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record SlotPos(int x, int y) {
|
||||||
|
public static final SlotPos INVALID_SLOT = new SlotPos(-1, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import dev.emi.emi.screen.EmiScreen;
|
||||||
|
import dev.emi.emi.screen.EmiScreenManager;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import org.aperlambda.lambdacommon.Identifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
public class EMICompat implements CompatHandler {
|
||||||
|
public static boolean handleTabs(boolean direction) {
|
||||||
|
if (MidnightControlsClient.get().input.actionGuiCooldown == 0 &&EmiScreenManager.searchLeft != null && EmiScreenManager.searchRight != null) {
|
||||||
|
if (direction) EmiScreenManager.searchRight.onPress();
|
||||||
|
else EmiScreenManager.searchLeft.onPress();
|
||||||
|
MidnightControlsClient.get().input.actionGuiCooldown = 5;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void handle(@NotNull MidnightControlsClient mod) {
|
||||||
|
ButtonCategory category = new ButtonCategory(new Identifier("midnightcontrols","category.emi"));
|
||||||
|
InputManager.registerCategory(category);
|
||||||
|
new ButtonBinding.Builder("emi_page_left")
|
||||||
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||||
|
.category(category)
|
||||||
|
.action((client,action,value,buttonState)->handleTabs(false)).cooldown()
|
||||||
|
.filter(((client, buttonBinding) -> client.currentScreen instanceof HandledScreen<?> || client.currentScreen instanceof EmiScreen))
|
||||||
|
.register();
|
||||||
|
new ButtonBinding.Builder("emi_page_right")
|
||||||
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||||
|
.category(category)
|
||||||
|
.action((client,action,value,buttonState)->handleTabs(true)).cooldown()
|
||||||
|
.filter(((client, buttonBinding) -> client.currentScreen instanceof HandledScreen<?> || client.currentScreen instanceof EmiScreen))
|
||||||
|
.register();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -30,7 +30,7 @@ public class HQMCompat implements CompatHandler {
|
|||||||
private Optional<Class<?>> guiBaseClass;
|
private Optional<Class<?>> guiBaseClass;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(@NotNull LambdaControlsClient mod) {
|
public void handle(@NotNull MidnightControlsClient mod) {
|
||||||
this.guiBaseClass = LambdaReflection.getClass(GUI_BASE_CLASS_PATH);
|
this.guiBaseClass = LambdaReflection.getClass(GUI_BASE_CLASS_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import io.github.cottonmc.cotton.gui.impl.client.CottonScreenImpl;
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WButton;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.sound.PositionedSoundInstance;
|
||||||
|
import net.minecraft.sound.SoundEvents;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
|
public class LibGuiCompat {
|
||||||
|
public static boolean handlePress(@NotNull Screen screen) {
|
||||||
|
if (screen instanceof CottonScreenImpl cottonScreen) {
|
||||||
|
if (cottonScreen.getDescription() != null && cottonScreen.getDescription().getFocus() != null) {
|
||||||
|
if (cottonScreen.getDescription().getFocus() instanceof WButton button && button.getOnClick() != null) {
|
||||||
|
button.getOnClick().run();
|
||||||
|
MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -31,35 +30,37 @@ import java.util.stream.Stream;
|
|||||||
* @version 1.5.0
|
* @version 1.5.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class LambdaControlsCompat {
|
public class MidnightControlsCompat {
|
||||||
private static final List<CompatHandler> HANDLERS = new ArrayList<>();
|
public static final List<CompatHandler> HANDLERS = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes compatibility with other mods if needed.
|
* Initializes compatibility with other mods if needed.
|
||||||
*
|
*
|
||||||
* @param mod The mod instance.
|
* @param mod the mod instance
|
||||||
*/
|
*/
|
||||||
public static void init(@NotNull LambdaControlsClient mod) {
|
public static void init(@NotNull MidnightControlsClient mod) {
|
||||||
if (FabricLoader.getInstance().isModLoaded("okzoomer")) {
|
// "okzoomer" is the mod ID used by Fabric-compatible versions of Ok Zoomer. (5.0.0-beta.6 and below.)
|
||||||
mod.log("Adding okzoomer compatibility...");
|
// "ok_zoomer" is the mod ID used by Quilt-exclusive versions of Ok Zoomer. (5.0.0-beta.7 and above.)
|
||||||
|
if (FabricLoader.getInstance().isModLoaded("okzoomer") || FabricLoader.getInstance().isModLoaded("ok_zoomer")) {
|
||||||
|
mod.log("Adding Ok Zoomer compatibility...");
|
||||||
HANDLERS.add(new OkZoomerCompat());
|
HANDLERS.add(new OkZoomerCompat());
|
||||||
}
|
}
|
||||||
if (isReiPresent()) {
|
if (isEMIPresent()) {
|
||||||
mod.log("Adding REI compatiblity...");
|
mod.log("Adding EMI compatibility...");
|
||||||
HANDLERS.add(new ReiCompat());
|
HANDLERS.add(new EMICompat());
|
||||||
}
|
}
|
||||||
if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
|
if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
|
||||||
mod.log("Adding HQM compatibility...");
|
mod.log("Adding HQM compatibility...");
|
||||||
HANDLERS.add(new HQMCompat());
|
HANDLERS.add(new HQMCompat());
|
||||||
}
|
}
|
||||||
HANDLERS.forEach(handler -> handler.handle(mod));
|
HANDLERS.forEach(handler -> handler.handle(mod));
|
||||||
InputManager.loadButtonBindings(mod.config);
|
InputManager.loadButtonBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a new compatibility handler.
|
* Registers a new compatibility handler.
|
||||||
*
|
*
|
||||||
* @param handler The compatibility handler to register.
|
* @param handler the compatibility handler to register
|
||||||
*/
|
*/
|
||||||
public static void registerCompatHandler(@NotNull CompatHandler handler) {
|
public static void registerCompatHandler(@NotNull CompatHandler handler) {
|
||||||
HANDLERS.add(handler);
|
HANDLERS.add(handler);
|
||||||
@@ -68,7 +69,7 @@ public class LambdaControlsCompat {
|
|||||||
/**
|
/**
|
||||||
* Streams through compatibility handlers.
|
* Streams through compatibility handlers.
|
||||||
*
|
*
|
||||||
* @return A stream of compatibility handlers.
|
* @return a stream of compatibility handlers
|
||||||
*/
|
*/
|
||||||
public static Stream<CompatHandler> streamCompatHandlers() {
|
public static Stream<CompatHandler> streamCompatHandlers() {
|
||||||
return HANDLERS.stream();
|
return HANDLERS.stream();
|
||||||
@@ -77,8 +78,8 @@ public class LambdaControlsCompat {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the mouse is required on the specified screen.
|
* Returns whether the mouse is required on the specified screen.
|
||||||
*
|
*
|
||||||
* @param screen The screen.
|
* @param screen the screen
|
||||||
* @return True if the mouse is requried on the specified screen, else false.
|
* @return true if the mouse is requried on the specified screen, else false
|
||||||
*/
|
*/
|
||||||
public static boolean requireMouseOnScreen(Screen screen) {
|
public static boolean requireMouseOnScreen(Screen screen) {
|
||||||
return HANDLERS.stream().anyMatch(handler -> handler.requireMouseOnScreen(screen));
|
return HANDLERS.stream().anyMatch(handler -> handler.requireMouseOnScreen(screen));
|
||||||
@@ -87,14 +88,14 @@ public class LambdaControlsCompat {
|
|||||||
/**
|
/**
|
||||||
* Returns a slot at the specified location if possible.
|
* Returns a slot at the specified location if possible.
|
||||||
*
|
*
|
||||||
* @param screen The screen.
|
* @param screen the screen
|
||||||
* @param mouseX The mouse X-coordinate.
|
* @param mouseX the mouse X-coordinate
|
||||||
* @param mouseY The mouse Y-coordinate.
|
* @param mouseY the mouse Y-coordinate
|
||||||
* @return A slot if present, else null.
|
* @return a slot if present, else null
|
||||||
*/
|
*/
|
||||||
public static @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
|
public static @Nullable CompatHandler.SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
|
||||||
for (CompatHandler handler : HANDLERS) {
|
for (var handler : HANDLERS) {
|
||||||
Pair<Integer, Integer> slot = handler.getSlotAt(screen, mouseX, mouseY);
|
var slot = handler.getSlotAt(screen, mouseX, mouseY);
|
||||||
if (slot != null)
|
if (slot != null)
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
@@ -104,9 +105,9 @@ public class LambdaControlsCompat {
|
|||||||
/**
|
/**
|
||||||
* Returns a custom translation key to make custom attack action strings on the HUD.
|
* Returns a custom translation key to make custom attack action strings on the HUD.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param placeResult The last place block result.
|
* @param placeResult the last place block result
|
||||||
* @return Null if untouched, else a translation key.
|
* @return null if untouched, else a translation key
|
||||||
*/
|
*/
|
||||||
public static String getAttackActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
|
public static String getAttackActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
|
||||||
for (CompatHandler handler : HANDLERS) {
|
for (CompatHandler handler : HANDLERS) {
|
||||||
@@ -121,9 +122,9 @@ public class LambdaControlsCompat {
|
|||||||
/**
|
/**
|
||||||
* Returns a custom translation key to make custom use action strings on the HUD.
|
* Returns a custom translation key to make custom use action strings on the HUD.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param placeResult The last place block result.
|
* @param placeResult the last place block result
|
||||||
* @return Null if untouched, else a translation key.
|
* @return null if untouched, else a translation key
|
||||||
*/
|
*/
|
||||||
public static String getUseActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
|
public static String getUseActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
|
||||||
for (CompatHandler handler : HANDLERS) {
|
for (CompatHandler handler : HANDLERS) {
|
||||||
@@ -138,9 +139,9 @@ public class LambdaControlsCompat {
|
|||||||
/**
|
/**
|
||||||
* Handles the menu back button.
|
* Handles the menu back button.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param screen The screen.
|
* @param screen the screen
|
||||||
* @return True if the handle was fired and succeed, else false.
|
* @return true if the handle was fired and succeed, else false
|
||||||
*/
|
*/
|
||||||
public static boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
public static boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
||||||
for (CompatHandler handler : HANDLERS) {
|
for (CompatHandler handler : HANDLERS) {
|
||||||
@@ -153,9 +154,17 @@ public class LambdaControlsCompat {
|
|||||||
/**
|
/**
|
||||||
* Returns whether Roughly Enough Items is present.
|
* Returns whether Roughly Enough Items is present.
|
||||||
*
|
*
|
||||||
* @return True if Roughly Enough Items is present, else false.
|
* @return true if Roughly Enough Items is present, else false
|
||||||
*/
|
*/
|
||||||
public static boolean isReiPresent() {
|
public static boolean isReiPresent() {
|
||||||
return FabricLoader.getInstance().isModLoaded("roughlyenoughitems");
|
return FabricLoader.getInstance().isModLoaded("roughlyenoughitems");
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Returns whether EMI is present.
|
||||||
|
*
|
||||||
|
* @return true if EMI is present, else false
|
||||||
|
*/
|
||||||
|
public static boolean isEMIPresent() {
|
||||||
|
return FabricLoader.getInstance().isModLoaded("emi");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||||
@@ -25,18 +26,15 @@ import java.util.Set;
|
|||||||
* @version 1.5.0
|
* @version 1.5.0
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public class LambdaControlsMixinPlugin implements IMixinConfigPlugin {
|
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
||||||
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>();
|
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>();
|
||||||
|
|
||||||
public LambdaControlsMixinPlugin() {
|
public MidnightControlsMixinPlugin() {
|
||||||
this.putConditionalMixin("EntryListWidgetAccessor", LambdaControlsCompat.isReiPresent());
|
this.putConditionalMixin("SodiumOptionsGUIAccessor", FabricLoader.getInstance().isModLoaded("sodium"));
|
||||||
this.putConditionalMixin("EntryWidgetAccessor", LambdaControlsCompat.isReiPresent());
|
|
||||||
this.putConditionalMixin("RecipeViewingScreenAccessor", LambdaControlsCompat.isReiPresent());
|
|
||||||
this.putConditionalMixin("VillagerRecipeViewingScreenAccessor", LambdaControlsCompat.isReiPresent());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putConditionalMixin(@NotNull String path, boolean condition) {
|
private void putConditionalMixin(@NotNull String path, boolean condition) {
|
||||||
this.conditionalMixins.put("me.lambdaurora.lambdacontrols.client.compat.mixin." + path, condition);
|
this.conditionalMixins.put("eu.midnightdust.midnightcontrols.client.compat.mixin." + path, condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021-2022 Karen/あけみ <karen@akemi.ai>, LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of MidnightControls.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import net.minecraft.client.option.KeyBinding;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a compatibility handler for Ok Zoomer.
|
||||||
|
*
|
||||||
|
* @author Karen/あけみ, LambdAurora
|
||||||
|
* @version 1.4.3
|
||||||
|
* @since 1.1.0
|
||||||
|
*/
|
||||||
|
public class OkZoomerCompat implements CompatHandler {
|
||||||
|
private boolean didAllReflectionCallsSucceed = false;
|
||||||
|
|
||||||
|
private KeyBinding okZoomerZoomKey;
|
||||||
|
private KeyBinding okZoomerIncreaseZoomKey;
|
||||||
|
private KeyBinding okZoomerDecreaseZoomKey;
|
||||||
|
private KeyBinding okZoomerResetZoomKey;
|
||||||
|
|
||||||
|
private Method okZoomerAreExtraKeyBindsEnabledMethod;
|
||||||
|
|
||||||
|
public OkZoomerCompat() {
|
||||||
|
// These strings represent the names of the classes, fields, and methods we use from the Ok Zoomer API
|
||||||
|
String okZoomerZoomKeybindsClassString;
|
||||||
|
|
||||||
|
String okZoomerZoomKeyFieldString;
|
||||||
|
String okZoomerIncreaseZoomKeyFieldString;
|
||||||
|
String okZoomerDecreaseZoomKeyFieldString;
|
||||||
|
String okZoomerResetZoomKeyFieldString;
|
||||||
|
|
||||||
|
String okZoomerAreExtraKeyBindsEnabledMethodNameString;
|
||||||
|
|
||||||
|
// These variables represent the actual objects that we reflect to
|
||||||
|
Class<?> okZoomerZoomKeybindsClass;
|
||||||
|
|
||||||
|
Field okZoomerZoomKeyField;
|
||||||
|
Field okZoomerIncreaseZoomKeyField;
|
||||||
|
Field okZoomerDecreaseZoomKeyField;
|
||||||
|
Field okZoomerResetZoomKeyField;
|
||||||
|
|
||||||
|
// First, we need to determine which version of the Ok Zoomer API we're dealing with here.
|
||||||
|
if (LambdaReflection.doesClassExist("io.github.ennuil.okzoomer.keybinds.ZoomKeybinds")) {
|
||||||
|
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.3+1.17.1/src/main/java/io/github/ennuil/okzoomer/keybinds/ZoomKeybinds.java
|
||||||
|
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.3 or below detected!");
|
||||||
|
|
||||||
|
okZoomerZoomKeybindsClassString = "io.github.ennuil.okzoomer.keybinds.ZoomKeybinds";
|
||||||
|
|
||||||
|
okZoomerZoomKeyFieldString = "zoomKey";
|
||||||
|
okZoomerIncreaseZoomKeyFieldString = "increaseZoomKey";
|
||||||
|
okZoomerDecreaseZoomKeyFieldString = "decreaseZoomKey";
|
||||||
|
okZoomerResetZoomKeyFieldString = "resetZoomKey";
|
||||||
|
|
||||||
|
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeybindsEnabled";
|
||||||
|
} else if (LambdaReflection.doesClassExist("io.github.ennuil.okzoomer.key_binds.ZoomKeyBinds")) {
|
||||||
|
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.6+1.18.2/src/main/java/io/github/ennuil/okzoomer/key_binds/ZoomKeyBinds.java
|
||||||
|
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.6, 5.0.0-beta.5, or 5.0.0-beta.4 detected!");
|
||||||
|
|
||||||
|
okZoomerZoomKeybindsClassString = "io.github.ennuil.okzoomer.key_binds.ZoomKeyBinds";
|
||||||
|
|
||||||
|
okZoomerZoomKeyFieldString = "ZOOM_KEY";
|
||||||
|
okZoomerIncreaseZoomKeyFieldString = "INCREASE_ZOOM_KEY";
|
||||||
|
okZoomerDecreaseZoomKeyFieldString = "DECREASE_ZOOM_KEY";
|
||||||
|
okZoomerResetZoomKeyFieldString = "RESET_ZOOM_KEY";
|
||||||
|
|
||||||
|
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeyBindsEnabled";
|
||||||
|
} else if (LambdaReflection.doesClassExist("io.github.ennuil.ok_zoomer.key_binds.ZoomKeyBinds")) {
|
||||||
|
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.7+1.18.2/src/main/java/io/github/ennuil/ok_zoomer/key_binds/ZoomKeyBinds.java
|
||||||
|
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.7 (Quilt) or above detected!");
|
||||||
|
|
||||||
|
okZoomerZoomKeybindsClassString = "io.github.ennuil.ok_zoomer.key_binds.ZoomKeyBinds";
|
||||||
|
|
||||||
|
okZoomerZoomKeyFieldString = "ZOOM_KEY";
|
||||||
|
okZoomerIncreaseZoomKeyFieldString = "INCREASE_ZOOM_KEY";
|
||||||
|
okZoomerDecreaseZoomKeyFieldString = "DECREASE_ZOOM_KEY";
|
||||||
|
okZoomerResetZoomKeyFieldString = "RESET_ZOOM_KEY";
|
||||||
|
|
||||||
|
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeyBindsEnabled";
|
||||||
|
} else {
|
||||||
|
// If all of the above checks fail, then the version of the Ok Zoomer API that the user is trying to use is too new.
|
||||||
|
MidnightControlsClient.get().warn("The version of Ok Zoomer that you are currently using is too new, and is not yet supported by MidnightControls!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflect to the ZoomKeyBinds (>= 5.0.0-beta.4) / ZoomKeybinds (<= 5.0.0-beta.3) class.
|
||||||
|
try {
|
||||||
|
okZoomerZoomKeybindsClass = Class.forName(okZoomerZoomKeybindsClassString);
|
||||||
|
} catch (ClassNotFoundException exception) {
|
||||||
|
// This theoretically should never happen.
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybinds class!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflect to all of the keybind fields.
|
||||||
|
try {
|
||||||
|
okZoomerZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerZoomKeyFieldString);
|
||||||
|
okZoomerIncreaseZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerIncreaseZoomKeyFieldString);
|
||||||
|
okZoomerDecreaseZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerDecreaseZoomKeyFieldString);
|
||||||
|
okZoomerResetZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerResetZoomKeyFieldString);
|
||||||
|
} catch (NoSuchFieldException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybind fields!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise KeyBinding objects
|
||||||
|
try {
|
||||||
|
okZoomerZoomKey = (KeyBinding) okZoomerZoomKeyField.get(null);
|
||||||
|
okZoomerIncreaseZoomKey = (KeyBinding) okZoomerIncreaseZoomKeyField.get(null);
|
||||||
|
okZoomerDecreaseZoomKey = (KeyBinding) okZoomerDecreaseZoomKeyField.get(null);
|
||||||
|
okZoomerResetZoomKey = (KeyBinding) okZoomerResetZoomKeyField.get(null);
|
||||||
|
} catch (IllegalAccessException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybind objects!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflect to the areExtraKeyBindsEnabled (>= 5.0.0-beta.4) / areExtraKeybindsEnabled (<= 5.0.0-beta.3) method.
|
||||||
|
// TODO: Consider replacing this entirely with getExtraKeyBind (>= 5.0.0-beta.4) / getExtraKeybind (<= 5.0.0-beta.3) in the future.
|
||||||
|
try {
|
||||||
|
okZoomerAreExtraKeyBindsEnabledMethod = okZoomerZoomKeybindsClass.getDeclaredMethod(okZoomerAreExtraKeyBindsEnabledMethodNameString);
|
||||||
|
} catch (NoSuchMethodException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls failed to reflect to an Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
didAllReflectionCallsSucceed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(@NotNull MidnightControlsClient mod) {
|
||||||
|
if (didAllReflectionCallsSucceed) {
|
||||||
|
new ButtonBinding.Builder("zoom")
|
||||||
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
|
||||||
|
.onlyInGame()
|
||||||
|
.cooldown(true)
|
||||||
|
.category(ButtonBinding.MISC_CATEGORY)
|
||||||
|
.linkKeybind(okZoomerZoomKey)
|
||||||
|
.register();
|
||||||
|
|
||||||
|
boolean okZoomerAreExtraKeyBindsEnabled = false;
|
||||||
|
try {
|
||||||
|
okZoomerAreExtraKeyBindsEnabled = (boolean) okZoomerAreExtraKeyBindsEnabledMethod.invoke(null);
|
||||||
|
} catch (IllegalAccessException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls encountered an IllegalAccessException while attempting to invoke a reflected Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
} catch (InvocationTargetException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls encountered an InvocationTargetException while attempting to invoke a reflected Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (okZoomerAreExtraKeyBindsEnabled) {
|
||||||
|
new ButtonBinding.Builder("zoom_in")
|
||||||
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||||
|
.onlyInGame()
|
||||||
|
.cooldown(true)
|
||||||
|
.category(ButtonBinding.MISC_CATEGORY)
|
||||||
|
.linkKeybind(okZoomerIncreaseZoomKey)
|
||||||
|
.register();
|
||||||
|
new ButtonBinding.Builder("zoom_out")
|
||||||
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||||
|
.onlyInGame()
|
||||||
|
.cooldown(true)
|
||||||
|
.category(ButtonBinding.MISC_CATEGORY)
|
||||||
|
.linkKeybind(okZoomerDecreaseZoomKey)
|
||||||
|
.register();
|
||||||
|
new ButtonBinding.Builder("zoom_reset")
|
||||||
|
.onlyInGame()
|
||||||
|
.cooldown(true)
|
||||||
|
.category(ButtonBinding.MISC_CATEGORY)
|
||||||
|
.linkKeybind(okZoomerResetZoomKey)
|
||||||
|
.register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.mixin.SodiumOptionsGUIAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||||
|
import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
|
||||||
|
public class SodiumCompat {
|
||||||
|
private static final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
public static void handleInput(Screen screen, boolean direction) {
|
||||||
|
if (screen instanceof SodiumOptionsGUI optionsGUI) {
|
||||||
|
SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI;
|
||||||
|
final int max = accessor.getControls().size()-1;
|
||||||
|
|
||||||
|
var option = accessor.getControls().stream().filter(ControlElement::isHovered).findFirst().orElse(accessor.getControls().get(0));
|
||||||
|
int i = accessor.getControls().indexOf(option);
|
||||||
|
i = (direction ? ((max > i) ? ++i : 0) : (i > 0 ? --i : max));
|
||||||
|
|
||||||
|
var dimensions = accessor.getControls().get(i).getDimensions();
|
||||||
|
int x = (int) (client.getWindow().getScaleFactor() * dimensions.getCenterX());
|
||||||
|
int y = (int) (client.getWindow().getScaleFactor() * dimensions.getCenterY());
|
||||||
|
InputManager.queueMousePosition(x,y);
|
||||||
|
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
||||||
|
MidnightControlsClient.get().input.actionGuiCooldown = 5;
|
||||||
|
if (MidnightControlsConfig.debug) MidnightControls.get().log(i+" "+accessor.getControls().size()+" | " + dimensions.getCenterX() + " " + dimensions.getCenterY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void handleTabs(Screen screen, boolean direction) {
|
||||||
|
if (screen instanceof SodiumOptionsGUI optionsGUI) {
|
||||||
|
SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI;
|
||||||
|
final int max = accessor.getPages().size()-1;
|
||||||
|
int i = accessor.getPages().indexOf(accessor.getCurrentPage());
|
||||||
|
i = (direction ? ((max > i) ? ++i : 0) : (i > 0 ? --i : max));
|
||||||
|
if (MidnightControlsConfig.debug) MidnightControls.get().log(""+i);
|
||||||
|
optionsGUI.setPage(accessor.getPages().get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.compat.mixin;
|
||||||
|
|
||||||
|
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||||
|
import me.jellysquid.mods.sodium.client.gui.options.OptionPage;
|
||||||
|
import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(value = SodiumOptionsGUI.class, remap = false)
|
||||||
|
public interface SodiumOptionsGUIAccessor {
|
||||||
|
@Accessor
|
||||||
|
List<ControlElement<?>> getControls();
|
||||||
|
@Accessor
|
||||||
|
List<OptionPage> getPages();
|
||||||
|
@Accessor
|
||||||
|
OptionPage getCurrentPage();
|
||||||
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.options.GameOptions;
|
import net.minecraft.client.option.GameOptions;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import org.aperlambda.lambdacommon.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
|
||||||
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
||||||
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -31,10 +31,10 @@ import static org.lwjgl.glfw.GLFW.*;
|
|||||||
* Represents a button binding.
|
* Represents a button binding.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.5.0
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public class ButtonBinding implements Nameable {
|
public class ButtonBinding {
|
||||||
public static final ButtonCategory MOVEMENT_CATEGORY;
|
public static final ButtonCategory MOVEMENT_CATEGORY;
|
||||||
public static final ButtonCategory GAMEPLAY_CATEGORY;
|
public static final ButtonCategory GAMEPLAY_CATEGORY;
|
||||||
public static final ButtonCategory INVENTORY_CATEGORY;
|
public static final ButtonCategory INVENTORY_CATEGORY;
|
||||||
@@ -63,6 +63,9 @@ public class ButtonBinding implements Nameable {
|
|||||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||||
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
|
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
|
||||||
.action(InputHandlers::handleScreenshot).cooldown().register();
|
.action(InputHandlers::handleScreenshot).cooldown().register();
|
||||||
|
|
||||||
|
public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B)
|
||||||
|
.action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.options.debugEnabled = !client.options.debugEnabled; return true;}).cooldown().register();
|
||||||
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
||||||
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
|
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
|
||||||
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
|
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
|
||||||
@@ -77,10 +80,20 @@ public class ButtonBinding implements Nameable {
|
|||||||
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB).onlyInGame().register();
|
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB).onlyInGame().register();
|
||||||
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).onlyInGame().cooldown().register();
|
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).onlyInGame().cooldown().register();
|
||||||
public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
||||||
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown().register();
|
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((client, binding) -> client.currentScreen != null && client.currentScreen.getClass().toString().contains("sodium"))).cooldown().register();
|
||||||
public static final ButtonBinding TAB_RIGHT = new Builder("tab_next").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
public static final ButtonBinding TAB_RIGHT = new Builder("tab_next").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||||
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown().register();
|
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((client, binding) -> client.currentScreen != null && client.currentScreen.getClass().toString().contains("sodium"))).cooldown().register();
|
||||||
public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown().register();
|
public static final ButtonBinding PAGE_LEFT = new Builder("page_back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||||
|
.action(InputHandlers.handlePage(false)).filter(InputHandlers::inInventory).cooldown().register();
|
||||||
|
public static final ButtonBinding PAGE_RIGHT = new Builder("page_next").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||||
|
.action(InputHandlers.handlePage(true)).filter(InputHandlers::inInventory).cooldown().register();
|
||||||
|
public static final ButtonBinding TAKE = new Builder("take").buttons(GLFW_GAMEPAD_BUTTON_X)
|
||||||
|
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
|
||||||
|
public static final ButtonBinding TAKE_ALL = new Builder("take_all").buttons(GLFW_GAMEPAD_BUTTON_A)
|
||||||
|
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
|
||||||
|
public static final ButtonBinding QUICK_MOVE = new Builder("quick_move").buttons(GLFW_GAMEPAD_BUTTON_Y)
|
||||||
|
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
|
||||||
|
public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").filter(InputHandlers::inGame).buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown().register();
|
||||||
public static final ButtonBinding USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register();
|
public static final ButtonBinding USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register();
|
||||||
|
|
||||||
private int[] button;
|
private int[] button;
|
||||||
@@ -89,12 +102,12 @@ public class ButtonBinding implements Nameable {
|
|||||||
private final Text text;
|
private final Text text;
|
||||||
private KeyBinding mcKeyBinding = null;
|
private KeyBinding mcKeyBinding = null;
|
||||||
protected PairPredicate<MinecraftClient, ButtonBinding> filter;
|
protected PairPredicate<MinecraftClient, ButtonBinding> filter;
|
||||||
private List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
|
private final List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
|
||||||
private boolean hasCooldown;
|
private boolean hasCooldown;
|
||||||
private int cooldown = 0;
|
private int cooldown = 0;
|
||||||
boolean pressed = false;
|
boolean pressed = false;
|
||||||
|
|
||||||
public ButtonBinding(@NotNull String key, int[] defaultButton, @NotNull List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
||||||
this.setButton(this.defaultButton = defaultButton);
|
this.setButton(this.defaultButton = defaultButton);
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.text = new TranslatableText(this.key);
|
this.text = new TranslatableText(this.key);
|
||||||
@@ -103,14 +116,14 @@ public class ButtonBinding implements Nameable {
|
|||||||
this.hasCooldown = hasCooldown;
|
this.hasCooldown = hasCooldown;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ButtonBinding(@NotNull String key, int[] defaultButton, boolean hasCooldown) {
|
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown) {
|
||||||
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown);
|
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the button bound.
|
* Returns the button bound.
|
||||||
*
|
*
|
||||||
* @return The bound button.
|
* @return the bound button
|
||||||
*/
|
*/
|
||||||
public int[] getButton() {
|
public int[] getButton() {
|
||||||
return this.button;
|
return this.button;
|
||||||
@@ -119,7 +132,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets the bound button.
|
* Sets the bound button.
|
||||||
*
|
*
|
||||||
* @param button The bound button.
|
* @param button the bound button
|
||||||
*/
|
*/
|
||||||
public void setButton(int[] button) {
|
public void setButton(int[] button) {
|
||||||
this.button = button;
|
this.button = button;
|
||||||
@@ -131,8 +144,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the bound button is the specified button or not.
|
* Returns whether the bound button is the specified button or not.
|
||||||
*
|
*
|
||||||
* @param button The button to check.
|
* @param button the button to check
|
||||||
* @return True if the bound button is the specified button, else false.
|
* @return true if the bound button is the specified button, else false
|
||||||
*/
|
*/
|
||||||
public boolean isButton(int[] button) {
|
public boolean isButton(int[] button) {
|
||||||
return InputManager.areButtonsEquivalent(button, this.button);
|
return InputManager.areButtonsEquivalent(button, this.button);
|
||||||
@@ -141,7 +154,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this button is down or not.
|
* Returns whether this button is down or not.
|
||||||
*
|
*
|
||||||
* @return True if the button is down, else false.
|
* @return true if the button is down, else false
|
||||||
*/
|
*/
|
||||||
public boolean isButtonDown() {
|
public boolean isButtonDown() {
|
||||||
return this.pressed;
|
return this.pressed;
|
||||||
@@ -150,7 +163,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this button binding is bound or not.
|
* Returns whether this button binding is bound or not.
|
||||||
*
|
*
|
||||||
* @return True if this button binding is bound, else false.
|
* @return true if this button binding is bound, else false
|
||||||
*/
|
*/
|
||||||
public boolean isNotBound() {
|
public boolean isNotBound() {
|
||||||
return this.button.length == 0 || this.button[0] == -1;
|
return this.button.length == 0 || this.button[0] == -1;
|
||||||
@@ -159,7 +172,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the default button assigned to this binding.
|
* Gets the default button assigned to this binding.
|
||||||
*
|
*
|
||||||
* @return The default button.
|
* @return the default button
|
||||||
*/
|
*/
|
||||||
public int[] getDefaultButton() {
|
public int[] getDefaultButton() {
|
||||||
return this.defaultButton;
|
return this.defaultButton;
|
||||||
@@ -168,7 +181,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the assigned button is the default button.
|
* Returns whether the assigned button is the default button.
|
||||||
*
|
*
|
||||||
* @return True if the assigned button is the default button, else false.
|
* @return true if the assigned button is the default button, else false
|
||||||
*/
|
*/
|
||||||
public boolean isDefault() {
|
public boolean isDefault() {
|
||||||
return this.button.length == this.defaultButton.length && InputManager.areButtonsEquivalent(this.button, this.defaultButton);
|
return this.button.length == this.defaultButton.length && InputManager.areButtonsEquivalent(this.button, this.defaultButton);
|
||||||
@@ -177,10 +190,9 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the button code.
|
* Returns the button code.
|
||||||
*
|
*
|
||||||
* @return The button code.
|
* @return the button code
|
||||||
*/
|
*/
|
||||||
public @NotNull
|
public String getButtonCode() {
|
||||||
String getButtonCode() {
|
|
||||||
return Arrays.stream(this.button)
|
return Arrays.stream(this.button)
|
||||||
.mapToObj(btn -> Integer.valueOf(btn).toString())
|
.mapToObj(btn -> Integer.valueOf(btn).toString())
|
||||||
.collect(Collectors.joining("+"));
|
.collect(Collectors.joining("+"));
|
||||||
@@ -189,7 +201,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets the key binding to emulate with this button binding.
|
* Sets the key binding to emulate with this button binding.
|
||||||
*
|
*
|
||||||
* @param keyBinding The optional key binding.
|
* @param keyBinding the optional key binding
|
||||||
*/
|
*/
|
||||||
public void setKeyBinding(@Nullable KeyBinding keyBinding) {
|
public void setKeyBinding(@Nullable KeyBinding keyBinding) {
|
||||||
this.mcKeyBinding = keyBinding;
|
this.mcKeyBinding = keyBinding;
|
||||||
@@ -198,8 +210,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the button binding is available in the current context.
|
* Returns whether the button binding is available in the current context.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @return True if the button binding is available, else false.
|
* @return true if the button binding is available, else false
|
||||||
*/
|
*/
|
||||||
public boolean isAvailable(@NotNull MinecraftClient client) {
|
public boolean isAvailable(@NotNull MinecraftClient client) {
|
||||||
return this.filter.test(client, this);
|
return this.filter.test(client, this);
|
||||||
@@ -216,8 +228,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Handles the button binding.
|
* Handles the button binding.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param state The state.
|
* @param state the state
|
||||||
*/
|
*/
|
||||||
public void handle(@NotNull MinecraftClient client, float value, @NotNull ButtonState state) {
|
public void handle(@NotNull MinecraftClient client, float value, @NotNull ButtonState state) {
|
||||||
if (state == ButtonState.REPEAT && this.hasCooldown && this.cooldown != 0)
|
if (state == ButtonState.REPEAT && this.hasCooldown && this.cooldown != 0)
|
||||||
@@ -231,7 +243,6 @@ public class ButtonBinding implements Nameable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.key;
|
return this.key;
|
||||||
}
|
}
|
||||||
@@ -239,10 +250,10 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the translation key of this button binding.
|
* Returns the translation key of this button binding.
|
||||||
*
|
*
|
||||||
* @return The translation key.
|
* @return the translation key
|
||||||
*/
|
*/
|
||||||
public @NotNull String getTranslationKey() {
|
public @NotNull String getTranslationKey() {
|
||||||
return "lambdacontrols.action." + this.getName();
|
return I18n.hasTranslation("midnightcontrols.action." + this.getName()) ? "midnightcontrols.action." + this.getName() : this.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Text getText() {
|
public @NotNull Text getText() {
|
||||||
@@ -252,7 +263,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the key binding equivalent of this button binding.
|
* Returns the key binding equivalent of this button binding.
|
||||||
*
|
*
|
||||||
* @return The key binding equivalent.
|
* @return the key binding equivalent
|
||||||
*/
|
*/
|
||||||
public @NotNull Optional<KeyBinding> asKeyBinding() {
|
public @NotNull Optional<KeyBinding> asKeyBinding() {
|
||||||
return Optional.ofNullable(this.mcKeyBinding);
|
return Optional.ofNullable(this.mcKeyBinding);
|
||||||
@@ -268,9 +279,9 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the specified axis as a button.
|
* Returns the specified axis as a button.
|
||||||
*
|
*
|
||||||
* @param axis The axis.
|
* @param axis the axis
|
||||||
* @param positive True if the axis part is positive, else false.
|
* @param positive true if the axis part is positive, else false
|
||||||
* @return The axis as a button.
|
* @return the axis as a button
|
||||||
*/
|
*/
|
||||||
public static int axisAsButton(int axis, boolean positive) {
|
public static int axisAsButton(int axis, boolean positive) {
|
||||||
return positive ? 100 + axis : 200 + axis;
|
return positive ? 100 + axis : 200 + axis;
|
||||||
@@ -279,8 +290,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the specified button is an axis or not.
|
* Returns whether the specified button is an axis or not.
|
||||||
*
|
*
|
||||||
* @param button The button.
|
* @param button the button
|
||||||
* @return True if the button is an axis, else false.
|
* @return true if the button is an axis, else false
|
||||||
*/
|
*/
|
||||||
public static boolean isAxis(int button) {
|
public static boolean isAxis(int button) {
|
||||||
button %= 500;
|
button %= 500;
|
||||||
@@ -290,97 +301,74 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the second Joycon's specified button code.
|
* Returns the second Joycon's specified button code.
|
||||||
*
|
*
|
||||||
* @param button The raw button code.
|
* @param button the raw button code
|
||||||
* @return The second Joycon's button code.
|
* @return the second Joycon's button code
|
||||||
*/
|
*/
|
||||||
public static int controller2Button(int button) {
|
public static int controller2Button(int button) {
|
||||||
return 500 + button;
|
return 500 + button;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(@NotNull GameOptions options) {
|
public static void init(@NotNull GameOptions options) {
|
||||||
ATTACK.mcKeyBinding = options.keyAttack;
|
ATTACK.mcKeyBinding = options.attackKey;
|
||||||
BACK.mcKeyBinding = options.keyBack;
|
BACK.mcKeyBinding = options.backKey;
|
||||||
CHAT.mcKeyBinding = options.keyChat;
|
CHAT.mcKeyBinding = options.chatKey;
|
||||||
DROP_ITEM.mcKeyBinding = options.keyDrop;
|
DROP_ITEM.mcKeyBinding = options.dropKey;
|
||||||
FORWARD.mcKeyBinding = options.keyForward;
|
FORWARD.mcKeyBinding = options.forwardKey;
|
||||||
INVENTORY.mcKeyBinding = options.keyInventory;
|
INVENTORY.mcKeyBinding = options.inventoryKey;
|
||||||
JUMP.mcKeyBinding = options.keyJump;
|
JUMP.mcKeyBinding = options.jumpKey;
|
||||||
LEFT.mcKeyBinding = options.keyLeft;
|
LEFT.mcKeyBinding = options.leftKey;
|
||||||
PICK_BLOCK.mcKeyBinding = options.keyPickItem;
|
PICK_BLOCK.mcKeyBinding = options.pickItemKey;
|
||||||
PLAYER_LIST.mcKeyBinding = options.keyPlayerList;
|
PLAYER_LIST.mcKeyBinding = options.playerListKey;
|
||||||
RIGHT.mcKeyBinding = options.keyRight;
|
RIGHT.mcKeyBinding = options.rightKey;
|
||||||
SCREENSHOT.mcKeyBinding = options.keyScreenshot;
|
SCREENSHOT.mcKeyBinding = options.screenshotKey;
|
||||||
SMOOTH_CAMERA.mcKeyBinding = options.keySmoothCamera;
|
SMOOTH_CAMERA.mcKeyBinding = options.smoothCameraKey;
|
||||||
SNEAK.mcKeyBinding = options.keySneak;
|
SNEAK.mcKeyBinding = options.sneakKey;
|
||||||
SPRINT.mcKeyBinding = options.keySprint;
|
SPRINT.mcKeyBinding = options.sprintKey;
|
||||||
SWAP_HANDS.mcKeyBinding = options.keySwapHands;
|
SWAP_HANDS.mcKeyBinding = options.swapHandsKey;
|
||||||
TOGGLE_PERSPECTIVE.mcKeyBinding = options.keyTogglePerspective;
|
TOGGLE_PERSPECTIVE.mcKeyBinding = options.togglePerspectiveKey;
|
||||||
USE.mcKeyBinding = options.keyUse;
|
USE.mcKeyBinding = options.useKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the localized name of the specified button.
|
* Returns the localized name of the specified button.
|
||||||
*
|
*
|
||||||
* @param button The button.
|
* @param button the button
|
||||||
* @return The localized name of the button.
|
* @return the localized name of the button
|
||||||
*/
|
*/
|
||||||
public static @NotNull Text getLocalizedButtonName(int button) {
|
public static @NotNull Text getLocalizedButtonName(int button) {
|
||||||
switch (button % 500) {
|
return switch (button % 500) {
|
||||||
case -1:
|
case -1 -> new TranslatableText("key.keyboard.unknown");
|
||||||
return new TranslatableText("key.keyboard.unknown");
|
case GLFW_GAMEPAD_BUTTON_A -> new TranslatableText("midnightcontrols.button.a");
|
||||||
case GLFW_GAMEPAD_BUTTON_A:
|
case GLFW_GAMEPAD_BUTTON_B -> new TranslatableText("midnightcontrols.button.b");
|
||||||
return new TranslatableText("lambdacontrols.button.a");
|
case GLFW_GAMEPAD_BUTTON_X -> new TranslatableText("midnightcontrols.button.x");
|
||||||
case GLFW_GAMEPAD_BUTTON_B:
|
case GLFW_GAMEPAD_BUTTON_Y -> new TranslatableText("midnightcontrols.button.y");
|
||||||
return new TranslatableText("lambdacontrols.button.b");
|
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER -> new TranslatableText("midnightcontrols.button.left_bumper");
|
||||||
case GLFW_GAMEPAD_BUTTON_X:
|
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER -> new TranslatableText("midnightcontrols.button.right_bumper");
|
||||||
return new TranslatableText("lambdacontrols.button.x");
|
case GLFW_GAMEPAD_BUTTON_BACK -> new TranslatableText("midnightcontrols.button.back");
|
||||||
case GLFW_GAMEPAD_BUTTON_Y:
|
case GLFW_GAMEPAD_BUTTON_START -> new TranslatableText("midnightcontrols.button.start");
|
||||||
return new TranslatableText("lambdacontrols.button.y");
|
case GLFW_GAMEPAD_BUTTON_GUIDE -> new TranslatableText("midnightcontrols.button.guide");
|
||||||
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
|
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB -> new TranslatableText("midnightcontrols.button.left_thumb");
|
||||||
return new TranslatableText("lambdacontrols.button.left_bumper");
|
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB -> new TranslatableText("midnightcontrols.button.right_thumb");
|
||||||
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
|
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> new TranslatableText("midnightcontrols.button.dpad_up");
|
||||||
return new TranslatableText("lambdacontrols.button.right_bumper");
|
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> new TranslatableText("midnightcontrols.button.dpad_right");
|
||||||
case GLFW_GAMEPAD_BUTTON_BACK:
|
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> new TranslatableText("midnightcontrols.button.dpad_down");
|
||||||
return new TranslatableText("lambdacontrols.button.back");
|
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> new TranslatableText("midnightcontrols.button.dpad_left");
|
||||||
case GLFW_GAMEPAD_BUTTON_START:
|
case 100 -> new TranslatableText("midnightcontrols.axis.left_x+");
|
||||||
return new TranslatableText("lambdacontrols.button.start");
|
case 101 -> new TranslatableText("midnightcontrols.axis.left_y+");
|
||||||
case GLFW_GAMEPAD_BUTTON_GUIDE:
|
case 102 -> new TranslatableText("midnightcontrols.axis.right_x+");
|
||||||
return new TranslatableText("lambdacontrols.button.guide");
|
case 103 -> new TranslatableText("midnightcontrols.axis.right_y+");
|
||||||
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
|
case 104 -> new TranslatableText("midnightcontrols.axis.left_trigger");
|
||||||
return new TranslatableText("lambdacontrols.button.left_thumb");
|
case 105 -> new TranslatableText("midnightcontrols.axis.right_trigger");
|
||||||
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
|
case 200 -> new TranslatableText("midnightcontrols.axis.left_x-");
|
||||||
return new TranslatableText("lambdacontrols.button.right_thumb");
|
case 201 -> new TranslatableText("midnightcontrols.axis.left_y-");
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_UP:
|
case 202 -> new TranslatableText("midnightcontrols.axis.right_x-");
|
||||||
return new TranslatableText("lambdacontrols.button.dpad_up");
|
case 203 -> new TranslatableText("midnightcontrols.axis.right_y-");
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT:
|
case 15 -> new TranslatableText("midnightcontrols.button.l4");
|
||||||
return new TranslatableText("lambdacontrols.button.dpad_right");
|
case 16 -> new TranslatableText("midnightcontrols.button.l5");
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN:
|
case 17 -> new TranslatableText("midnightcontrols.button.r4");
|
||||||
return new TranslatableText("lambdacontrols.button.dpad_down");
|
case 18 -> new TranslatableText("midnightcontrols.button.r5");
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT:
|
default -> new TranslatableText("midnightcontrols.button.unknown", button);
|
||||||
return new TranslatableText("lambdacontrols.button.dpad_left");
|
};
|
||||||
case 100:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.left_x+");
|
|
||||||
case 101:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.left_y+");
|
|
||||||
case 102:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.right_x+");
|
|
||||||
case 103:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.right_y+");
|
|
||||||
case 104:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.left_trigger");
|
|
||||||
case 105:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.right_trigger");
|
|
||||||
case 200:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.left_x-");
|
|
||||||
case 201:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.left_y-");
|
|
||||||
case 202:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.right_x-");
|
|
||||||
case 203:
|
|
||||||
return new TranslatableText("lambdacontrols.axis.right_y-");
|
|
||||||
default:
|
|
||||||
return new TranslatableText("lambdacontrols.button.unknown", button);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -402,37 +390,39 @@ public class ButtonBinding implements Nameable {
|
|||||||
ButtonBinding.HOTBAR_LEFT,
|
ButtonBinding.HOTBAR_LEFT,
|
||||||
ButtonBinding.HOTBAR_RIGHT,
|
ButtonBinding.HOTBAR_RIGHT,
|
||||||
ButtonBinding.INVENTORY,
|
ButtonBinding.INVENTORY,
|
||||||
ButtonBinding.SWAP_HANDS
|
ButtonBinding.SWAP_HANDS,
|
||||||
|
ButtonBinding.TAB_LEFT,
|
||||||
|
ButtonBinding.TAB_RIGHT,
|
||||||
|
ButtonBinding.PAGE_LEFT,
|
||||||
|
ButtonBinding.PAGE_RIGHT,
|
||||||
|
ButtonBinding.TAKE,
|
||||||
|
ButtonBinding.TAKE_ALL,
|
||||||
|
ButtonBinding.QUICK_MOVE,
|
||||||
|
ButtonBinding.SLOT_UP,
|
||||||
|
ButtonBinding.SLOT_DOWN,
|
||||||
|
ButtonBinding.SLOT_LEFT,
|
||||||
|
ButtonBinding.SLOT_RIGHT
|
||||||
));
|
));
|
||||||
MULTIPLAYER_CATEGORY = InputManager.registerDefaultCategory("key.categories.multiplayer",
|
MULTIPLAYER_CATEGORY = InputManager.registerDefaultCategory("key.categories.multiplayer",
|
||||||
category -> category.registerAllBindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST));
|
category -> category.registerAllBindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST));
|
||||||
MISC_CATEGORY = InputManager.registerDefaultCategory("key.categories.misc", category -> category.registerAllBindings(
|
MISC_CATEGORY = InputManager.registerDefaultCategory("key.categories.misc", category -> category.registerAllBindings(
|
||||||
ButtonBinding.SCREENSHOT,
|
ButtonBinding.SCREENSHOT,
|
||||||
|
ButtonBinding.TOGGLE_PERSPECTIVE,
|
||||||
|
ButtonBinding.PAUSE_GAME,
|
||||||
//SMOOTH_CAMERA,
|
//SMOOTH_CAMERA,
|
||||||
ButtonBinding.TOGGLE_PERSPECTIVE
|
ButtonBinding.DEBUG_SCREEN
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a builder instance.
|
* Returns a builder instance.
|
||||||
*
|
*
|
||||||
* @param identifier The identifier of the button binding.
|
* @param identifier the identifier of the button binding
|
||||||
* @return The builder instance
|
* @return the builder instance
|
||||||
* @since 1.5.0
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
public static Builder builder(@NotNull Identifier identifier) {
|
public static Builder builder(@NotNull Identifier identifier) {
|
||||||
return new Builder(identifier);
|
return new Builder(identifier);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a builder instance.
|
|
||||||
*
|
|
||||||
* @param identifier The identifier of the button binding.
|
|
||||||
* @return The builder instance.
|
|
||||||
* @since 1.5.0
|
|
||||||
*/
|
|
||||||
public static Builder builder(@NotNull net.minecraft.util.Identifier identifier) {
|
|
||||||
return new Builder(identifier);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,7 +436,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
public static class Builder {
|
public static class Builder {
|
||||||
private final String key;
|
private final String key;
|
||||||
private int[] buttons = new int[0];
|
private int[] buttons = new int[0];
|
||||||
private List<PressAction> actions = new ArrayList<>();
|
private final List<PressAction> actions = new ArrayList<>();
|
||||||
private PairPredicate<MinecraftClient, ButtonBinding> filter = Predicates.pairAlwaysTrue();
|
private PairPredicate<MinecraftClient, ButtonBinding> filter = Predicates.pairAlwaysTrue();
|
||||||
private boolean cooldown = false;
|
private boolean cooldown = false;
|
||||||
private ButtonCategory category = null;
|
private ButtonCategory category = null;
|
||||||
@@ -455,7 +445,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* This constructor shouldn't be used for other mods.
|
* This constructor shouldn't be used for other mods.
|
||||||
*
|
*
|
||||||
* @param key The key with format {@code "<namespace>.<name>"}.
|
* @param key the key with format {@code "<namespace>.<name>"}
|
||||||
*/
|
*/
|
||||||
public Builder(@NotNull String key) {
|
public Builder(@NotNull String key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
@@ -463,18 +453,14 @@ public class ButtonBinding implements Nameable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Builder(@NotNull Identifier identifier) {
|
public Builder(@NotNull Identifier identifier) {
|
||||||
this(identifier.getNamespace() + "." + identifier.getName());
|
this(identifier.getNamespace() + "." + identifier.getPath());
|
||||||
}
|
|
||||||
|
|
||||||
public Builder(@NotNull net.minecraft.util.Identifier identifier) {
|
|
||||||
this(new Identifier(identifier.toString()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the default buttons of the {@link ButtonBinding}.
|
* Defines the default buttons of the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @param buttons The default buttons.
|
* @param buttons the default buttons
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder buttons(int... buttons) {
|
public Builder buttons(int... buttons) {
|
||||||
this.buttons = buttons;
|
this.buttons = buttons;
|
||||||
@@ -484,7 +470,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets the {@link ButtonBinding} to unbound.
|
* Sets the {@link ButtonBinding} to unbound.
|
||||||
*
|
*
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder unbound() {
|
public Builder unbound() {
|
||||||
return this.buttons(-1);
|
return this.buttons(-1);
|
||||||
@@ -493,8 +479,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Adds the actions to the {@link ButtonBinding}.
|
* Adds the actions to the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @param actions The actions to add.
|
* @param actions the actions to add
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder actions(@NotNull PressAction... actions) {
|
public Builder actions(@NotNull PressAction... actions) {
|
||||||
this.actions.addAll(Arrays.asList(actions));
|
this.actions.addAll(Arrays.asList(actions));
|
||||||
@@ -504,8 +490,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Adds an action to the {@link ButtonBinding}.
|
* Adds an action to the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @param action The action to add.
|
* @param action the action to add
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder action(@NotNull PressAction action) {
|
public Builder action(@NotNull PressAction action) {
|
||||||
this.actions.add(action);
|
this.actions.add(action);
|
||||||
@@ -515,8 +501,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets a filter for the {@link ButtonBinding}.
|
* Sets a filter for the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @param filter The filter.
|
* @param filter the filter
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder filter(@NotNull PairPredicate<MinecraftClient, ButtonBinding> filter) {
|
public Builder filter(@NotNull PairPredicate<MinecraftClient, ButtonBinding> filter) {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
@@ -526,7 +512,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets the filter of {@link ButtonBinding} to only in game.
|
* Sets the filter of {@link ButtonBinding} to only in game.
|
||||||
*
|
*
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
* @see #filter(PairPredicate)
|
* @see #filter(PairPredicate)
|
||||||
* @see InputHandlers#inGame(MinecraftClient, ButtonBinding)
|
* @see InputHandlers#inGame(MinecraftClient, ButtonBinding)
|
||||||
*/
|
*/
|
||||||
@@ -537,7 +523,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets the filter of {@link ButtonBinding} to only in inventory.
|
* Sets the filter of {@link ButtonBinding} to only in inventory.
|
||||||
*
|
*
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
* @see #filter(PairPredicate)
|
* @see #filter(PairPredicate)
|
||||||
* @see InputHandlers#inInventory(MinecraftClient, ButtonBinding)
|
* @see InputHandlers#inInventory(MinecraftClient, ButtonBinding)
|
||||||
*/
|
*/
|
||||||
@@ -548,8 +534,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets whether the {@link ButtonBinding} has a cooldown or not.
|
* Sets whether the {@link ButtonBinding} has a cooldown or not.
|
||||||
*
|
*
|
||||||
* @param cooldown True if the {@link ButtonBinding} has a cooldown, else false.
|
* @param cooldown true if the {@link ButtonBinding} has a cooldown, else false
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder cooldown(boolean cooldown) {
|
public Builder cooldown(boolean cooldown) {
|
||||||
this.cooldown = cooldown;
|
this.cooldown = cooldown;
|
||||||
@@ -559,7 +545,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Puts a cooldown on the {@link ButtonBinding}.
|
* Puts a cooldown on the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
* @since 1.5.0
|
* @since 1.5.0
|
||||||
*/
|
*/
|
||||||
public Builder cooldown() {
|
public Builder cooldown() {
|
||||||
@@ -569,8 +555,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets the category of the {@link ButtonBinding}.
|
* Sets the category of the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @param category The category.
|
* @param category the category
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder category(@Nullable ButtonCategory category) {
|
public Builder category(@Nullable ButtonCategory category) {
|
||||||
this.category = category;
|
this.category = category;
|
||||||
@@ -580,8 +566,8 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Sets the keybinding linked to the {@link ButtonBinding}.
|
* Sets the keybinding linked to the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @param binding The keybinding to link.
|
* @param binding the keybinding to link
|
||||||
* @return The builder instance.
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder linkKeybind(@Nullable KeyBinding binding) {
|
public Builder linkKeybind(@Nullable KeyBinding binding) {
|
||||||
this.mcBinding = binding;
|
this.mcBinding = binding;
|
||||||
@@ -591,10 +577,10 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Builds the {@link ButtonBinding}.
|
* Builds the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @return The built {@link ButtonBinding}.
|
* @return the built {@link ButtonBinding}
|
||||||
*/
|
*/
|
||||||
public ButtonBinding build() {
|
public ButtonBinding build() {
|
||||||
ButtonBinding binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown);
|
var binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown);
|
||||||
if (this.category != null)
|
if (this.category != null)
|
||||||
this.category.registerBinding(binding);
|
this.category.registerBinding(binding);
|
||||||
if (this.mcBinding != null)
|
if (this.mcBinding != null)
|
||||||
@@ -605,7 +591,7 @@ public class ButtonBinding implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Builds and registers the {@link ButtonBinding}.
|
* Builds and registers the {@link ButtonBinding}.
|
||||||
*
|
*
|
||||||
* @return The built {@link ButtonBinding}.
|
* @return the built {@link ButtonBinding}
|
||||||
* @see #build()
|
* @see #build()
|
||||||
*/
|
*/
|
||||||
public ButtonBinding register() {
|
public ButtonBinding register() {
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import org.aperlambda.lambdacommon.Identifier;
|
import org.aperlambda.lambdacommon.Identifier;
|
||||||
@@ -29,7 +29,7 @@ import java.util.List;
|
|||||||
public class ButtonCategory implements Identifiable {
|
public class ButtonCategory implements Identifiable {
|
||||||
private final List<ButtonBinding> bindings = new ArrayList<>();
|
private final List<ButtonBinding> bindings = new ArrayList<>();
|
||||||
private final Identifier id;
|
private final Identifier id;
|
||||||
private int priority;
|
private final int priority;
|
||||||
|
|
||||||
public ButtonCategory(@NotNull Identifier id, int priority) {
|
public ButtonCategory(@NotNull Identifier id, int priority) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@@ -57,7 +57,7 @@ public class ButtonCategory implements Identifiable {
|
|||||||
/**
|
/**
|
||||||
* Gets the bindings assigned to this category.
|
* Gets the bindings assigned to this category.
|
||||||
*
|
*
|
||||||
* @return The bindings assigned to this category.
|
* @return the bindings assigned to this category
|
||||||
*/
|
*/
|
||||||
public @NotNull List<ButtonBinding> getBindings() {
|
public @NotNull List<ButtonBinding> getBindings() {
|
||||||
return Collections.unmodifiableList(this.bindings);
|
return Collections.unmodifiableList(this.bindings);
|
||||||
@@ -68,7 +68,7 @@ public class ButtonCategory implements Identifiable {
|
|||||||
* <p>
|
* <p>
|
||||||
* The translation key should be `modid.identifier_name`.
|
* The translation key should be `modid.identifier_name`.
|
||||||
*
|
*
|
||||||
* @return The translated name.
|
* @return the translated name
|
||||||
*/
|
*/
|
||||||
public @NotNull String getTranslatedName() {
|
public @NotNull String getTranslatedName() {
|
||||||
if (this.id.getNamespace().equals("minecraft"))
|
if (this.id.getNamespace().equals("minecraft"))
|
||||||
@@ -81,7 +81,7 @@ public class ButtonCategory implements Identifiable {
|
|||||||
* Gets the priority display of this category.
|
* Gets the priority display of this category.
|
||||||
* It will defines in which order the categories will display on the controls screen.
|
* It will defines in which order the categories will display on the controls screen.
|
||||||
*
|
*
|
||||||
* @return The priority of this category.
|
* @return the priority of this category
|
||||||
*/
|
*/
|
||||||
public int getPriority() {
|
public int getPriority() {
|
||||||
return this.priority;
|
return this.priority;
|
||||||
@@ -1,34 +1,34 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControls;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.client.toast.SystemToast;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.PointerBuffer;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
import org.lwjgl.glfw.GLFWGamepadState;
|
import org.lwjgl.glfw.GLFWGamepadState;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.nio.Buffer;
|
import java.net.URL;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.SeekableByteChannel;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -41,30 +41,16 @@ import static org.lwjgl.BufferUtils.createByteBuffer;
|
|||||||
* Represents a controller.
|
* Represents a controller.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.4.3
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public class Controller implements Nameable {
|
public record Controller(int id) implements Nameable {
|
||||||
private static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
private static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
||||||
private final int id;
|
|
||||||
|
|
||||||
public Controller(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the identifier of this controller.
|
|
||||||
*
|
|
||||||
* @return The identifier of this controller.
|
|
||||||
*/
|
|
||||||
public int getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the controller's globally unique identifier.
|
* Gets the controller's globally unique identifier.
|
||||||
*
|
*
|
||||||
* @return The controller's GUID.
|
* @return the controller's GUID
|
||||||
*/
|
*/
|
||||||
public String getGuid() {
|
public String getGuid() {
|
||||||
String guid = GLFW.glfwGetJoystickGUID(this.id);
|
String guid = GLFW.glfwGetJoystickGUID(this.id);
|
||||||
@@ -74,7 +60,7 @@ public class Controller implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this controller is connected or not.
|
* Returns whether this controller is connected or not.
|
||||||
*
|
*
|
||||||
* @return True if this controller is connected, else false.
|
* @return true if this controller is connected, else false
|
||||||
*/
|
*/
|
||||||
public boolean isConnected() {
|
public boolean isConnected() {
|
||||||
return GLFW.glfwJoystickPresent(this.id);
|
return GLFW.glfwJoystickPresent(this.id);
|
||||||
@@ -83,7 +69,7 @@ public class Controller implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether this controller is a gamepad or not.
|
* Returns whether this controller is a gamepad or not.
|
||||||
*
|
*
|
||||||
* @return True if this controller is a gamepad, else false.
|
* @return true if this controller is a gamepad, else false
|
||||||
*/
|
*/
|
||||||
public boolean isGamepad() {
|
public boolean isGamepad() {
|
||||||
return this.isConnected() && GLFW.glfwJoystickIsGamepad(this.id);
|
return this.isConnected() && GLFW.glfwJoystickIsGamepad(this.id);
|
||||||
@@ -92,29 +78,29 @@ public class Controller implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the name of the controller.
|
* Gets the name of the controller.
|
||||||
*
|
*
|
||||||
* @return The controller's name.
|
* @return the controller's name
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String getName() {
|
public String getName() {
|
||||||
String name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
|
var name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
|
||||||
return name == null ? String.valueOf(this.getId()) : name;
|
return name == null ? String.valueOf(this.id()) : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the state of the controller.
|
* Gets the state of the controller.
|
||||||
*
|
*
|
||||||
* @return The state of the controller input.
|
* @return the state of the controller input
|
||||||
*/
|
*/
|
||||||
public GLFWGamepadState getState() {
|
public GLFWGamepadState getState() {
|
||||||
GLFWGamepadState state = GLFWGamepadState.create();
|
var state = GLFWGamepadState.create();
|
||||||
if (this.isGamepad())
|
if (this.isGamepad())
|
||||||
GLFW.glfwGetGamepadState(this.id, state);
|
GLFW.glfwGetGamepadState(this.id, state);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull Controller byId(int id) {
|
public static Controller byId(int id) {
|
||||||
if (id > GLFW.GLFW_JOYSTICK_LAST) {
|
if (id > GLFW.GLFW_JOYSTICK_LAST) {
|
||||||
LambdaControlsClient.get().log("Controller '" + id + "' doesn't exist.");
|
MidnightControlsClient.get().log("Controller '" + id + "' doesn't exist.");
|
||||||
id = GLFW.GLFW_JOYSTICK_LAST;
|
id = GLFW.GLFW_JOYSTICK_LAST;
|
||||||
}
|
}
|
||||||
Controller controller;
|
Controller controller;
|
||||||
@@ -127,33 +113,33 @@ public class Controller implements Nameable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull Optional<Controller> byGuid(@NotNull String guid) {
|
public static Optional<Controller> byGuid(@NotNull String guid) {
|
||||||
return CONTROLLERS.values().stream().filter(Controller::isConnected)
|
return CONTROLLERS.values().stream().filter(Controller::isConnected)
|
||||||
.filter(controller -> controller.getGuid().equals(guid))
|
.filter(controller -> controller.getGuid().equals(guid))
|
||||||
.max(Comparator.comparingInt(Controller::getId));
|
.max(Comparator.comparingInt(Controller::id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the specified resource and returns the raw data as a ByteBuffer.
|
* Reads the specified resource and returns the raw data as a ByteBuffer.
|
||||||
*
|
*
|
||||||
* @param resource The resource to read.
|
* @param resource the resource to read
|
||||||
* @param bufferSize The initial buffer size.
|
* @param bufferSize the initial buffer size
|
||||||
* @return The resource data.
|
* @return the resource data
|
||||||
* @throws IOException If an IO error occurs.
|
* @throws IOException If an IO error occurs.
|
||||||
*/
|
*/
|
||||||
private static ByteBuffer ioResourceToBuffer(String resource, int bufferSize) throws IOException {
|
private static ByteBuffer ioResourceToBuffer(String resource, int bufferSize) throws IOException {
|
||||||
ByteBuffer buffer = null;
|
ByteBuffer buffer = null;
|
||||||
|
|
||||||
Path path = Paths.get(resource);
|
var path = Paths.get(resource);
|
||||||
if (Files.isReadable(path)) {
|
if (Files.isReadable(path)) {
|
||||||
try (SeekableByteChannel fc = Files.newByteChannel(path)) {
|
try (var fc = Files.newByteChannel(path)) {
|
||||||
buffer = createByteBuffer((int) fc.size() + 2);
|
buffer = createByteBuffer((int) fc.size() + 2);
|
||||||
while (fc.read(buffer) != -1) ;
|
while (fc.read(buffer) != -1) ;
|
||||||
buffer.put((byte) 0);
|
buffer.put((byte) 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
((Buffer) buffer).flip(); // Force Java 8 >.<
|
if (buffer != null) buffer.flip(); // Force Java 8 >.<
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,42 +148,53 @@ public class Controller implements Nameable {
|
|||||||
*/
|
*/
|
||||||
public static void updateMappings() {
|
public static void updateMappings() {
|
||||||
try {
|
try {
|
||||||
if (!LambdaControlsClient.MAPPINGS_FILE.exists())
|
MidnightControlsClient.get().log("Updating controller mappings...");
|
||||||
|
File databaseFile = new File("config/gamecontrollerdatabase.txt");
|
||||||
|
try {
|
||||||
|
BufferedInputStream in = new BufferedInputStream(new URL("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").openStream());
|
||||||
|
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(databaseFile));
|
||||||
|
byte[] dataBuffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
||||||
|
out.write(dataBuffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {/* Just continue when internet connection is not available */}
|
||||||
|
var database = ioResourceToBuffer(databaseFile.getPath(), 1024);
|
||||||
|
if (database != null) GLFW.glfwUpdateGamepadMappings(database);
|
||||||
|
if (!MidnightControlsClient.MAPPINGS_FILE.exists())
|
||||||
return;
|
return;
|
||||||
LambdaControlsClient.get().log("Updating controller mappings...");
|
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024);
|
||||||
ByteBuffer buffer = ioResourceToBuffer(LambdaControlsClient.MAPPINGS_FILE.getPath(), 1024);
|
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
|
||||||
GLFW.glfwUpdateGamepadMappings(buffer);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryStack memoryStack = MemoryStack.stackPush();
|
try (var memoryStack = MemoryStack.stackPush()) {
|
||||||
try {
|
var pointerBuffer = memoryStack.mallocPointer(1);
|
||||||
PointerBuffer pointerBuffer = memoryStack.mallocPointer(1);
|
|
||||||
int i = GLFW.glfwGetError(pointerBuffer);
|
int i = GLFW.glfwGetError(pointerBuffer);
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
long l = pointerBuffer.get();
|
long l = pointerBuffer.get();
|
||||||
String string = l == 0L ? "" : MemoryUtil.memUTF8(l);
|
var string = l == 0L ? "" : MemoryUtil.memUTF8(l);
|
||||||
MinecraftClient client = MinecraftClient.getInstance();
|
var client = MinecraftClient.getInstance();
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
|
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
|
||||||
new TranslatableText("lambdacontrols.controller.mappings.error"), new LiteralText(string)));
|
new TranslatableText("midnightcontrols.controller.mappings.error"), new LiteralText(string)));
|
||||||
|
MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
/* Ignored :concern: */
|
/* Ignored :concern: */
|
||||||
} finally {
|
|
||||||
memoryStack.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LambdaControlsClient.get().config.hasDebug()) {
|
if (MidnightControlsConfig.debug) {
|
||||||
for (int i = GLFW.GLFW_JOYSTICK_1; i <= GLFW.GLFW_JOYSTICK_16; i++) {
|
for (int i = GLFW.GLFW_JOYSTICK_1; i <= GLFW.GLFW_JOYSTICK_16; i++) {
|
||||||
Controller controller = byId(i);
|
var controller = byId(i);
|
||||||
|
|
||||||
if (!controller.isConnected())
|
if (!controller.isConnected())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LambdaControls.get().log(String.format("Controller #%d name: \"%s\"\n GUID: %s\n Gamepad: %s",
|
MidnightControls.get().log(String.format("Controller #%d name: \"%s\"\n GUID: %s\n Gamepad: %s",
|
||||||
controller.id,
|
controller.id,
|
||||||
controller.getName(),
|
controller.getName(),
|
||||||
controller.getGuid(),
|
controller.getGuid(),
|
||||||
@@ -1,44 +1,58 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.ButtonState;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaInput;
|
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
||||||
import dev.lambdaurora.lambdacontrols.client.mixin.AdvancementsScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import dev.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
import dev.lambdaurora.lambdacontrols.client.mixin.RecipeBookWidgetAccessor;
|
import eu.midnightdust.midnightcontrols.client.compat.EMICompat;
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.RecipeBookWidgetAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
|
||||||
|
import net.fabricmc.fabric.impl.item.group.CreativeGuiExtensions;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
import net.minecraft.client.gl.Framebuffer;
|
||||||
|
import net.minecraft.client.gui.hud.DebugHud;
|
||||||
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
||||||
import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget;
|
import net.minecraft.client.gui.widget.PressableWidget;
|
||||||
import net.minecraft.client.util.ScreenshotUtils;
|
import net.minecraft.client.util.ScreenshotRecorder;
|
||||||
import net.minecraft.item.ItemGroup;
|
import net.minecraft.item.ItemGroup;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.screen.slot.SlotActionType;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
import org.aperlambda.lambdacommon.utils.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents some input handlers.
|
* Represents some input handlers.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.4.3
|
* @version 1.7.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class InputHandlers {
|
public class InputHandlers {
|
||||||
@@ -53,24 +67,23 @@ public class InputHandlers {
|
|||||||
// When ingame
|
// When ingame
|
||||||
if (client.currentScreen == null && client.player != null) {
|
if (client.currentScreen == null && client.player != null) {
|
||||||
if (next)
|
if (next)
|
||||||
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 8 ? 0 : client.player.inventory.selectedSlot + 1;
|
client.player.getInventory().selectedSlot = client.player.getInventory().selectedSlot == 8 ? 0 : client.player.getInventory().selectedSlot + 1;
|
||||||
else
|
else
|
||||||
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 0 ? 8 : client.player.inventory.selectedSlot - 1;
|
client.player.getInventory().selectedSlot = client.player.getInventory().selectedSlot == 0 ? 8 : client.player.getInventory().selectedSlot - 1;
|
||||||
return true;
|
return true;
|
||||||
} else if (client.currentScreen instanceof CreativeInventoryScreen) {
|
} else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) {
|
||||||
CreativeInventoryScreenAccessor inventory = (CreativeInventoryScreenAccessor) client.currentScreen;
|
int currentTab = CreativeInventoryScreenAccessor.getSelectedTab();
|
||||||
int currentTab = inventory.getSelectedTab();
|
|
||||||
int nextTab = currentTab + (next ? 1 : -1);
|
int nextTab = currentTab + (next ? 1 : -1);
|
||||||
if (nextTab < 0)
|
if (nextTab < 0)
|
||||||
nextTab = ItemGroup.GROUPS.length - 1;
|
nextTab = ItemGroup.GROUPS.length - 1;
|
||||||
else if (nextTab >= ItemGroup.GROUPS.length)
|
else if (nextTab >= ItemGroup.GROUPS.length)
|
||||||
nextTab = 0;
|
nextTab = 0;
|
||||||
inventory.lambdacontrols$setSelectedTab(ItemGroup.GROUPS[nextTab]);
|
inventory.midnightcontrols$setSelectedTab(ItemGroup.GROUPS[nextTab]);
|
||||||
return true;
|
return true;
|
||||||
} else if (client.currentScreen instanceof InventoryScreen) {
|
} else if (client.currentScreen instanceof InventoryScreen inventoryScreen) {
|
||||||
RecipeBookWidgetAccessor recipeBook = (RecipeBookWidgetAccessor) ((InventoryScreen) client.currentScreen).getRecipeBookWidget();
|
var recipeBook = (RecipeBookWidgetAccessor) inventoryScreen.getRecipeBookWidget();
|
||||||
List<RecipeGroupButtonWidget> tabs = recipeBook.getTabButtons();
|
var tabs = recipeBook.getTabButtons();
|
||||||
RecipeGroupButtonWidget currentTab = recipeBook.getCurrentTab();
|
var currentTab = recipeBook.getCurrentTab();
|
||||||
if (currentTab == null)
|
if (currentTab == null)
|
||||||
return false;
|
return false;
|
||||||
int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1);
|
int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1);
|
||||||
@@ -81,12 +94,11 @@ public class InputHandlers {
|
|||||||
currentTab.setToggled(false);
|
currentTab.setToggled(false);
|
||||||
recipeBook.setCurrentTab(currentTab = tabs.get(nextTab));
|
recipeBook.setCurrentTab(currentTab = tabs.get(nextTab));
|
||||||
currentTab.setToggled(true);
|
currentTab.setToggled(true);
|
||||||
recipeBook.lambdacontrols$refreshResults(true);
|
recipeBook.midnightcontrols$refreshResults(true);
|
||||||
return true;
|
return true;
|
||||||
} else if (client.currentScreen instanceof AdvancementsScreen) {
|
} else if (client.currentScreen instanceof AdvancementsScreenAccessor screen) {
|
||||||
AdvancementsScreenAccessor screen = (AdvancementsScreenAccessor) client.currentScreen;
|
var tabs = screen.getTabs().values().stream().distinct().collect(Collectors.toList());
|
||||||
List<AdvancementTab> tabs = screen.getTabs().values().stream().distinct().collect(Collectors.toList());
|
var tab = screen.getSelectedTab();
|
||||||
AdvancementTab tab = screen.getSelectedTab();
|
|
||||||
if (tab == null)
|
if (tab == null)
|
||||||
return false;
|
return false;
|
||||||
for (int i = 0; i < tabs.size(); i++) {
|
for (int i = 0; i < tabs.size(); i++) {
|
||||||
@@ -101,10 +113,94 @@ public class InputHandlers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
} else if (FabricLoader.getInstance().isModLoaded("sodium")) SodiumCompat.handleTabs(client.currentScreen, next);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static PressAction handlePage(boolean next) {
|
||||||
|
return (client, button, value, action) -> {
|
||||||
|
if (client.currentScreen instanceof CreativeInventoryScreen) {
|
||||||
|
var screen = (HandledScreenAccessor) client.currentScreen;
|
||||||
|
try {
|
||||||
|
if (next) {
|
||||||
|
return client.currentScreen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||||
|
.map(element -> (PressableWidget) element)
|
||||||
|
.filter(element -> element.getMessage() != null)
|
||||||
|
.anyMatch(element -> {
|
||||||
|
if (element.getMessage().getString().equals(">")) {
|
||||||
|
element.onPress();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return client.currentScreen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||||
|
.map(element -> (PressableWidget) element)
|
||||||
|
.filter(element -> element.getMessage() != null)
|
||||||
|
.anyMatch(element -> {
|
||||||
|
if (element.getMessage().getString().equals("<")) {
|
||||||
|
element.onPress();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
public static PressAction handleActions() {
|
||||||
|
return (client, button, value, action) -> {
|
||||||
|
if (!(client.currentScreen instanceof HandledScreen<?> screen)) return false;
|
||||||
|
if (client.interactionManager == null || client.player == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (MidnightControlsClient.get().input.inventoryInteractionCooldown > 0)
|
||||||
|
return true;
|
||||||
|
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||||
|
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||||
|
|
||||||
|
var accessor = (HandledScreenAccessor) screen;
|
||||||
|
Slot slot = ((HandledScreenAccessor) screen).midnightcontrols$getSlotAt(x, y);
|
||||||
|
|
||||||
|
int slotId;
|
||||||
|
if (slot == null) {
|
||||||
|
if (button.getName().equals("take_all")) {
|
||||||
|
((MouseAccessor) client.mouse).setLeftButtonClicked(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
slotId = accessor.midnightcontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1;
|
||||||
|
} else {
|
||||||
|
slotId = slot.id;
|
||||||
|
}
|
||||||
|
var actionType = SlotActionType.PICKUP;
|
||||||
|
int clickData = GLFW.GLFW_MOUSE_BUTTON_1;
|
||||||
|
|
||||||
|
MidnightControlsClient.get().input.inventoryInteractionCooldown = 5;
|
||||||
|
switch (button.getName()) {
|
||||||
|
case "take_all": {
|
||||||
|
if (screen instanceof CreativeInventoryScreen) {
|
||||||
|
if (slot != null && (((CreativeInventoryScreenAccessor) accessor).midnightcontrols$isCreativeInventorySlot(slot) || MidnightControlsCompat.streamCompatHandlers().anyMatch(handler -> handler.isCreativeSlot(screen, slot))))
|
||||||
|
actionType = SlotActionType.CLONE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "take": {
|
||||||
|
clickData = GLFW_MOUSE_BUTTON_2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "quick_move": {
|
||||||
|
actionType = SlotActionType.QUICK_MOVE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
accessor.midnightcontrols$onMouseClick(slot, slotId, clickData, actionType);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean handlePauseGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) {
|
public static boolean handlePauseGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) {
|
||||||
if (action == ButtonState.PRESS) {
|
if (action == ButtonState.PRESS) {
|
||||||
@@ -114,7 +210,7 @@ public class InputHandlers {
|
|||||||
else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it.
|
else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it.
|
||||||
client.player.closeHandledScreen();
|
client.player.closeHandledScreen();
|
||||||
else // Else just close the current screen.
|
else // Else just close the current screen.
|
||||||
client.currentScreen.onClose();
|
client.currentScreen.close();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -122,14 +218,14 @@ public class InputHandlers {
|
|||||||
/**
|
/**
|
||||||
* Handles the screenshot action.
|
* Handles the screenshot action.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param binding The binding which fired the action.
|
* @param binding the binding which fired the action
|
||||||
* @param action The action done on the binding.
|
* @param action the action done on the binding
|
||||||
* @return True if handled, else false.
|
* @return true if handled, else false
|
||||||
*/
|
*/
|
||||||
public static boolean handleScreenshot(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) {
|
public static boolean handleScreenshot(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) {
|
||||||
if (action == ButtonState.RELEASE)
|
if (action == ButtonState.RELEASE)
|
||||||
ScreenshotUtils.saveScreenshot(client.runDirectory, client.getWindow().getFramebufferWidth(), client.getWindow().getFramebufferHeight(), client.getFramebuffer(),
|
ScreenshotRecorder.saveScreenshot(client.runDirectory, client.getFramebuffer(),
|
||||||
text -> client.execute(() -> client.inGameHud.getChatHud().addMessage(text)));
|
text -> client.execute(() -> client.inGameHud.getChatHud().addMessage(text)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -137,10 +233,10 @@ public class InputHandlers {
|
|||||||
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||||
button.asKeyBinding().ifPresent(binding -> {
|
button.asKeyBinding().ifPresent(binding -> {
|
||||||
boolean sneakToggled = client.options.sneakToggled;
|
boolean sneakToggled = client.options.sneakToggled;
|
||||||
if (client.player.abilities.flying && sneakToggled)
|
if (client.player.getAbilities().flying && sneakToggled)
|
||||||
client.options.sneakToggled = false;
|
client.options.sneakToggled = false;
|
||||||
binding.setPressed(button.pressed);
|
binding.setPressed(button.pressed);
|
||||||
if (client.player.abilities.flying && sneakToggled)
|
if (client.player.getAbilities().flying && sneakToggled)
|
||||||
client.options.sneakToggled = true;
|
client.options.sneakToggled = true;
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@@ -148,18 +244,17 @@ public class InputHandlers {
|
|||||||
|
|
||||||
public static PressAction handleInventorySlotPad(int direction) {
|
public static PressAction handleInventorySlotPad(int direction) {
|
||||||
return (client, binding, value, action) -> {
|
return (client, binding, value, action) -> {
|
||||||
if (!(client.currentScreen instanceof HandledScreen && action != ButtonState.RELEASE))
|
if (!(client.currentScreen instanceof HandledScreen inventory && action != ButtonState.RELEASE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
HandledScreen inventory = (HandledScreen) client.currentScreen;
|
var accessor = (HandledScreenAccessor) inventory;
|
||||||
HandledScreenAccessor accessor = (HandledScreenAccessor) inventory;
|
|
||||||
int guiLeft = accessor.getX();
|
int guiLeft = accessor.getX();
|
||||||
int guiTop = accessor.getY();
|
int guiTop = accessor.getY();
|
||||||
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||||
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||||
|
|
||||||
// Finds the hovered slot.
|
// Finds the hovered slot.
|
||||||
Slot mouseSlot = accessor.lambdacontrols$getSlotAt(mouseX, mouseY);
|
var mouseSlot = accessor.midnightcontrols$getSlotAt(mouseX, mouseY);
|
||||||
|
|
||||||
// Finds the closest slot in the GUI within 14 pixels.
|
// Finds the closest slot in the GUI within 14 pixels.
|
||||||
Optional<Slot> closestSlot = inventory.getScreenHandler().slots.parallelStream()
|
Optional<Slot> closestSlot = inventory.getScreenHandler().slots.parallelStream()
|
||||||
@@ -179,7 +274,7 @@ public class InputHandlers {
|
|||||||
double distance = Math.sqrt(Math.pow(posX - otherPosX, 2) + Math.pow(posY - otherPosY, 2));
|
double distance = Math.sqrt(Math.pow(posX - otherPosX, 2) + Math.pow(posY - otherPosY, 2));
|
||||||
return Pair.of(slot, distance);
|
return Pair.of(slot, distance);
|
||||||
}).filter(entry -> {
|
}).filter(entry -> {
|
||||||
Slot slot = entry.key;
|
var slot = entry.key;
|
||||||
int posX = guiLeft + slot.x + 8;
|
int posX = guiLeft + slot.x + 8;
|
||||||
int posY = guiTop + slot.y + 8;
|
int posY = guiTop + slot.y + 8;
|
||||||
int otherPosX = (int) mouseX;
|
int otherPosX = (int) mouseX;
|
||||||
@@ -203,7 +298,7 @@ public class InputHandlers {
|
|||||||
.map(p -> p.key);
|
.map(p -> p.key);
|
||||||
|
|
||||||
if (closestSlot.isPresent()) {
|
if (closestSlot.isPresent()) {
|
||||||
Slot slot = closestSlot.get();
|
var slot = closestSlot.get();
|
||||||
int x = guiLeft + slot.x + 8;
|
int x = guiLeft + slot.x + 8;
|
||||||
int y = guiTop + slot.y + 8;
|
int y = guiTop + slot.y + 8;
|
||||||
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
|
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
|
||||||
@@ -217,9 +312,9 @@ public class InputHandlers {
|
|||||||
/**
|
/**
|
||||||
* Returns always true to the filter.
|
* Returns always true to the filter.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param binding The affected binding.
|
* @param binding the affected binding
|
||||||
* @return True.
|
* @return true
|
||||||
*/
|
*/
|
||||||
public static boolean always(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
public static boolean always(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
return true;
|
return true;
|
||||||
@@ -228,33 +323,33 @@ public class InputHandlers {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the client is in game or not.
|
* Returns whether the client is in game or not.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param binding The affected binding.
|
* @param binding the affected binding
|
||||||
* @return True if the client is in game, else false.
|
* @return true if the client is in game, else false
|
||||||
*/
|
*/
|
||||||
public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
return client.currentScreen == null;
|
return client.currentScreen == null && MidnightControlsClient.get().input.screenCloseCooldown <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the client is in a non-interactive screen (which means require mouse input) or not.
|
* Returns whether the client is in a non-interactive screen (which means require mouse input) or not.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param binding The affected binding.
|
* @param binding the affected binding
|
||||||
* @return True if the client is in a non-interactive screen, else false.
|
* @return true if the client is in a non-interactive screen, else false
|
||||||
*/
|
*/
|
||||||
public static boolean inNonInteractiveScreens(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
public static boolean inNonInteractiveScreens(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
if (client.currentScreen == null)
|
if (client.currentScreen == null)
|
||||||
return false;
|
return false;
|
||||||
return !LambdaInput.isScreenInteractive(client.currentScreen);
|
return !MidnightInput.isScreenInteractive(client.currentScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the client is in an inventory or not.
|
* Returns whether the client is in an inventory or not.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param binding The affected binding.
|
* @param binding the affected binding
|
||||||
* @return True if the client is in an inventory, else false.
|
* @return true if the client is in an inventory, else false
|
||||||
*/
|
*/
|
||||||
public static boolean inInventory(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
public static boolean inInventory(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
return client.currentScreen instanceof HandledScreen;
|
return client.currentScreen instanceof HandledScreen;
|
||||||
@@ -263,9 +358,9 @@ public class InputHandlers {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the client is in the advancements screen or not.
|
* Returns whether the client is in the advancements screen or not.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param binding The affected binding.
|
* @param binding the affected binding
|
||||||
* @return True if the client is in the advancements screen, else false.
|
* @return true if the client is in the advancements screen, else false
|
||||||
*/
|
*/
|
||||||
public static boolean inAdvancements(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
public static boolean inAdvancements(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
return client.currentScreen instanceof AdvancementsScreen;
|
return client.currentScreen instanceof AdvancementsScreen;
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import dev.lambdaurora.lambdacontrols.client.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.MouseAccessor;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import org.aperlambda.lambdacommon.Identifier;
|
import org.aperlambda.lambdacommon.Identifier;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
|
||||||
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
@@ -33,25 +33,29 @@ import java.util.stream.Stream;
|
|||||||
* Represents an input manager for controllers.
|
* Represents an input manager for controllers.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.4.0
|
* @version 1.7.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class InputManager {
|
public class InputManager {
|
||||||
public static final InputManager INPUT_MANAGER = new InputManager();
|
public static final InputManager INPUT_MANAGER = new InputManager();
|
||||||
private static final List<ButtonBinding> BINDINGS = new ArrayList<>();
|
private static final List<ButtonBinding> BINDINGS = new ArrayList<>();
|
||||||
private static final List<ButtonCategory> CATEGORIES = new ArrayList<>();
|
private static final List<ButtonCategory> CATEGORIES = new ArrayList<>();
|
||||||
public static final Map<Integer, ButtonState> STATES = new HashMap<>();
|
public static final Int2ObjectMap<ButtonState> STATES = new Int2ObjectOpenHashMap<>();
|
||||||
public static final Map<Integer, Float> BUTTON_VALUES = new HashMap<>();
|
public static final Int2FloatMap BUTTON_VALUES = new Int2FloatOpenHashMap();
|
||||||
private int prevTargetMouseX = 0;
|
public int prevTargetMouseX = 0;
|
||||||
private int prevTargetMouseY = 0;
|
public int prevTargetMouseY = 0;
|
||||||
private int targetMouseX = 0;
|
public int targetMouseX = 0;
|
||||||
private int targetMouseY = 0;
|
public int targetMouseY = 0;
|
||||||
|
|
||||||
protected InputManager() {
|
protected InputManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick(@NotNull MinecraftClient client) {
|
public void tick(@NotNull MinecraftClient client) {
|
||||||
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
|
if (MidnightControlsConfig.autoSwitchMode && !MidnightControlsConfig.isEditing && MidnightControlsConfig.controlsMode != ControlsMode.TOUCHSCREEN)
|
||||||
|
if (MidnightControlsConfig.getController().isConnected() && MidnightControlsConfig.getController().isGamepad())
|
||||||
|
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||||
|
else MidnightControlsConfig.controlsMode = ControlsMode.DEFAULT;
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||||
this.controllerTick(client);
|
this.controllerTick(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,24 +68,24 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Updates the mouse position. Should only be called on pre render of a screen.
|
* Updates the mouse position. Should only be called on pre render of a screen.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
*/
|
*/
|
||||||
public void updateMousePosition(@NotNull MinecraftClient client) {
|
public void updateMousePosition(@NotNull MinecraftClient client) {
|
||||||
Objects.requireNonNull(client, "Client instance cannot be null.");
|
Objects.requireNonNull(client, "Client instance cannot be null.");
|
||||||
if (this.prevTargetMouseX != this.targetMouseX || this.prevTargetMouseY != this.targetMouseY) {
|
if (this.prevTargetMouseX != this.targetMouseX || this.prevTargetMouseY != this.targetMouseY) {
|
||||||
double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getTickDelta() + 0.5;
|
double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getTickDelta() + 0.5;
|
||||||
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getTickDelta() + 0.5;
|
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getTickDelta() + 0.5;
|
||||||
if (!LambdaControlsClient.get().config.hasVirtualMouse())
|
if (!MidnightControlsConfig.virtualMouse)
|
||||||
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
||||||
((MouseAccessor) client.mouse).lambdacontrols$onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the mouse position.
|
* Resets the mouse position.
|
||||||
*
|
*
|
||||||
* @param windowWidth The window width.
|
* @param windowWidth the window width
|
||||||
* @param windowHeight The window height.
|
* @param windowHeight the window height
|
||||||
*/
|
*/
|
||||||
public void resetMousePosition(int windowWidth, int windowHeight) {
|
public void resetMousePosition(int windowWidth, int windowHeight) {
|
||||||
this.targetMouseX = this.prevTargetMouseX = (int) (windowWidth / 2.F);
|
this.targetMouseX = this.prevTargetMouseX = (int) (windowWidth / 2.F);
|
||||||
@@ -98,8 +102,8 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the specified binding is registered or not.
|
* Returns whether the specified binding is registered or not.
|
||||||
*
|
*
|
||||||
* @param binding The binding to check.
|
* @param binding the binding to check
|
||||||
* @return True if the binding is registered, else false.
|
* @return true if the binding is registered, else false
|
||||||
*/
|
*/
|
||||||
public static boolean hasBinding(@NotNull ButtonBinding binding) {
|
public static boolean hasBinding(@NotNull ButtonBinding binding) {
|
||||||
return BINDINGS.contains(binding);
|
return BINDINGS.contains(binding);
|
||||||
@@ -108,8 +112,8 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the specified binding is registered or not.
|
* Returns whether the specified binding is registered or not.
|
||||||
*
|
*
|
||||||
* @param name The name of the binding to check.
|
* @param name the name of the binding to check
|
||||||
* @return True if the binding is registered, else false.
|
* @return true if the binding is registered, else false
|
||||||
*/
|
*/
|
||||||
public static boolean hasBinding(@NotNull String name) {
|
public static boolean hasBinding(@NotNull String name) {
|
||||||
return BINDINGS.parallelStream().map(ButtonBinding::getName).anyMatch(binding -> binding.equalsIgnoreCase(name));
|
return BINDINGS.parallelStream().map(ButtonBinding::getName).anyMatch(binding -> binding.equalsIgnoreCase(name));
|
||||||
@@ -118,8 +122,8 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the specified binding is registered or not.
|
* Returns whether the specified binding is registered or not.
|
||||||
*
|
*
|
||||||
* @param identifier The identifier of the binding to check.
|
* @param identifier the identifier of the binding to check
|
||||||
* @return True if the binding is registered, else false.
|
* @return true if the binding is registered, else false
|
||||||
*/
|
*/
|
||||||
public static boolean hasBinding(@NotNull Identifier identifier) {
|
public static boolean hasBinding(@NotNull Identifier identifier) {
|
||||||
return hasBinding(identifier.getNamespace() + "." + identifier.getName());
|
return hasBinding(identifier.getNamespace() + "." + identifier.getName());
|
||||||
@@ -128,8 +132,8 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Registers a button binding.
|
* Registers a button binding.
|
||||||
*
|
*
|
||||||
* @param binding The binding to register.
|
* @param binding the binding to register
|
||||||
* @return The registered binding.
|
* @return the registered binding
|
||||||
*/
|
*/
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull ButtonBinding binding) {
|
public static @NotNull ButtonBinding registerBinding(@NotNull ButtonBinding binding) {
|
||||||
if (hasBinding(binding))
|
if (hasBinding(binding))
|
||||||
@@ -159,8 +163,8 @@ public class InputManager {
|
|||||||
*/
|
*/
|
||||||
public static void sortBindings() {
|
public static void sortBindings() {
|
||||||
synchronized (BINDINGS) {
|
synchronized (BINDINGS) {
|
||||||
List<ButtonBinding> sorted = BINDINGS.stream().sorted(Collections.reverseOrder(Comparator.comparingInt(binding -> binding.getButton().length)))
|
var sorted = BINDINGS.stream()
|
||||||
.collect(Collectors.toList());
|
.sorted(Collections.reverseOrder(Comparator.comparingInt(binding -> binding.getButton().length))).toList();
|
||||||
BINDINGS.clear();
|
BINDINGS.clear();
|
||||||
BINDINGS.addAll(sorted);
|
BINDINGS.addAll(sorted);
|
||||||
}
|
}
|
||||||
@@ -169,8 +173,8 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Registers a category of button bindings.
|
* Registers a category of button bindings.
|
||||||
*
|
*
|
||||||
* @param category The category to register.
|
* @param category the category to register
|
||||||
* @return The registered category.
|
* @return the registered category
|
||||||
*/
|
*/
|
||||||
public static ButtonCategory registerCategory(@NotNull ButtonCategory category) {
|
public static ButtonCategory registerCategory(@NotNull ButtonCategory category) {
|
||||||
CATEGORIES.add(category);
|
CATEGORIES.add(category);
|
||||||
@@ -186,31 +190,29 @@ public class InputManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static ButtonCategory registerDefaultCategory(@NotNull String key, @NotNull Consumer<ButtonCategory> keyAdder) {
|
protected static ButtonCategory registerDefaultCategory(@NotNull String key, @NotNull Consumer<ButtonCategory> keyAdder) {
|
||||||
ButtonCategory category = registerCategory(new Identifier("minecraft", key), CATEGORIES.size());
|
var category = registerCategory(new Identifier("minecraft", key), CATEGORIES.size());
|
||||||
keyAdder.accept(category);
|
keyAdder.accept(category);
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the button bindings from configuration.
|
* Loads the button bindings from configuration.
|
||||||
*
|
|
||||||
* @param config The configuration instance.
|
|
||||||
*/
|
*/
|
||||||
public static void loadButtonBindings(@NotNull LambdaControlsConfig config) {
|
public static void loadButtonBindings() {
|
||||||
List<ButtonBinding> queue = new ArrayList<>(BINDINGS);
|
var queue = new ArrayList<>(BINDINGS);
|
||||||
queue.forEach(config::loadButtonBinding);
|
queue.forEach(MidnightControlsConfig::loadButtonBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the binding state.
|
* Returns the binding state.
|
||||||
*
|
*
|
||||||
* @param binding The binding.
|
* @param binding the binding
|
||||||
* @return The current state of the binding.
|
* @return the current state of the binding
|
||||||
*/
|
*/
|
||||||
public static @NotNull ButtonState getBindingState(@NotNull ButtonBinding binding) {
|
public static @NotNull ButtonState getBindingState(@NotNull ButtonBinding binding) {
|
||||||
ButtonState state = ButtonState.REPEAT;
|
var state = ButtonState.REPEAT;
|
||||||
for (int btn : binding.getButton()) {
|
for (int btn : binding.getButton()) {
|
||||||
ButtonState btnState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
|
var btnState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
|
||||||
if (btnState == ButtonState.PRESS)
|
if (btnState == ButtonState.PRESS)
|
||||||
state = ButtonState.PRESS;
|
state = ButtonState.PRESS;
|
||||||
else if (btnState == ButtonState.RELEASE) {
|
else if (btnState == ButtonState.RELEASE) {
|
||||||
@@ -243,8 +245,8 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the button has duplicated bindings.
|
* Returns whether the button has duplicated bindings.
|
||||||
*
|
*
|
||||||
* @param button The button to check.
|
* @param button the button to check
|
||||||
* @return True if the button has duplicated bindings, else false.
|
* @return true if the button has duplicated bindings, else false
|
||||||
*/
|
*/
|
||||||
public static boolean hasDuplicatedBindings(int[] button) {
|
public static boolean hasDuplicatedBindings(int[] button) {
|
||||||
return BINDINGS.parallelStream().filter(binding -> areButtonsEquivalent(binding.getButton(), button)).count() > 1;
|
return BINDINGS.parallelStream().filter(binding -> areButtonsEquivalent(binding.getButton(), button)).count() > 1;
|
||||||
@@ -253,8 +255,8 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the button has duplicated bindings.
|
* Returns whether the button has duplicated bindings.
|
||||||
*
|
*
|
||||||
* @param binding The binding to check.
|
* @param binding the binding to check
|
||||||
* @return True if the button has duplicated bindings, else false.
|
* @return true if the button has duplicated bindings, else false
|
||||||
*/
|
*/
|
||||||
public static boolean hasDuplicatedBindings(ButtonBinding binding) {
|
public static boolean hasDuplicatedBindings(ButtonBinding binding) {
|
||||||
return BINDINGS.parallelStream().filter(other -> areButtonsEquivalent(other.getButton(), binding.getButton()) && other.filter.equals(binding.filter)).count() > 1;
|
return BINDINGS.parallelStream().filter(other -> areButtonsEquivalent(other.getButton(), binding.getButton()) && other.filter.equals(binding.filter)).count() > 1;
|
||||||
@@ -263,9 +265,9 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the specified buttons are equivalent or not.
|
* Returns whether the specified buttons are equivalent or not.
|
||||||
*
|
*
|
||||||
* @param buttons1 First set of buttons.
|
* @param buttons1 first set of buttons
|
||||||
* @param buttons2 Second set of buttons.
|
* @param buttons2 second set of buttons
|
||||||
* @return True if the two sets of buttons are equivalent, else false.
|
* @return true if the two sets of buttons are equivalent, else false
|
||||||
*/
|
*/
|
||||||
public static boolean areButtonsEquivalent(int[] buttons1, int[] buttons2) {
|
public static boolean areButtonsEquivalent(int[] buttons1, int[] buttons2) {
|
||||||
if (buttons1.length != buttons2.length)
|
if (buttons1.length != buttons2.length)
|
||||||
@@ -285,9 +287,9 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the button set contains the specified button or not.
|
* Returns whether the button set contains the specified button or not.
|
||||||
*
|
*
|
||||||
* @param buttons The button set.
|
* @param buttons the button set
|
||||||
* @param button The button to check.
|
* @param button the button to check
|
||||||
* @return True if the button set contains the specified button, else false.
|
* @return true if the button set contains the specified button, else false
|
||||||
*/
|
*/
|
||||||
public static boolean containsButton(int[] buttons, int button) {
|
public static boolean containsButton(int[] buttons, int button) {
|
||||||
return Arrays.stream(buttons).anyMatch(btn -> btn == button);
|
return Arrays.stream(buttons).anyMatch(btn -> btn == button);
|
||||||
@@ -297,20 +299,22 @@ public class InputManager {
|
|||||||
* Updates the button states.
|
* Updates the button states.
|
||||||
*/
|
*/
|
||||||
public static void updateStates() {
|
public static void updateStates() {
|
||||||
STATES.forEach((btn, state) -> {
|
for (var entry : STATES.int2ObjectEntrySet()) {
|
||||||
if (state == ButtonState.PRESS)
|
if (entry.getValue() == ButtonState.PRESS)
|
||||||
STATES.put(btn, ButtonState.REPEAT);
|
STATES.put(entry.getIntKey(), ButtonState.REPEAT);
|
||||||
else if (state == ButtonState.RELEASE)
|
else if (entry.getValue() == ButtonState.RELEASE)
|
||||||
STATES.put(btn, ButtonState.NONE);
|
STATES.put(entry.getIntKey(), ButtonState.NONE);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateBindings(@NotNull MinecraftClient client) {
|
public static void updateBindings(@NotNull MinecraftClient client) {
|
||||||
List<Integer> skipButtons = new ArrayList<>();
|
var skipButtons = new IntArrayList();
|
||||||
Map<ButtonBinding, Pair<ButtonState, Float>> states = new HashMap<>();
|
record ButtonStateValue(ButtonState state, float value) {
|
||||||
for (ButtonBinding binding : BINDINGS) {
|
}
|
||||||
ButtonState state = binding.isAvailable(client) ? getBindingState(binding) : ButtonState.NONE;
|
var states = new Object2ObjectOpenHashMap<ButtonBinding, ButtonStateValue>();
|
||||||
if (skipButtons.stream().anyMatch(btn -> containsButton(binding.getButton(), btn))) {
|
for (var binding : BINDINGS) {
|
||||||
|
var state = binding.isAvailable(client) ? getBindingState(binding) : ButtonState.NONE;
|
||||||
|
if (skipButtons.intStream().anyMatch(btn -> containsButton(binding.getButton(), btn))) {
|
||||||
if (binding.pressed)
|
if (binding.pressed)
|
||||||
state = ButtonState.RELEASE;
|
state = ButtonState.RELEASE;
|
||||||
else
|
else
|
||||||
@@ -328,12 +332,12 @@ public class InputManager {
|
|||||||
|
|
||||||
float value = getBindingValue(binding, state);
|
float value = getBindingValue(binding, state);
|
||||||
|
|
||||||
states.put(binding, Pair.of(state, value));
|
states.put(binding, new ButtonStateValue(state, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
states.forEach((binding, state) -> {
|
states.forEach((binding, state) -> {
|
||||||
if (state.key != ButtonState.NONE) {
|
if (state.state() != ButtonState.NONE) {
|
||||||
binding.handle(client, state.value, state.key);
|
binding.handle(client, state.value(), state.state());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -358,11 +362,11 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns a new key binding instance.
|
* Returns a new key binding instance.
|
||||||
*
|
*
|
||||||
* @param id The identifier of the key binding.
|
* @param id the identifier of the key binding
|
||||||
* @param type The type.
|
* @param type the type
|
||||||
* @param code The code.
|
* @param code the code
|
||||||
* @param category The category of the key binding.
|
* @param category the category of the key binding
|
||||||
* @return The key binding.
|
* @return the key binding
|
||||||
* @see #makeKeyBinding(Identifier, InputUtil.Type, int, String)
|
* @see #makeKeyBinding(Identifier, InputUtil.Type, int, String)
|
||||||
*/
|
*/
|
||||||
public static @NotNull KeyBinding makeKeyBinding(@NotNull net.minecraft.util.Identifier id, InputUtil.Type type, int code, @NotNull String category) {
|
public static @NotNull KeyBinding makeKeyBinding(@NotNull net.minecraft.util.Identifier id, InputUtil.Type type, int code, @NotNull String category) {
|
||||||
@@ -372,11 +376,11 @@ public class InputManager {
|
|||||||
/**
|
/**
|
||||||
* Returns a new key binding instance.
|
* Returns a new key binding instance.
|
||||||
*
|
*
|
||||||
* @param id The identifier of the key binding.
|
* @param id the identifier of the key binding
|
||||||
* @param type The type.
|
* @param type the type
|
||||||
* @param code The code.
|
* @param code the code
|
||||||
* @param category The category of the key binding.
|
* @param category the category of the key binding
|
||||||
* @return The key binding.
|
* @return the key binding
|
||||||
* @see #makeKeyBinding(net.minecraft.util.Identifier, InputUtil.Type, int, String)
|
* @see #makeKeyBinding(net.minecraft.util.Identifier, InputUtil.Type, int, String)
|
||||||
*/
|
*/
|
||||||
public static @NotNull KeyBinding makeKeyBinding(@NotNull Identifier id, InputUtil.Type type, int code, @NotNull String category) {
|
public static @NotNull KeyBinding makeKeyBinding(@NotNull Identifier id, InputUtil.Type type, int code, @NotNull String category) {
|
||||||
@@ -1,18 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.input.Input;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
|
import net.minecraft.client.tutorial.MovementTutorialStepHandler;
|
||||||
|
import net.minecraft.client.util.InputUtil;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.enchantment.Enchantments;
|
||||||
|
import net.minecraft.enchantment.SoulSpeedEnchantment;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.nbt.NbtList;
|
||||||
|
import net.minecraft.nbt.scanner.SimpleNbtScanner;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,7 +79,7 @@ public final class MovementHandler implements PressAction {
|
|||||||
|
|
||||||
this.shouldOverrideMovement = direction != 0;
|
this.shouldOverrideMovement = direction != 0;
|
||||||
|
|
||||||
if (LambdaControlsClient.get().config.hasAnalogMovement()) {
|
if (MidnightControlsConfig.analogMovement) {
|
||||||
value = (float) Math.pow(value, 2);
|
value = (float) Math.pow(value, 2);
|
||||||
} else value = 1.f;
|
} else value = 1.f;
|
||||||
|
|
||||||
@@ -78,18 +89,20 @@ public final class MovementHandler implements PressAction {
|
|||||||
this.pressingBack = direction < 0;
|
this.pressingBack = direction < 0;
|
||||||
this.movementForward = direction * value;
|
this.movementForward = direction * value;
|
||||||
|
|
||||||
// Slowing down if sneaking.
|
// Slowing down if sneaking or crawling.
|
||||||
if (client.player.input.sneaking)
|
if (client.player.shouldSlowDown()) {
|
||||||
this.movementForward *= 0.3D;
|
this.movementForward *= MathHelper.clamp(0.3F, 0.0F, 1.0F);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Handle sideways movement.
|
// Handle sideways movement.
|
||||||
this.pressingLeft = direction > 0;
|
this.pressingLeft = direction > 0;
|
||||||
this.pressingRight = direction < 0;
|
this.pressingRight = direction < 0;
|
||||||
this.movementSideways = direction * value;
|
this.movementSideways = direction * value;
|
||||||
|
|
||||||
// Slowing down if sneaking.
|
// Slowing down if sneaking or crawling.
|
||||||
if (client.player.input.sneaking)
|
if (client.player.shouldSlowDown()) {
|
||||||
this.movementSideways *= 0.3D;
|
this.movementSideways *= MathHelper.clamp(0.3F, 0.0F, 1.0F);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.shouldOverrideMovement;
|
return this.shouldOverrideMovement;
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.options.StickyKeyBinding;
|
import net.minecraft.client.option.StickyKeyBinding;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a press action callback.
|
* Represents a press action callback.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.4.3
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
@@ -31,7 +31,7 @@ public interface PressAction {
|
|||||||
if (binding instanceof StickyKeyBinding)
|
if (binding instanceof StickyKeyBinding)
|
||||||
binding.setPressed(button.pressed);
|
binding.setPressed(button.pressed);
|
||||||
else
|
else
|
||||||
((KeyBindingAccessor) binding).lambdacontrols_handlePressState(button.isButtonDown());
|
((KeyBindingAccessor) binding).midnightcontrols$handlePressState(button.isButtonDown());
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -39,8 +39,8 @@ public interface PressAction {
|
|||||||
/**
|
/**
|
||||||
* Handles when there is a press action.
|
* Handles when there is a press action.
|
||||||
*
|
*
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
* @param action The action done.
|
* @param action the action done
|
||||||
*/
|
*/
|
||||||
boolean press(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action);
|
boolean press(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action);
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import me.lambdaurora.spruceui.Position;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import me.lambdaurora.spruceui.option.SpruceOption;
|
import dev.lambdaurora.spruceui.option.SpruceOption;
|
||||||
import me.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||||
import me.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
|
import dev.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
|
||||||
import net.minecraft.client.toast.SystemToast;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
|
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
@@ -27,7 +28,7 @@ import java.nio.file.Files;
|
|||||||
* Represents the controller mappings file editor screen.
|
* Represents the controller mappings file editor screen.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.4.3
|
* @version 1.7.0
|
||||||
* @since 1.4.3
|
* @since 1.4.3
|
||||||
*/
|
*/
|
||||||
public class MappingsStringInputWidget extends SpruceContainerWidget {
|
public class MappingsStringInputWidget extends SpruceContainerWidget {
|
||||||
@@ -37,7 +38,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
|||||||
|
|
||||||
protected MappingsStringInputWidget(Position position, int width, int height) {
|
protected MappingsStringInputWidget(Position position, int width, int height) {
|
||||||
super(position, width, height);
|
super(position, width, height);
|
||||||
//super(new TranslatableText("lambdacontrols.menu.title.mappings.string"));
|
//super(new TranslatableText("midnightcontrols.menu.title.mappings.string"));
|
||||||
|
|
||||||
this.reloadMappingsOption = ReloadControllerMappingsOption.newOption(btn -> {
|
this.reloadMappingsOption = ReloadControllerMappingsOption.newOption(btn -> {
|
||||||
this.writeMappings();
|
this.writeMappings();
|
||||||
@@ -59,13 +60,13 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
|||||||
if (this.textArea != null) {
|
if (this.textArea != null) {
|
||||||
this.mappings = this.textArea.getText();
|
this.mappings = this.textArea.getText();
|
||||||
try {
|
try {
|
||||||
FileWriter fw = new FileWriter(LambdaControlsClient.MAPPINGS_FILE, false);
|
var fw = new FileWriter(MidnightControlsClient.MAPPINGS_FILE, false);
|
||||||
fw.write(this.mappings);
|
fw.write(this.mappings);
|
||||||
fw.close();
|
fw.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (this.client != null)
|
if (this.client != null)
|
||||||
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.TUTORIAL_HINT,
|
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.TUTORIAL_HINT,
|
||||||
new TranslatableText("lambdacontrols.controller.mappings.error.write"), LiteralText.EMPTY));
|
new TranslatableText("midnightcontrols.controller.mappings.error.write"), Text.of("")));
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,13 +77,13 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
|||||||
this.mappings = this.textArea.getText();
|
this.mappings = this.textArea.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
String mappings = "";
|
var mappings = "";
|
||||||
|
|
||||||
if (this.mappings != null)
|
if (this.mappings != null)
|
||||||
mappings = this.mappings;
|
mappings = this.mappings;
|
||||||
else if (LambdaControlsClient.MAPPINGS_FILE.exists()) {
|
else if (MidnightControlsClient.MAPPINGS_FILE.exists()) {
|
||||||
try {
|
try {
|
||||||
mappings = String.join("\n", Files.readAllLines(LambdaControlsClient.MAPPINGS_FILE.toPath()));
|
mappings = String.join("\n", Files.readAllLines(MidnightControlsClient.MAPPINGS_FILE.toPath()));
|
||||||
this.mappings = mappings;
|
this.mappings = mappings;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
/* Ignored */
|
/* Ignored */
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControlsConstants;
|
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||||
import dev.lambdaurora.lambdacontrols.client.HudSide;
|
import eu.midnightdust.midnightcontrols.client.HudSide;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
import me.lambdaurora.spruceui.hud.Hud;
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import dev.lambdaurora.spruceui.hud.Hud;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.client.util.Window;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
@@ -29,14 +30,14 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the LambdaControls HUD.
|
* Represents the midnightcontrols HUD.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.3.2
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public class LambdaControlsHud extends Hud {
|
public class MidnightControlsHud extends Hud {
|
||||||
private final LambdaControlsClient mod;
|
private final MidnightControlsClient mod;
|
||||||
private MinecraftClient client;
|
private MinecraftClient client;
|
||||||
private int attackWidth = 0;
|
private int attackWidth = 0;
|
||||||
private int attackButtonWidth = 0;
|
private int attackButtonWidth = 0;
|
||||||
@@ -52,9 +53,10 @@ public class LambdaControlsHud extends Hud {
|
|||||||
private String attackAction = "";
|
private String attackAction = "";
|
||||||
private String placeAction = "";
|
private String placeAction = "";
|
||||||
private int ticksDisplayedCrosshair = 0;
|
private int ticksDisplayedCrosshair = 0;
|
||||||
|
private static float scale = 1f;
|
||||||
|
|
||||||
public LambdaControlsHud(@NotNull LambdaControlsClient mod) {
|
public MidnightControlsHud(@NotNull MidnightControlsClient mod) {
|
||||||
super(new Identifier(LambdaControlsConstants.NAMESPACE, "hud/button_indicator"));
|
super(new Identifier(MidnightControlsConstants.NAMESPACE, "hud/button_indicator"));
|
||||||
this.mod = mod;
|
this.mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,32 +65,40 @@ public class LambdaControlsHud extends Hud {
|
|||||||
super.init(client, screenWidth, screenHeight);
|
super.init(client, screenWidth, screenHeight);
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.inventoryWidth = this.width(ButtonBinding.INVENTORY);
|
this.inventoryWidth = this.width(ButtonBinding.INVENTORY);
|
||||||
this.inventoryButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY);
|
this.inventoryButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY);
|
||||||
this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS);
|
this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS);
|
||||||
this.swapHandsButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.SWAP_HANDS);
|
this.swapHandsButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.SWAP_HANDS);
|
||||||
this.dropItemWidth = this.width(ButtonBinding.DROP_ITEM);
|
this.dropItemWidth = this.width(ButtonBinding.DROP_ITEM);
|
||||||
this.dropItemButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.DROP_ITEM);
|
this.dropItemButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.DROP_ITEM);
|
||||||
this.attackButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.ATTACK);
|
this.attackButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.ATTACK);
|
||||||
this.useButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.USE);
|
this.useButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.USE);
|
||||||
|
if (client.options.guiScale >= 4) {
|
||||||
|
scale = 0.75f;
|
||||||
|
} else scale = 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the LambdaControls' HUD.
|
* Renders the midnightcontrols' HUD.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void render(MatrixStack matrices, float tickDelta) {
|
public void render(MatrixStack matrices, float tickDelta) {
|
||||||
if (this.mod.config.getControlsMode() == ControlsMode.CONTROLLER && this.client.currentScreen == null) {
|
if (this.client == null) return;
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && this.client.currentScreen == null) {
|
||||||
int y = bottom(2);
|
int y = bottom(2);
|
||||||
this.renderFirstIcons(matrices, this.mod.config.getHudSide() == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
matrices.push();
|
||||||
this.renderSecondIcons(matrices, this.mod.config.getHudSide() == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
if (scale != 1f) matrices.scale(scale,scale,scale);
|
||||||
this.renderFirstSection(matrices, this.mod.config.getHudSide() == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
this.renderFirstIcons(matrices, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : (int) ((client.getWindow().getScaledWidth() - 2) * (1 / scale)), y);
|
||||||
this.renderSecondSection(matrices, this.mod.config.getHudSide() == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
this.renderSecondIcons(matrices, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : (int) ((client.getWindow().getScaledWidth() - 2) * (1 / scale)), y);
|
||||||
|
this.renderFirstSection(matrices, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : (int) ((client.getWindow().getScaledWidth() - 2) * (1 / scale)), y);
|
||||||
|
this.renderSecondSection(matrices, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : (int) ((client.getWindow().getScaledWidth() - 2) * (1 / scale)), y);
|
||||||
|
matrices.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mod.reacharound.isLastReacharoundVertical()) {
|
if (this.mod.reacharound.isLastReacharoundVertical()) {
|
||||||
// Render crosshair indicator.
|
// Render crosshair indicator.
|
||||||
Window window = this.client.getWindow();
|
var window = this.client.getWindow();
|
||||||
String text = "[ ]";
|
var text = "[ ]";
|
||||||
|
|
||||||
float scale = Math.min(5, this.ticksDisplayedCrosshair + tickDelta) / 5F;
|
float scale = Math.min(5, this.ticksDisplayedCrosshair + tickDelta) / 5F;
|
||||||
scale *= scale;
|
scale *= scale;
|
||||||
@@ -101,14 +111,14 @@ public class LambdaControlsHud extends Hud {
|
|||||||
|
|
||||||
public void renderFirstIcons(MatrixStack matrices, int x, int y) {
|
public void renderFirstIcons(MatrixStack matrices, int x, int y) {
|
||||||
int offset = 2 + this.inventoryWidth + this.inventoryButtonWidth + 4;
|
int offset = 2 + this.inventoryWidth + this.inventoryButtonWidth + 4;
|
||||||
int currentX = this.mod.config.getHudSide() == HudSide.LEFT ? x : x - this.inventoryButtonWidth;
|
int currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.inventoryButtonWidth;
|
||||||
this.drawButton(matrices, currentX, y, ButtonBinding.INVENTORY, true);
|
this.drawButton(matrices, currentX, y, ButtonBinding.INVENTORY, true);
|
||||||
this.drawButton(matrices, currentX += (this.mod.config.getHudSide() == HudSide.LEFT ? offset : -offset), y, ButtonBinding.SWAP_HANDS, true);
|
this.drawButton(matrices, currentX += (MidnightControlsConfig.hudSide == HudSide.LEFT ? offset : -offset), y, ButtonBinding.SWAP_HANDS, true);
|
||||||
offset = 2 + this.swapHandsWidth + this.dropItemButtonWidth + 4;
|
offset = 2 + this.swapHandsWidth + this.dropItemButtonWidth + 4;
|
||||||
if (this.client.options.showSubtitles && this.mod.config.getHudSide() == HudSide.RIGHT) {
|
if (this.client.options.showSubtitles && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
||||||
currentX += -offset;
|
currentX += -offset;
|
||||||
} else {
|
} else {
|
||||||
currentX = this.mod.config.getHudSide() == HudSide.LEFT ? x : x - this.dropItemButtonWidth;
|
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.dropItemButtonWidth;
|
||||||
y -= 24;
|
y -= 24;
|
||||||
}
|
}
|
||||||
this.drawButton(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
this.drawButton(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
||||||
@@ -118,11 +128,11 @@ public class LambdaControlsHud extends Hud {
|
|||||||
int offset;
|
int offset;
|
||||||
int currentX = x;
|
int currentX = x;
|
||||||
if (!this.placeAction.isEmpty()) {
|
if (!this.placeAction.isEmpty()) {
|
||||||
if (this.mod.config.getHudSide() == HudSide.LEFT)
|
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
||||||
currentX -= this.useButtonWidth;
|
currentX -= this.useButtonWidth;
|
||||||
this.drawButton(matrices, currentX, y, ButtonBinding.USE, true);
|
this.drawButton(matrices, currentX, y, ButtonBinding.USE, true);
|
||||||
offset = 2 + this.useWidth + 4;
|
offset = 2 + this.useWidth + 4;
|
||||||
if (this.client.options.showSubtitles && this.mod.config.getHudSide() == HudSide.LEFT) {
|
if (this.client.options.showSubtitles && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||||
currentX -= offset;
|
currentX -= offset;
|
||||||
} else {
|
} else {
|
||||||
currentX = x;
|
currentX = x;
|
||||||
@@ -130,23 +140,23 @@ public class LambdaControlsHud extends Hud {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mod.config.getHudSide() == HudSide.LEFT)
|
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
||||||
currentX -= this.attackButtonWidth;
|
currentX -= this.attackButtonWidth;
|
||||||
|
|
||||||
this.drawButton(matrices, currentX, y, ButtonBinding.ATTACK, this.attackWidth != 0);
|
this.drawButton(matrices, currentX, y, ButtonBinding.ATTACK, this.attackWidth != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderFirstSection(MatrixStack matrices, int x, int y) {
|
public void renderFirstSection(MatrixStack matrices, int x, int y) {
|
||||||
int currentX = this.mod.config.getHudSide() == HudSide.LEFT ? x + this.inventoryButtonWidth + 2 : x - this.inventoryButtonWidth - 2 - this.inventoryWidth;
|
int currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x + this.inventoryButtonWidth + 2 : x - this.inventoryButtonWidth - 2 - this.inventoryWidth;
|
||||||
this.drawTip(matrices, currentX, y, ButtonBinding.INVENTORY, true);
|
this.drawTip(matrices, currentX, y, ButtonBinding.INVENTORY, true);
|
||||||
currentX += this.mod.config.getHudSide() == HudSide.LEFT ? this.inventoryWidth + 4 + this.swapHandsButtonWidth + 2
|
currentX += MidnightControlsConfig.hudSide == HudSide.LEFT ? this.inventoryWidth + 4 + this.swapHandsButtonWidth + 2
|
||||||
: -this.swapHandsWidth - 2 - this.swapHandsButtonWidth - 4;
|
: -this.swapHandsWidth - 2 - this.swapHandsButtonWidth - 4;
|
||||||
this.drawTip(matrices, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
this.drawTip(matrices, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
||||||
if (this.client.options.showSubtitles && this.mod.config.getHudSide() == HudSide.RIGHT) {
|
if (this.client.options.showSubtitles && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
||||||
currentX += -this.dropItemWidth - 2 - this.dropItemButtonWidth - 4;
|
currentX += -this.dropItemWidth - 2 - this.dropItemButtonWidth - 4;
|
||||||
} else {
|
} else {
|
||||||
y -= 24;
|
y -= 24;
|
||||||
currentX = this.mod.config.getHudSide() == HudSide.LEFT ? x + this.dropItemButtonWidth + 2 : x - this.dropItemButtonWidth - 2 - this.dropItemWidth;
|
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x + this.dropItemButtonWidth + 2 : x - this.dropItemButtonWidth - 2 - this.dropItemWidth;
|
||||||
}
|
}
|
||||||
this.drawTip(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
this.drawTip(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
||||||
}
|
}
|
||||||
@@ -155,11 +165,11 @@ public class LambdaControlsHud extends Hud {
|
|||||||
int currentX = x;
|
int currentX = x;
|
||||||
|
|
||||||
if (!this.placeAction.isEmpty()) {
|
if (!this.placeAction.isEmpty()) {
|
||||||
currentX += this.mod.config.getHudSide() == HudSide.RIGHT ? this.useButtonWidth + 2 : -this.useButtonWidth - 2 - this.useWidth;
|
currentX += MidnightControlsConfig.hudSide == HudSide.RIGHT ? this.useButtonWidth + 2 : -this.useButtonWidth - 2 - this.useWidth;
|
||||||
|
|
||||||
this.drawTip(matrices, currentX, y, this.placeAction, true);
|
this.drawTip(matrices, currentX, y, this.placeAction, true);
|
||||||
|
|
||||||
if (this.client.options.showSubtitles && this.mod.config.getHudSide() == HudSide.LEFT) {
|
if (this.client.options.showSubtitles && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||||
currentX -= 4;
|
currentX -= 4;
|
||||||
} else {
|
} else {
|
||||||
currentX = x;
|
currentX = x;
|
||||||
@@ -167,7 +177,7 @@ public class LambdaControlsHud extends Hud {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentX += this.mod.config.getHudSide() == HudSide.RIGHT ? this.attackButtonWidth + 2 : -this.attackButtonWidth - 2 - this.attackWidth;
|
currentX += MidnightControlsConfig.hudSide == HudSide.RIGHT ? this.attackButtonWidth + 2 : -this.attackButtonWidth - 2 - this.attackWidth;
|
||||||
|
|
||||||
this.drawTip(matrices, currentX, y, this.attackAction, this.attackWidth != 0);
|
this.drawTip(matrices, currentX, y, this.attackAction, this.attackWidth != 0);
|
||||||
}
|
}
|
||||||
@@ -175,7 +185,7 @@ public class LambdaControlsHud extends Hud {
|
|||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
if (this.mod.config.getControlsMode() == ControlsMode.CONTROLLER) {
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||||
if (this.client.crosshairTarget == null)
|
if (this.client.crosshairTarget == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -192,7 +202,7 @@ public class LambdaControlsHud extends Hud {
|
|||||||
else
|
else
|
||||||
this.placeHitResult = null;
|
this.placeHitResult = null;
|
||||||
|
|
||||||
this.attackAction = this.client.crosshairTarget.getType() == HitResult.Type.BLOCK ? "lambdacontrols.action.hit" : ButtonBinding.ATTACK.getTranslationKey();
|
this.attackAction = this.client.crosshairTarget.getType() == HitResult.Type.BLOCK ? "midnightcontrols.action.hit" : ButtonBinding.ATTACK.getTranslationKey();
|
||||||
this.attackWidth = this.width(attackAction);
|
this.attackWidth = this.width(attackAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +213,7 @@ public class LambdaControlsHud extends Hud {
|
|||||||
this.ticksDisplayedCrosshair = 0;
|
this.ticksDisplayedCrosshair = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String customAttackAction = LambdaControlsCompat.getAttackActionAt(this.client, this.placeHitResult);
|
var customAttackAction = MidnightControlsCompat.getAttackActionAt(this.client, this.placeHitResult);
|
||||||
if (customAttackAction != null) {
|
if (customAttackAction != null) {
|
||||||
this.attackAction = customAttackAction;
|
this.attackAction = customAttackAction;
|
||||||
this.attackWidth = this.width(customAttackAction);
|
this.attackWidth = this.width(customAttackAction);
|
||||||
@@ -219,13 +229,13 @@ public class LambdaControlsHud extends Hud {
|
|||||||
placeAction = "";
|
placeAction = "";
|
||||||
} else {
|
} else {
|
||||||
if (this.placeHitResult != null && stack.getItem() instanceof BlockItem) {
|
if (this.placeHitResult != null && stack.getItem() instanceof BlockItem) {
|
||||||
placeAction = "lambdacontrols.action.place";
|
placeAction = "midnightcontrols.action.place";
|
||||||
} else {
|
} else {
|
||||||
placeAction = ButtonBinding.USE.getTranslationKey();
|
placeAction = ButtonBinding.USE.getTranslationKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String customUseAction = LambdaControlsCompat.getUseActionAt(this.client, this.placeHitResult);
|
var customUseAction = MidnightControlsCompat.getUseActionAt(this.client, this.placeHitResult);
|
||||||
if (customUseAction != null)
|
if (customUseAction != null)
|
||||||
placeAction = customUseAction;
|
placeAction = customUseAction;
|
||||||
|
|
||||||
@@ -245,7 +255,7 @@ public class LambdaControlsHud extends Hud {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int bottom(int y) {
|
private int bottom(int y) {
|
||||||
return this.client.getWindow().getScaledHeight() - y - LambdaControlsRenderer.ICON_SIZE;
|
return (int) ((this.client.getWindow().getScaledHeight() * (1/scale)) - y - MidnightControlsRenderer.ICON_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int width(@NotNull ButtonBinding binding) {
|
private int width(@NotNull ButtonBinding binding) {
|
||||||
@@ -260,7 +270,7 @@ public class LambdaControlsHud extends Hud {
|
|||||||
|
|
||||||
private void drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display) {
|
private void drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display) {
|
||||||
if (display)
|
if (display)
|
||||||
LambdaControlsRenderer.drawButton(matrices, x, y, button, this.client);
|
MidnightControlsRenderer.drawButton(matrices, x, y, button, this.client);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawTip(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display) {
|
private void drawTip(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display) {
|
||||||
@@ -270,8 +280,8 @@ public class LambdaControlsHud extends Hud {
|
|||||||
private void drawTip(MatrixStack matrices, int x, int y, @NotNull String action, boolean display) {
|
private void drawTip(MatrixStack matrices, int x, int y, @NotNull String action, boolean display) {
|
||||||
if (!display)
|
if (!display)
|
||||||
return;
|
return;
|
||||||
String translatedAction = I18n.translate(action);
|
var translatedAction = I18n.translate(action);
|
||||||
int textY = (LambdaControlsRenderer.ICON_SIZE / 2 - this.client.textRenderer.fontHeight / 2) + 1;
|
int textY = (MidnightControlsRenderer.ICON_SIZE / 2 - this.client.textRenderer.fontHeight / 2) + 1;
|
||||||
this.client.textRenderer.draw(matrices, translatedAction, (float) x, (float) (y + textY), 14737632);
|
this.client.textRenderer.draw(matrices, translatedAction, (float) x, (float) (y + textY), 14737632);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,66 +1,60 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaInput;
|
import eu.midnightdust.midnightcontrols.client.ControllerType;
|
||||||
import dev.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
import net.minecraft.client.font.TextRenderer;
|
||||||
import net.minecraft.client.gui.DrawableHelper;
|
import net.minecraft.client.gui.DrawableHelper;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the LambdaControls renderer.
|
* Represents the midnightcontrols renderer.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.5.0
|
* @version 1.7.0
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public class LambdaControlsRenderer {
|
public class MidnightControlsRenderer {
|
||||||
public static final int ICON_SIZE = 20;
|
public static final int ICON_SIZE = 20;
|
||||||
private static final int BUTTON_SIZE = 15;
|
private static final int BUTTON_SIZE = 15;
|
||||||
private static final int AXIS_SIZE = 18;
|
private static final int AXIS_SIZE = 18;
|
||||||
|
|
||||||
public static int getButtonSize(int button) {
|
public static int getButtonSize(int button) {
|
||||||
switch (button) {
|
return switch (button) {
|
||||||
case -1:
|
case -1 -> 0;
|
||||||
return 0;
|
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100, GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200,
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100:
|
GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100, GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200,
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200:
|
GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100, GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200,
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100:
|
GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100, GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200 -> AXIS_SIZE;
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200:
|
default -> BUTTON_SIZE;
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100:
|
};
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200:
|
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100:
|
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200:
|
|
||||||
return AXIS_SIZE;
|
|
||||||
default:
|
|
||||||
return BUTTON_SIZE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the binding icon width.
|
* Gets the binding icon width.
|
||||||
*
|
*
|
||||||
* @param binding The binding.
|
* @param binding the binding
|
||||||
* @return The width.
|
* @return the width
|
||||||
*/
|
*/
|
||||||
public static int getBindingIconWidth(@NotNull ButtonBinding binding) {
|
public static int getBindingIconWidth(@NotNull ButtonBinding binding) {
|
||||||
return getBindingIconWidth(binding.getButton());
|
return getBindingIconWidth(binding.getButton());
|
||||||
@@ -69,8 +63,8 @@ public class LambdaControlsRenderer {
|
|||||||
/**
|
/**
|
||||||
* Gets the binding icon width.
|
* Gets the binding icon width.
|
||||||
*
|
*
|
||||||
* @param buttons The buttons.
|
* @param buttons the buttons
|
||||||
* @return The width.
|
* @return the width
|
||||||
*/
|
*/
|
||||||
public static int getBindingIconWidth(int[] buttons) {
|
public static int getBindingIconWidth(int[] buttons) {
|
||||||
int width = 0;
|
int width = 0;
|
||||||
@@ -83,11 +77,11 @@ public class LambdaControlsRenderer {
|
|||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Pair<Integer, Integer> drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client) {
|
public static ButtonSize drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client) {
|
||||||
return drawButton(matrices, x, y, button.getButton(), client);
|
return drawButton(matrices, x, y, button.getButton(), client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Pair<Integer, Integer> drawButton(MatrixStack matrices, int x, int y, int[] buttons, @NotNull MinecraftClient client) {
|
public static ButtonSize drawButton(MatrixStack matrices, int x, int y, int[] buttons, @NotNull MinecraftClient client) {
|
||||||
int height = 0;
|
int height = 0;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
int currentX = x;
|
int currentX = x;
|
||||||
@@ -102,10 +96,9 @@ public class LambdaControlsRenderer {
|
|||||||
currentX = x + length;
|
currentX = x + length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Pair.of(length, height);
|
return new ButtonSize(length, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecated")
|
|
||||||
public static int drawButton(MatrixStack matrices, int x, int y, int button, @NotNull MinecraftClient client) {
|
public static int drawButton(MatrixStack matrices, int x, int y, int button, @NotNull MinecraftClient client) {
|
||||||
boolean second = false;
|
boolean second = false;
|
||||||
if (button == -1)
|
if (button == -1)
|
||||||
@@ -115,81 +108,65 @@ public class LambdaControlsRenderer {
|
|||||||
second = true;
|
second = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int controllerType = LambdaControlsClient.get().config.getControllerType().getId();
|
int controllerType = MidnightControlsConfig.controllerType == ControllerType.DEFAULT ? MidnightControlsConfig.matchControllerToType().getId() : MidnightControlsConfig.controllerType.getId();
|
||||||
boolean axis = false;
|
boolean axis = false;
|
||||||
int buttonOffset = button * 15;
|
int buttonOffset = button * 15;
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
|
case 15 -> buttonOffset = 0;
|
||||||
buttonOffset = 7 * 15;
|
case 16 -> buttonOffset = 18;
|
||||||
break;
|
case 17 -> buttonOffset = 36;
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
|
case 18 -> buttonOffset = 54;
|
||||||
buttonOffset = 8 * 15;
|
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER -> buttonOffset = 7 * 15;
|
||||||
break;
|
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER -> buttonOffset = 8 * 15;
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_BACK:
|
case GLFW.GLFW_GAMEPAD_BUTTON_BACK -> buttonOffset = 4 * 15;
|
||||||
buttonOffset = 4 * 15;
|
case GLFW.GLFW_GAMEPAD_BUTTON_START -> buttonOffset = 6 * 15;
|
||||||
break;
|
case GLFW.GLFW_GAMEPAD_BUTTON_GUIDE -> buttonOffset = 5 * 15;
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_START:
|
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB -> buttonOffset = 15 * 15;
|
||||||
buttonOffset = 6 * 15;
|
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB -> buttonOffset = 16 * 15;
|
||||||
break;
|
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100 -> {
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_GUIDE:
|
|
||||||
buttonOffset = 5 * 15;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
|
|
||||||
buttonOffset = 15 * 15;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
|
|
||||||
buttonOffset = 16 * 15;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100:
|
|
||||||
buttonOffset = 0;
|
buttonOffset = 0;
|
||||||
axis = true;
|
axis = true;
|
||||||
break;
|
}
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100:
|
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100 -> {
|
||||||
buttonOffset = 18;
|
buttonOffset = 18;
|
||||||
axis = true;
|
axis = true;
|
||||||
break;
|
}
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100:
|
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100 -> {
|
||||||
buttonOffset = 2 * 18;
|
buttonOffset = 2 * 18;
|
||||||
axis = true;
|
axis = true;
|
||||||
break;
|
}
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100:
|
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100 -> {
|
||||||
buttonOffset = 3 * 18;
|
buttonOffset = 3 * 18;
|
||||||
axis = true;
|
axis = true;
|
||||||
break;
|
}
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200:
|
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200 -> {
|
||||||
buttonOffset = 4 * 18;
|
buttonOffset = 4 * 18;
|
||||||
axis = true;
|
axis = true;
|
||||||
break;
|
}
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200:
|
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200 -> {
|
||||||
buttonOffset = 5 * 18;
|
buttonOffset = 5 * 18;
|
||||||
axis = true;
|
axis = true;
|
||||||
break;
|
}
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200:
|
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200 -> {
|
||||||
buttonOffset = 6 * 18;
|
buttonOffset = 6 * 18;
|
||||||
axis = true;
|
axis = true;
|
||||||
break;
|
}
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200:
|
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200 -> {
|
||||||
buttonOffset = 7 * 18;
|
buttonOffset = 7 * 18;
|
||||||
axis = true;
|
axis = true;
|
||||||
break;
|
}
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 100:
|
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 100, GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 200 -> buttonOffset = 9 * 15;
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 200:
|
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100, GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200 -> buttonOffset = 10 * 15;
|
||||||
buttonOffset = 9 * 15;
|
|
||||||
break;
|
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100:
|
|
||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200:
|
|
||||||
buttonOffset = 10 * 15;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client.getTextureManager().bindTexture(axis ? LambdaControlsClient.CONTROLLER_AXIS : LambdaControlsClient.CONTROLLER_BUTTONS);
|
RenderSystem.setShaderTexture(0, axis ? MidnightControlsClient.CONTROLLER_AXIS : button >= 15 && button <= 19 ? MidnightControlsClient.CONTROLLER_EXPANDED :MidnightControlsClient.CONTROLLER_BUTTONS);
|
||||||
RenderSystem.disableDepthTest();
|
RenderSystem.disableDepthTest();
|
||||||
|
|
||||||
int assetSize = axis ? AXIS_SIZE : BUTTON_SIZE;
|
int assetSize = axis || (button >= 15 && button <= 18) ? AXIS_SIZE : BUTTON_SIZE;
|
||||||
|
|
||||||
RenderSystem.color4f(1.0F, second ? 0.0F : 1.0F, 1.0F, 1.0F);
|
RenderSystem.setShaderColor(1.f, second ? 0.f : 1.f, 1.f, 1.f);
|
||||||
DrawableHelper.drawTexture(matrices, x + (ICON_SIZE / 2 - assetSize / 2), y + (ICON_SIZE / 2 - assetSize / 2),
|
DrawableHelper.drawTexture(matrices, x + (ICON_SIZE / 2 - assetSize / 2), y + (ICON_SIZE / 2 - assetSize / 2),
|
||||||
(float) buttonOffset, (float) (controllerType * (axis ? AXIS_SIZE : BUTTON_SIZE)),
|
(float) buttonOffset, (float) (controllerType * assetSize),
|
||||||
assetSize, assetSize,
|
assetSize, assetSize,
|
||||||
256, 256);
|
256, 256);
|
||||||
RenderSystem.enableDepthTest();
|
RenderSystem.enableDepthTest();
|
||||||
@@ -203,10 +180,10 @@ public class LambdaControlsRenderer {
|
|||||||
|
|
||||||
public static int drawButtonTip(MatrixStack matrices, int x, int y, int[] button, @NotNull String action, boolean display, @NotNull MinecraftClient client) {
|
public static int drawButtonTip(MatrixStack matrices, int x, int y, int[] button, @NotNull String action, boolean display, @NotNull MinecraftClient client) {
|
||||||
if (display) {
|
if (display) {
|
||||||
int buttonWidth = drawButton(matrices, x, y, button, client).key;
|
int buttonWidth = drawButton(matrices, x, y, button, client).length();
|
||||||
|
|
||||||
String translatedAction = I18n.translate(action);
|
var translatedAction = I18n.translate(action);
|
||||||
int textY = (LambdaControlsRenderer.ICON_SIZE / 2 - client.textRenderer.fontHeight / 2) + 1;
|
int textY = (MidnightControlsRenderer.ICON_SIZE / 2 - client.textRenderer.fontHeight / 2) + 1;
|
||||||
|
|
||||||
return client.textRenderer.drawWithShadow(matrices, translatedAction, (float) (x + buttonWidth + 2), (float) (y + textY), 14737632);
|
return client.textRenderer.drawWithShadow(matrices, translatedAction, (float) (x + buttonWidth + 2), (float) (y + textY), 14737632);
|
||||||
}
|
}
|
||||||
@@ -219,7 +196,8 @@ public class LambdaControlsRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void renderVirtualCursor(@NotNull MatrixStack matrices, @NotNull MinecraftClient client) {
|
public static void renderVirtualCursor(@NotNull MatrixStack matrices, @NotNull MinecraftClient client) {
|
||||||
if (!LambdaControlsClient.get().config.hasVirtualMouse() || (client.currentScreen == null || LambdaInput.isScreenInteractive(client.currentScreen)))
|
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|
||||||
|
|| MidnightInput.isScreenInteractive(client.currentScreen)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int mouseX = (int) (client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
int mouseX = (int) (client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
||||||
@@ -227,12 +205,11 @@ public class LambdaControlsRenderer {
|
|||||||
|
|
||||||
boolean hoverSlot = false;
|
boolean hoverSlot = false;
|
||||||
|
|
||||||
if (client.currentScreen instanceof HandledScreen) {
|
if (client.currentScreen instanceof HandledScreenAccessor inventoryScreen) {
|
||||||
HandledScreenAccessor inventoryScreen = (HandledScreenAccessor) client.currentScreen;
|
|
||||||
int guiLeft = inventoryScreen.getX();
|
int guiLeft = inventoryScreen.getX();
|
||||||
int guiTop = inventoryScreen.getY();
|
int guiTop = inventoryScreen.getY();
|
||||||
|
|
||||||
Slot slot = inventoryScreen.lambdacontrols$getSlotAt(mouseX, mouseY);
|
Slot slot = inventoryScreen.midnightcontrols$getSlotAt(mouseX, mouseY);
|
||||||
|
|
||||||
if (slot != null) {
|
if (slot != null) {
|
||||||
mouseX = guiLeft + slot.x;
|
mouseX = guiLeft + slot.x;
|
||||||
@@ -242,11 +219,11 @@ public class LambdaControlsRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hoverSlot) {
|
if (!hoverSlot) {
|
||||||
Pair<Integer, Integer> slot = LambdaControlsCompat.getSlotAt(client.currentScreen, mouseX, mouseY);
|
var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, mouseX, mouseY);
|
||||||
|
|
||||||
if (slot != null) {
|
if (slot != null) {
|
||||||
mouseX = slot.getFirst();
|
mouseX = slot.x();
|
||||||
mouseY = slot.getSecond();
|
mouseY = slot.y();
|
||||||
hoverSlot = true;
|
hoverSlot = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,19 +239,23 @@ public class LambdaControlsRenderer {
|
|||||||
/**
|
/**
|
||||||
* Draws the virtual cursor.
|
* Draws the virtual cursor.
|
||||||
*
|
*
|
||||||
* @param matrices The matrix stack.
|
* @param matrices the matrix stack
|
||||||
* @param x X coordinate.
|
* @param x x coordinate
|
||||||
* @param y Y coordinate.
|
* @param y y coordinate
|
||||||
* @param hoverSlot True if hovering a slot, else false.
|
* @param hoverSlot true if hovering a slot, else false
|
||||||
* @param client The client instance.
|
* @param client the client instance
|
||||||
*/
|
*/
|
||||||
public static void drawCursor(@NotNull MatrixStack matrices, int x, int y, boolean hoverSlot, @NotNull MinecraftClient client) {
|
public static void drawCursor(@NotNull MatrixStack matrices, int x, int y, boolean hoverSlot, @NotNull MinecraftClient client) {
|
||||||
client.getTextureManager().bindTexture(LambdaControlsClient.CURSOR_TEXTURE);
|
|
||||||
|
|
||||||
RenderSystem.disableDepthTest();
|
RenderSystem.disableDepthTest();
|
||||||
|
|
||||||
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
|
||||||
DrawableHelper.drawTexture(matrices, x, y, hoverSlot ? 16.F : 0.F, LambdaControlsClient.get().config.getVirtualMouseSkin().ordinal() * 16.F, 16, 16, 32, 64);
|
RenderSystem.setShaderTexture(0, MidnightControlsClient.CURSOR_TEXTURE);
|
||||||
|
DrawableHelper.drawTexture(matrices, x, y,
|
||||||
|
hoverSlot ? 16.f : 0.f, MidnightControlsConfig.virtualMouseSkin.ordinal() * 16.f,
|
||||||
|
16, 16, 32, 64);
|
||||||
RenderSystem.enableDepthTest();
|
RenderSystem.enableDepthTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record ButtonSize(int length, int height) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,434 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import dev.lambdaurora.spruceui.background.Background;
|
||||||
|
import dev.lambdaurora.spruceui.widget.SpruceWidget;
|
||||||
|
import eu.midnightdust.lib.util.MidnightColorUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
||||||
|
import dev.lambdaurora.spruceui.Position;
|
||||||
|
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||||
|
import dev.lambdaurora.spruceui.option.*;
|
||||||
|
import dev.lambdaurora.spruceui.screen.SpruceScreen;
|
||||||
|
import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget;
|
||||||
|
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
||||||
|
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||||
|
import dev.lambdaurora.spruceui.widget.container.SpruceOptionListWidget;
|
||||||
|
import dev.lambdaurora.spruceui.widget.container.tabbed.SpruceTabbedWidget;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
|
import net.minecraft.client.render.*;
|
||||||
|
import net.minecraft.client.resource.language.I18n;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.MutableText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
|
import net.minecraft.util.Util;
|
||||||
|
import net.minecraft.util.math.Matrix4f;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the midnightcontrols settings screen.
|
||||||
|
*/
|
||||||
|
public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||||
|
private static final Text SDL2_GAMEPAD_TOOL = new LiteralText("SDL2 Gamepad Tool").formatted(Formatting.GREEN);
|
||||||
|
public static final String GAMEPAD_TOOL_URL = "https://generalarcade.com/gamepadtool/";
|
||||||
|
final MidnightControlsClient mod = MidnightControlsClient.get();
|
||||||
|
private final Screen parent;
|
||||||
|
// General options
|
||||||
|
private final SpruceOption inputModeOption;
|
||||||
|
private final SpruceOption autoSwitchModeOption;
|
||||||
|
private final SpruceOption rotationSpeedOption;
|
||||||
|
private final SpruceOption yAxisRotationSpeedOption;
|
||||||
|
private final SpruceOption mouseSpeedOption;
|
||||||
|
private final SpruceOption virtualMouseOption;
|
||||||
|
private final SpruceOption resetOption;
|
||||||
|
// Gameplay options
|
||||||
|
private final SpruceOption analogMovementOption;
|
||||||
|
private final SpruceOption doubleTapToSprintOption;
|
||||||
|
private final SpruceOption autoJumpOption;
|
||||||
|
private final SpruceOption fastBlockPlacingOption;
|
||||||
|
private final SpruceOption frontBlockPlacingOption;
|
||||||
|
private final SpruceOption verticalReacharoundOption;
|
||||||
|
private final SpruceOption flyDriftingOption;
|
||||||
|
private final SpruceOption flyVerticalDriftingOption;
|
||||||
|
// Appearance options
|
||||||
|
private final SpruceOption controllerTypeOption;
|
||||||
|
private final SpruceOption virtualMouseSkinOption;
|
||||||
|
private final SpruceOption hudEnableOption;
|
||||||
|
private final SpruceOption hudSideOption;
|
||||||
|
// Controller options
|
||||||
|
private final SpruceOption controllerOption =
|
||||||
|
new SpruceCyclingOption("midnightcontrols.menu.controller",
|
||||||
|
amount -> {
|
||||||
|
int id = MidnightControlsConfig.getController().id();
|
||||||
|
id += amount;
|
||||||
|
if (id > GLFW.GLFW_JOYSTICK_LAST)
|
||||||
|
id = GLFW.GLFW_JOYSTICK_1;
|
||||||
|
id = searchNextAvailableController(id, false);
|
||||||
|
MidnightControlsConfig.setController(Controller.byId(id));
|
||||||
|
},
|
||||||
|
option -> {
|
||||||
|
var controller = MidnightControlsConfig.getController();
|
||||||
|
var controllerName = controller.getName();
|
||||||
|
if (!controller.isConnected())
|
||||||
|
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.RED));
|
||||||
|
else if (!controller.isGamepad())
|
||||||
|
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.GOLD));
|
||||||
|
else
|
||||||
|
return option.getDisplayText(new LiteralText(controllerName));
|
||||||
|
}, null);
|
||||||
|
private final SpruceOption secondControllerOption = new SpruceCyclingOption("midnightcontrols.menu.controller2",
|
||||||
|
amount -> {
|
||||||
|
int id = MidnightControlsConfig.getSecondController().map(Controller::id).orElse(-1);
|
||||||
|
id += amount;
|
||||||
|
if (id > GLFW.GLFW_JOYSTICK_LAST)
|
||||||
|
id = -1;
|
||||||
|
id = searchNextAvailableController(id, true);
|
||||||
|
MidnightControlsConfig.setSecondController(id == -1 ? null : Controller.byId(id));
|
||||||
|
},
|
||||||
|
option -> MidnightControlsConfig.getSecondController().map(controller -> {
|
||||||
|
var controllerName = controller.getName();
|
||||||
|
if (!controller.isConnected())
|
||||||
|
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.RED));
|
||||||
|
else if (!controller.isGamepad())
|
||||||
|
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.GOLD));
|
||||||
|
else
|
||||||
|
return option.getDisplayText(new LiteralText(controllerName));
|
||||||
|
}).orElse(option.getDisplayText(SpruceTexts.OPTIONS_OFF.copy().formatted(Formatting.RED))),
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.controller2"));
|
||||||
|
private final SpruceOption unfocusedInputOption;
|
||||||
|
private final SpruceOption invertsRightXAxis;
|
||||||
|
private final SpruceOption invertsRightYAxis;
|
||||||
|
private final SpruceOption rightDeadZoneOption;
|
||||||
|
private final SpruceOption leftDeadZoneOption;
|
||||||
|
private final SpruceOption[] maxAnalogValueOptions = new SpruceOption[]{
|
||||||
|
maxAnalogValueOption("midnightcontrols.menu.max_left_x_value", GLFW.GLFW_GAMEPAD_AXIS_LEFT_X),
|
||||||
|
maxAnalogValueOption("midnightcontrols.menu.max_left_y_value", GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y),
|
||||||
|
maxAnalogValueOption("midnightcontrols.menu.max_right_x_value", GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X),
|
||||||
|
maxAnalogValueOption("midnightcontrols.menu.max_right_y_value", GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y)
|
||||||
|
};
|
||||||
|
|
||||||
|
private static SpruceOption maxAnalogValueOption(String key, int axis) {
|
||||||
|
return new SpruceDoubleOption(key, .25f, 1.f, 0.05f,
|
||||||
|
() -> MidnightControlsConfig.getAxisMaxValue(axis),
|
||||||
|
newValue -> MidnightControlsConfig.setAxisMaxValue(axis, newValue),
|
||||||
|
option -> option.getDisplayText(new LiteralText(String.format("%.2f", option.get()))),
|
||||||
|
new TranslatableText(key.replace("menu", "tooltip"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final MutableText controllerMappingsUrlText = new LiteralText("(")
|
||||||
|
.append(new LiteralText(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
|
||||||
|
.append("),");
|
||||||
|
|
||||||
|
private static int searchNextAvailableController(int newId, boolean allowNone) {
|
||||||
|
if ((allowNone && newId == -1) || newId == 0) return newId;
|
||||||
|
|
||||||
|
boolean connected = Controller.byId(newId).isConnected();
|
||||||
|
if (!connected) {
|
||||||
|
newId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newId > GLFW.GLFW_JOYSTICK_LAST)
|
||||||
|
newId = allowNone ? -1 : GLFW.GLFW_JOYSTICK_1;
|
||||||
|
|
||||||
|
return connected ? newId : searchNextAvailableController(newId, allowNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MidnightControlsSettingsScreen(Screen parent, boolean hideControls) {
|
||||||
|
super(new TranslatableText("midnightcontrols.title.settings"));
|
||||||
|
MidnightControlsConfig.isEditing = true;
|
||||||
|
this.parent = parent;
|
||||||
|
// General options
|
||||||
|
this.inputModeOption = new SpruceCyclingOption("midnightcontrols.menu.controls_mode",
|
||||||
|
amount -> {
|
||||||
|
var next = MidnightControlsConfig.controlsMode.next();
|
||||||
|
MidnightControlsConfig.controlsMode = next;
|
||||||
|
MidnightControlsConfig.save();
|
||||||
|
|
||||||
|
if (this.client.player != null) {
|
||||||
|
ClientPlayNetworking.getSender().sendPacket(MidnightControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next));
|
||||||
|
}
|
||||||
|
}, option -> option.getDisplayText(new TranslatableText(MidnightControlsConfig.controlsMode.getTranslationKey())),
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.controls_mode"));
|
||||||
|
this.autoSwitchModeOption = new SpruceToggleBooleanOption("midnightcontrols.menu.auto_switch_mode", () -> MidnightControlsConfig.autoSwitchMode,
|
||||||
|
value -> MidnightControlsConfig.autoSwitchMode = value, new TranslatableText("midnightcontrols.tooltip.auto_switch_mode"));
|
||||||
|
this.rotationSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.rotation_speed", 0.0, 100.0, .5f,
|
||||||
|
() -> MidnightControlsConfig.rotationSpeed,
|
||||||
|
value -> MidnightControlsConfig.rotationSpeed = value, option -> option.getDisplayText(new LiteralText(String.valueOf(option.get()))),
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.rotation_speed"));
|
||||||
|
this.yAxisRotationSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.y_axis_rotation_speed", 0.0, 100.0, .5f,
|
||||||
|
() -> MidnightControlsConfig.yAxisRotationSpeed,
|
||||||
|
value -> MidnightControlsConfig.yAxisRotationSpeed = value, option -> option.getDisplayText(new LiteralText(String.valueOf(option.get()))),
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.y_axis_rotation_speed"));
|
||||||
|
this.mouseSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.mouse_speed", 0.0, 150.0, .5f,
|
||||||
|
() -> MidnightControlsConfig.mouseSpeed,
|
||||||
|
value -> MidnightControlsConfig.mouseSpeed = value, option -> option.getDisplayText(new LiteralText(String.valueOf(option.get()))),
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.mouse_speed"));
|
||||||
|
this.resetOption = SpruceSimpleActionOption.reset(btn -> {
|
||||||
|
// TODO
|
||||||
|
MidnightControlsConfig.reset();
|
||||||
|
var client = MinecraftClient.getInstance();
|
||||||
|
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||||
|
});
|
||||||
|
// Gameplay options
|
||||||
|
this.analogMovementOption = new SpruceToggleBooleanOption("midnightcontrols.menu.analog_movement",
|
||||||
|
() -> MidnightControlsConfig.analogMovement, value -> MidnightControlsConfig.analogMovement = value,
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.analog_movement"));
|
||||||
|
this.doubleTapToSprintOption = new SpruceToggleBooleanOption("midnightcontrols.menu.double_tap_to_sprint",
|
||||||
|
() -> MidnightControlsConfig.doubleTapToSprint, value -> MidnightControlsConfig.doubleTapToSprint = value,
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.double_tap_to_sprint"));
|
||||||
|
this.autoJumpOption = new SpruceToggleBooleanOption("options.autoJump",
|
||||||
|
() -> this.client.options.autoJump,
|
||||||
|
newValue -> this.client.options.autoJump = newValue,
|
||||||
|
null);
|
||||||
|
this.fastBlockPlacingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fast_block_placing", () -> MidnightControlsConfig.fastBlockPlacing,
|
||||||
|
value -> MidnightControlsConfig.fastBlockPlacing = value, new TranslatableText("midnightcontrols.tooltip.fast_block_placing"));
|
||||||
|
this.frontBlockPlacingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.reacharound.horizontal", () -> MidnightControlsConfig.horizontalReacharound,
|
||||||
|
value -> MidnightControlsConfig.horizontalReacharound = value, new TranslatableText("midnightcontrols.tooltip.reacharound.horizontal"));
|
||||||
|
this.verticalReacharoundOption = new SpruceToggleBooleanOption("midnightcontrols.menu.reacharound.vertical", () -> MidnightControlsConfig.verticalReacharound,
|
||||||
|
value -> MidnightControlsConfig.verticalReacharound = value, new TranslatableText("midnightcontrols.tooltip.reacharound.vertical"));
|
||||||
|
this.flyDriftingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fly_drifting", () -> MidnightControlsConfig.flyDrifting,
|
||||||
|
value -> MidnightControlsConfig.flyDrifting = value, new TranslatableText("midnightcontrols.tooltip.fly_drifting"));
|
||||||
|
this.flyVerticalDriftingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fly_drifting_vertical", () -> MidnightControlsConfig.verticalFlyDrifting,
|
||||||
|
value -> MidnightControlsConfig.verticalFlyDrifting = value, new TranslatableText("midnightcontrols.tooltip.fly_drifting_vertical"));
|
||||||
|
// Appearance options
|
||||||
|
this.controllerTypeOption = new SpruceCyclingOption("midnightcontrols.menu.controller_type",
|
||||||
|
amount -> MidnightControlsConfig.controllerType = MidnightControlsConfig.controllerType.next(),
|
||||||
|
option -> option.getDisplayText(MidnightControlsConfig.controllerType.getTranslatedText()),
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.controller_type"));
|
||||||
|
this.virtualMouseSkinOption = new SpruceCyclingOption("midnightcontrols.menu.virtual_mouse.skin",
|
||||||
|
amount -> MidnightControlsConfig.virtualMouseSkin = MidnightControlsConfig.virtualMouseSkin.next(),
|
||||||
|
option -> option.getDisplayText(MidnightControlsConfig.virtualMouseSkin.getTranslatedText()),
|
||||||
|
null);
|
||||||
|
this.hudEnableOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hud_enable", () -> MidnightControlsConfig.hudEnable,
|
||||||
|
this.mod::setHudEnabled, new TranslatableText("midnightcontrols.tooltip.hud_enable"));
|
||||||
|
this.hudSideOption = new SpruceCyclingOption("midnightcontrols.menu.hud_side",
|
||||||
|
amount -> MidnightControlsConfig.hudSide = MidnightControlsConfig.hudSide.next(),
|
||||||
|
option -> option.getDisplayText(MidnightControlsConfig.hudSide.getTranslatedText()),
|
||||||
|
new TranslatableText("midnightcontrols.tooltip.hud_side"));
|
||||||
|
// Controller options
|
||||||
|
this.rightDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.right_dead_zone", 0.05, 1.0, .05f,
|
||||||
|
() -> MidnightControlsConfig.rightDeadZone,
|
||||||
|
value -> MidnightControlsConfig.rightDeadZone = value, option -> {
|
||||||
|
var value = String.valueOf(option.get());
|
||||||
|
return option.getDisplayText(new LiteralText(value.substring(0, Math.min(value.length(), 5))));
|
||||||
|
}, new TranslatableText("midnightcontrols.tooltip.right_dead_zone"));
|
||||||
|
this.leftDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.left_dead_zone", 0.05, 1.0, .05f,
|
||||||
|
() -> MidnightControlsConfig.leftDeadZone,
|
||||||
|
value -> MidnightControlsConfig.leftDeadZone = value, option -> {
|
||||||
|
var value = String.valueOf(option.get());
|
||||||
|
return option.getDisplayText(new LiteralText(value.substring(0, Math.min(value.length(), 5))));
|
||||||
|
}, new TranslatableText("midnightcontrols.tooltip.left_dead_zone"));
|
||||||
|
this.invertsRightXAxis = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_right_x_axis", () -> MidnightControlsConfig.invertRightXAxis,
|
||||||
|
value -> MidnightControlsConfig.invertRightXAxis = value, null);
|
||||||
|
this.invertsRightYAxis = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_right_y_axis", () -> MidnightControlsConfig.invertRightYAxis,
|
||||||
|
value -> MidnightControlsConfig.invertRightYAxis = value, null);
|
||||||
|
this.unfocusedInputOption = new SpruceToggleBooleanOption("midnightcontrols.menu.unfocused_input", () -> MidnightControlsConfig.unfocusedInput,
|
||||||
|
value -> MidnightControlsConfig.unfocusedInput = value, new TranslatableText("midnightcontrols.tooltip.unfocused_input"));
|
||||||
|
this.virtualMouseOption = new SpruceToggleBooleanOption("midnightcontrols.menu.virtual_mouse", () -> MidnightControlsConfig.virtualMouse,
|
||||||
|
value -> MidnightControlsConfig.virtualMouse = value, new TranslatableText("midnightcontrols.tooltip.virtual_mouse"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed() {
|
||||||
|
MidnightControlsConfig.isEditing = false;
|
||||||
|
MidnightControlsConfig.save();
|
||||||
|
super.removed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
MidnightControlsConfig.isEditing = false;
|
||||||
|
MidnightControlsConfig.save();
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getTextHeight() {
|
||||||
|
return (5 + this.textRenderer.fontHeight) * 3 + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
this.buildTabs();
|
||||||
|
|
||||||
|
this.addDrawableChild(this.resetOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 150));
|
||||||
|
this.addDrawableChild(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, 20, SpruceTexts.GUI_DONE,
|
||||||
|
btn -> this.client.setScreen(this.parent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildTabs() {
|
||||||
|
var tabs = new SpruceTabbedWidget(Position.of(0, 24), this.width, this.height - 32 - 24,
|
||||||
|
null,
|
||||||
|
Math.max(116, this.width / 8), 0);
|
||||||
|
tabs.getList().setBackground(new MidnightControlsBackground());
|
||||||
|
this.addDrawableChild(tabs);
|
||||||
|
|
||||||
|
tabs.addSeparatorEntry(new TranslatableText("midnightcontrols.menu.separator.general"));
|
||||||
|
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.general"), null,
|
||||||
|
this::buildGeneralTab);
|
||||||
|
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.gameplay"), null,
|
||||||
|
this::buildGameplayTab);
|
||||||
|
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.visual"), null,
|
||||||
|
this::buildVisualTab);
|
||||||
|
|
||||||
|
tabs.addSeparatorEntry(new TranslatableText("options.controls"));
|
||||||
|
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.controller_controls"), null,
|
||||||
|
this::buildControllerControlsTab);
|
||||||
|
|
||||||
|
tabs.addSeparatorEntry(new TranslatableText("midnightcontrols.menu.separator.controller"));
|
||||||
|
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.controller"), null,
|
||||||
|
this::buildControllerTab);
|
||||||
|
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.mappings.string"), null,
|
||||||
|
this::buildMappingsStringEditorTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpruceOptionListWidget buildGeneralTab(int width, int height) {
|
||||||
|
var list = new SpruceOptionListWidget(Position.origin(), width, height);
|
||||||
|
list.setBackground(new MidnightControlsBackground(130));
|
||||||
|
list.addSingleOptionEntry(this.inputModeOption);
|
||||||
|
list.addSingleOptionEntry(this.autoSwitchModeOption);
|
||||||
|
list.addSingleOptionEntry(this.rotationSpeedOption);
|
||||||
|
list.addSingleOptionEntry(this.yAxisRotationSpeedOption);
|
||||||
|
list.addSingleOptionEntry(this.mouseSpeedOption);
|
||||||
|
list.addSingleOptionEntry(this.virtualMouseOption);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpruceOptionListWidget buildGameplayTab(int width, int height) {
|
||||||
|
var list = new SpruceOptionListWidget(Position.origin(), width, height);
|
||||||
|
list.setBackground(new MidnightControlsBackground(130));
|
||||||
|
list.addSingleOptionEntry(this.analogMovementOption);
|
||||||
|
list.addSingleOptionEntry(this.doubleTapToSprintOption);
|
||||||
|
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.fastBlockPlacingOption);
|
||||||
|
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.frontBlockPlacingOption);
|
||||||
|
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.verticalReacharoundOption);
|
||||||
|
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.flyDriftingOption);
|
||||||
|
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.flyVerticalDriftingOption);
|
||||||
|
list.addSingleOptionEntry(this.autoJumpOption);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpruceOptionListWidget buildVisualTab(int width, int height) {
|
||||||
|
var list = new SpruceOptionListWidget(Position.origin(), width, height);
|
||||||
|
list.setBackground(new MidnightControlsBackground(130));
|
||||||
|
list.addSingleOptionEntry(this.controllerTypeOption);
|
||||||
|
list.addSingleOptionEntry(this.virtualMouseSkinOption);
|
||||||
|
list.addSingleOptionEntry(new SpruceSeparatorOption("midnightcontrols.menu.title.hud", true, null));
|
||||||
|
list.addSingleOptionEntry(this.hudEnableOption);
|
||||||
|
list.addSingleOptionEntry(this.hudSideOption);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ControllerControlsWidget buildControllerControlsTab(int width, int height) {
|
||||||
|
return new ControllerControlsWidget(Position.origin(), width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractSpruceWidget buildControllerTab(int width, int height) {
|
||||||
|
var root = new SpruceContainerWidget(Position.origin(), width, height);
|
||||||
|
|
||||||
|
var aboutMappings1 = new SpruceLabelWidget(Position.of(0, 2),
|
||||||
|
new TranslatableText("midnightcontrols.controller.mappings.1", SDL2_GAMEPAD_TOOL),
|
||||||
|
width, true);
|
||||||
|
|
||||||
|
var gamepadToolUrlLabel = new SpruceLabelWidget(Position.of(0, aboutMappings1.getHeight() + 4),
|
||||||
|
this.controllerMappingsUrlText, width,
|
||||||
|
label -> Util.getOperatingSystem().open(GAMEPAD_TOOL_URL), true);
|
||||||
|
gamepadToolUrlLabel.setTooltip(new TranslatableText("chat.link.open"));
|
||||||
|
|
||||||
|
var aboutMappings3 = new SpruceLabelWidget(Position.of(0,
|
||||||
|
aboutMappings1.getHeight() + gamepadToolUrlLabel.getHeight() + 6),
|
||||||
|
new TranslatableText("midnightcontrols.controller.mappings.3", Formatting.GREEN.toString(), Formatting.RESET.toString()),
|
||||||
|
width, true);
|
||||||
|
|
||||||
|
int listHeight = height - 8 - aboutMappings1.getHeight() - aboutMappings3.getHeight() - gamepadToolUrlLabel.getHeight();
|
||||||
|
var labels = new SpruceContainerWidget(Position.of(0,
|
||||||
|
listHeight),
|
||||||
|
width, height - listHeight);
|
||||||
|
labels.addChild(aboutMappings1);
|
||||||
|
labels.addChild(gamepadToolUrlLabel);
|
||||||
|
labels.addChild(aboutMappings3);
|
||||||
|
|
||||||
|
var list = new SpruceOptionListWidget(Position.origin(), width, listHeight);
|
||||||
|
list.setBackground(new MidnightControlsBackground(130));
|
||||||
|
list.addSingleOptionEntry(this.controllerOption);
|
||||||
|
list.addSingleOptionEntry(this.secondControllerOption);
|
||||||
|
list.addSingleOptionEntry(this.unfocusedInputOption);
|
||||||
|
list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
|
||||||
|
list.addSingleOptionEntry(this.rightDeadZoneOption);
|
||||||
|
list.addSingleOptionEntry(this.leftDeadZoneOption);
|
||||||
|
for (var option : this.maxAnalogValueOptions) {
|
||||||
|
list.addSingleOptionEntry(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.addChild(list);
|
||||||
|
root.addChild(labels);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpruceContainerWidget buildMappingsStringEditorTab(int width, int height) {
|
||||||
|
return new MappingsStringInputWidget(Position.origin(), width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderTitle(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||||
|
drawCenteredText(matrices, this.textRenderer, I18n.translate("midnightcontrols.menu.title"), this.width / 2, 8, 16777215);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MidnightControlsBackground implements Background {
|
||||||
|
private int transparency = 160;
|
||||||
|
public MidnightControlsBackground() {}
|
||||||
|
public MidnightControlsBackground(int transparency) {
|
||||||
|
this.transparency = transparency;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrixStack, SpruceWidget widget, int vOffset, int mouseX, int mouseY, float delta) {
|
||||||
|
fill(matrixStack, widget.getX(), widget.getY(), widget.getX() + widget.getWidth(), widget.getY() + widget.getHeight(), MidnightColorUtil.hex2Rgb("#000000"));
|
||||||
|
}
|
||||||
|
private void fill(MatrixStack matrixStack, int x2, int y2, int x1, int y1, Color color) {
|
||||||
|
matrixStack.push();
|
||||||
|
|
||||||
|
Matrix4f matrix = matrixStack.peek().getPositionMatrix();
|
||||||
|
float r = (float)(color.getRed()) / 255.0F;
|
||||||
|
float g = (float)(color.getGreen()) / 255.0F;
|
||||||
|
float b = (float)(color.getBlue()) / 255.0F;
|
||||||
|
float t = (float)(transparency) / 255.0F;
|
||||||
|
BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
|
||||||
|
RenderSystem.enableBlend();
|
||||||
|
RenderSystem.disableTexture();
|
||||||
|
RenderSystem.defaultBlendFunc();
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||||
|
bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
|
||||||
|
bufferBuilder.vertex(matrix, (float)x1, (float)y2, 0.0F).color(r, g, b, t).next();
|
||||||
|
bufferBuilder.vertex(matrix, (float)x2, (float)y2, 0.0F).color(r, g, b, t).next();
|
||||||
|
bufferBuilder.vertex(matrix, (float)x2, (float)y1, 0.0F).color(r, g, b, t).next();
|
||||||
|
bufferBuilder.vertex(matrix, (float)x1, (float)y1, 0.0F).color(r, g, b, t).next();
|
||||||
|
bufferBuilder.end();
|
||||||
|
BufferRenderer.draw(bufferBuilder);
|
||||||
|
RenderSystem.enableTexture();
|
||||||
|
RenderSystem.disableBlend();
|
||||||
|
matrixStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import me.lambdaurora.spruceui.option.SpruceSimpleActionOption;
|
import dev.lambdaurora.spruceui.option.SpruceSimpleActionOption;
|
||||||
import me.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.toast.SystemToast;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -24,18 +24,18 @@ import java.util.function.Consumer;
|
|||||||
* Represents the option to reload the controller mappings.
|
* Represents the option to reload the controller mappings.
|
||||||
*/
|
*/
|
||||||
public class ReloadControllerMappingsOption {
|
public class ReloadControllerMappingsOption {
|
||||||
private static final String KEY = "lambdacontrols.menu.reload_controller_mappings";
|
private static final String KEY = "midnightcontrols.menu.reload_controller_mappings";
|
||||||
|
|
||||||
public static SpruceSimpleActionOption newOption(@Nullable Consumer<SpruceButtonWidget> before) {
|
public static SpruceSimpleActionOption newOption(@Nullable Consumer<SpruceButtonWidget> before) {
|
||||||
return SpruceSimpleActionOption.of(KEY, btn -> {
|
return SpruceSimpleActionOption.of(KEY, btn -> {
|
||||||
MinecraftClient client = MinecraftClient.getInstance();
|
var client = MinecraftClient.getInstance();
|
||||||
if (before != null)
|
if (before != null)
|
||||||
before.accept(btn);
|
before.accept(btn);
|
||||||
Controller.updateMappings();
|
Controller.updateMappings();
|
||||||
if (client.currentScreen instanceof LambdaControlsSettingsScreen)
|
if (client.currentScreen instanceof MidnightControlsSettingsScreen)
|
||||||
client.currentScreen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
client.currentScreen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||||
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
|
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
|
||||||
new TranslatableText("lambdacontrols.controller.mappings.updated"), LiteralText.EMPTY));
|
new TranslatableText("midnightcontrols.controller.mappings.updated"), Text.of("")));
|
||||||
}, new TranslatableText("lambdacontrols.tooltip.reload_controller_mappings"));
|
}, new TranslatableText("midnightcontrols.tooltip.reload_controller_mappings"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import dev.lambdaurora.lambdacontrols.client.ring.RingPage;
|
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the controls ring screen.
|
* Represents the controls ring screen.
|
||||||
@@ -23,15 +24,15 @@ import net.minecraft.text.TranslatableText;
|
|||||||
* @since 1.4.3
|
* @since 1.4.3
|
||||||
*/
|
*/
|
||||||
public class RingScreen extends Screen {
|
public class RingScreen extends Screen {
|
||||||
protected final LambdaControlsClient mod;
|
protected final MidnightControlsClient mod;
|
||||||
|
|
||||||
public RingScreen() {
|
public RingScreen() {
|
||||||
super(new TranslatableText("lambdacontrols.menu.title.ring"));
|
super(new LiteralText("midnightcontrols.menu.title.ring"));
|
||||||
this.mod = LambdaControlsClient.get();
|
this.mod = MidnightControlsClient.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPauseScreen() {
|
public boolean shouldPause() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,10 +47,10 @@ public class RingScreen extends Screen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||||
/*if (LambdaControlsClient.BINDING_RING.matchesMouse(button)) {
|
if (mod.ring.getCurrentPage().onClick(client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight(), (int) mouseX, (int) mouseY)) {
|
||||||
this.onClose();
|
this.close();
|
||||||
return true;
|
return true;
|
||||||
}*/
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,296 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
|
import dev.lambdaurora.spruceui.Position;
|
||||||
|
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.HudSide;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.widget.SilentTexturedButtonWidget;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||||
|
import net.minecraft.client.gui.screen.ChatScreen;
|
||||||
|
import net.minecraft.client.gui.screen.GameMenuScreen;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
||||||
|
import net.minecraft.client.gui.widget.TexturedButtonWidget;
|
||||||
|
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Arm;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Direction;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X;
|
||||||
|
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the touchscreen overlay
|
||||||
|
*/
|
||||||
|
public class TouchscreenOverlay extends Screen {
|
||||||
|
public static final Identifier WIDGETS_LOCATION = new Identifier("midnightcontrols", "textures/gui/widgets.png");
|
||||||
|
private MidnightControlsClient mod;
|
||||||
|
private SilentTexturedButtonWidget jumpButton;
|
||||||
|
private SilentTexturedButtonWidget flyButton;
|
||||||
|
private SilentTexturedButtonWidget flyUpButton;
|
||||||
|
private SilentTexturedButtonWidget flyDownButton;
|
||||||
|
private int flyButtonEnableTicks = 0;
|
||||||
|
private int forwardButtonTick = 0;
|
||||||
|
private SilentTexturedButtonWidget forwardLeftButton;
|
||||||
|
private SilentTexturedButtonWidget forwardRightButton;
|
||||||
|
private SilentTexturedButtonWidget startSneakButton;
|
||||||
|
private SilentTexturedButtonWidget endSneakButton;
|
||||||
|
|
||||||
|
public TouchscreenOverlay(@NotNull MidnightControlsClient mod) {
|
||||||
|
super(new LiteralText("Touchscreen overlay"));
|
||||||
|
this.mod = mod;
|
||||||
|
this.passEvents = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPause()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||||
|
super.keyPressed(keyCode,scanCode,modifiers);
|
||||||
|
//return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pauseGame(boolean bl) {
|
||||||
|
if (this.client == null)
|
||||||
|
return;
|
||||||
|
boolean bl2 = this.client.isIntegratedServerRunning() && !this.client.getServer().isRemote();
|
||||||
|
if (bl2) {
|
||||||
|
this.client.setScreen(new GameMenuScreen(!bl));
|
||||||
|
this.client.getSoundManager().pauseAll();
|
||||||
|
} else {
|
||||||
|
this.client.setScreen(new GameMenuScreen(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the forward button ticks cooldown.
|
||||||
|
*
|
||||||
|
* @param state The button state.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void updateForwardButtonsState(boolean state) {
|
||||||
|
if (state)
|
||||||
|
this.forwardButtonTick = -1;
|
||||||
|
else
|
||||||
|
this.forwardButtonTick = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the jump buttons.
|
||||||
|
*/
|
||||||
|
private void updateJumpButtons() {
|
||||||
|
if (this.client == null)
|
||||||
|
return;
|
||||||
|
if (!this.client.interactionManager.isFlyingLocked()) {
|
||||||
|
boolean oldStateFly = this.flyButton.isVisible();
|
||||||
|
this.jumpButton.setVisible(false);
|
||||||
|
this.flyButton.setVisible(true);
|
||||||
|
this.flyUpButton.setVisible(true);
|
||||||
|
this.flyDownButton.setVisible(true);
|
||||||
|
if (oldStateFly != this.flyButton.isVisible()) {
|
||||||
|
this.flyButtonEnableTicks = 5;
|
||||||
|
this.setJump(false);
|
||||||
|
} else if (this.flyButtonEnableTicks > 0)
|
||||||
|
this.flyButtonEnableTicks--;
|
||||||
|
} else {
|
||||||
|
this.jumpButton.setVisible(true);
|
||||||
|
this.flyButton.setVisible(false);
|
||||||
|
this.flyUpButton.setVisible(false);
|
||||||
|
this.flyDownButton.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the jump button.
|
||||||
|
*
|
||||||
|
* @param btn The pressed button.
|
||||||
|
*/
|
||||||
|
private void handleJump(SpruceButtonWidget btn) {
|
||||||
|
((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(btn.isActive());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handles the jump button.
|
||||||
|
*
|
||||||
|
* @param state The state.
|
||||||
|
*/
|
||||||
|
private void setJump(boolean state) {
|
||||||
|
((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
if (this.forwardButtonTick > 0) {
|
||||||
|
this.forwardButtonTick--;
|
||||||
|
} else if (this.forwardButtonTick == 0) {
|
||||||
|
if (this.forwardLeftButton.isVisible())
|
||||||
|
this.forwardLeftButton.setVisible(false);
|
||||||
|
if (this.forwardRightButton.isVisible())
|
||||||
|
this.forwardRightButton.setVisible(false);
|
||||||
|
}
|
||||||
|
this.updateJumpButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
int scaledWidth = this.client.getWindow().getScaledWidth();
|
||||||
|
int scaledHeight = this.client.getWindow().getScaledHeight();
|
||||||
|
this.addDrawableChild(new TexturedButtonWidget(scaledWidth / 2 - 20, 0, 20, 20, 0, 106, 20, new Identifier("textures/gui/widgets.png"), 256, 256,
|
||||||
|
btn -> this.client.setScreen(new ChatScreen("")), Text.of("")));
|
||||||
|
this.addDrawableChild(new TexturedButtonWidget(scaledWidth / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256,
|
||||||
|
btn -> this.pauseGame(false)));
|
||||||
|
// Inventory buttons.
|
||||||
|
int inventoryButtonX = scaledWidth / 2;
|
||||||
|
int inventoryButtonY = scaledHeight - 16 - 5;
|
||||||
|
if (this.client.options.mainArm == Arm.LEFT) {
|
||||||
|
inventoryButtonX = inventoryButtonX - 91 - 24;
|
||||||
|
} else {
|
||||||
|
inventoryButtonX = inventoryButtonX + 91 + 4;
|
||||||
|
}
|
||||||
|
this.addDrawableChild(new TexturedButtonWidget(inventoryButtonX, inventoryButtonY, 20, 20, 20, 0, 20, WIDGETS_LOCATION, 256, 256,
|
||||||
|
btn -> {
|
||||||
|
if (this.client.interactionManager.hasRidingInventory()) {
|
||||||
|
this.client.player.openRidingInventory();
|
||||||
|
} else {
|
||||||
|
this.client.getTutorialManager().onInventoryOpened();
|
||||||
|
this.client.setScreen(new InventoryScreen(this.client.player));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
int jumpButtonX, swapHandsX, sneakButtonX;
|
||||||
|
int sneakButtonY = scaledHeight - 10 - 40 - 5;
|
||||||
|
if (MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||||
|
jumpButtonX = scaledWidth - 20 - 20;
|
||||||
|
swapHandsX = jumpButtonX - 5 - 40;
|
||||||
|
sneakButtonX = 10 + 20 + 5;
|
||||||
|
} else {
|
||||||
|
jumpButtonX = 20;
|
||||||
|
swapHandsX = jumpButtonX + 5 + 40;
|
||||||
|
sneakButtonX = scaledWidth - 10 - 40 - 5;
|
||||||
|
}
|
||||||
|
// Swap items hand.
|
||||||
|
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY), 20, 20, Text.of(""),
|
||||||
|
button -> {
|
||||||
|
if (button.isActive()) {
|
||||||
|
if (!this.client.player.isSpectator()) {
|
||||||
|
this.client.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},0, 160, 20, WIDGETS_LOCATION));
|
||||||
|
// Drop
|
||||||
|
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY + 5 + 20), 20, 20, Text.of(""), btn ->
|
||||||
|
((KeyBindingAccessor) this.client.options.dropKey).midnightcontrols$handlePressState(btn.isActive()), 0, 160, 20, WIDGETS_LOCATION));
|
||||||
|
// Jump keys
|
||||||
|
this.addDrawableChild(this.jumpButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.of(""), this::handleJump, 0, 40, 20, WIDGETS_LOCATION));
|
||||||
|
this.addDrawableChild(this.flyButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.of(""),btn -> {
|
||||||
|
if (this.flyButtonEnableTicks == 0) this.client.player.getAbilities().flying = false;
|
||||||
|
}, 20, 40, 20, WIDGETS_LOCATION)
|
||||||
|
);
|
||||||
|
this.addDrawableChild(this.flyUpButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY - 5 - 20), 20, 20,Text.of(""),
|
||||||
|
this::handleJump, 40, 40, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.addDrawableChild(this.flyDownButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY + 20 + 5), 20, 20, Text.of(""),
|
||||||
|
btn -> ((KeyBindingAccessor) this.client.options.sneakKey).midnightcontrols$handlePressState(btn.isActive()), 60, 40, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.updateJumpButtons();
|
||||||
|
// Movements keys
|
||||||
|
this.addDrawableChild((this.startSneakButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY), 20, 20, Text.of(""), btn -> {
|
||||||
|
if (btn.isActive()) {
|
||||||
|
((KeyBindingAccessor) this.client.options.sneakKey).midnightcontrols$handlePressState(true);
|
||||||
|
this.startSneakButton.setVisible(false);
|
||||||
|
this.endSneakButton.setVisible(true);
|
||||||
|
}
|
||||||
|
}, 0, 120, 20, WIDGETS_LOCATION))
|
||||||
|
);
|
||||||
|
this.addDrawableChild((this.endSneakButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY), 20, 20, Text.of(""), btn -> {
|
||||||
|
if (btn.isActive()) {
|
||||||
|
((KeyBindingAccessor) this.client.options.sneakKey).midnightcontrols$handlePressState(false);
|
||||||
|
this.endSneakButton.setVisible(false);
|
||||||
|
this.startSneakButton.setVisible(true);
|
||||||
|
}
|
||||||
|
}, 20, 120, 20, WIDGETS_LOCATION)));
|
||||||
|
this.endSneakButton.setVisible(false);
|
||||||
|
this.addDrawableChild(this.forwardLeftButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20), 20, 20, Text.of(""), btn -> {
|
||||||
|
((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive());
|
||||||
|
((KeyBindingAccessor) this.client.options.leftKey).midnightcontrols$handlePressState(btn.isActive());
|
||||||
|
this.updateForwardButtonsState(btn.isActive());
|
||||||
|
}, 80, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.forwardLeftButton.setVisible(false);
|
||||||
|
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY - 5 - 20), 20, 20, Text.of(""), btn -> {
|
||||||
|
((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive());
|
||||||
|
this.updateForwardButtonsState(btn.isActive());
|
||||||
|
this.forwardLeftButton.setVisible(true);
|
||||||
|
this.forwardRightButton.setVisible(true);
|
||||||
|
}, 0, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.addDrawableChild(this.forwardRightButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX + 20 + 5, sneakButtonY - 5 - 20), 20, 20, Text.of(""), btn -> {
|
||||||
|
((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive());
|
||||||
|
((KeyBindingAccessor) this.client.options.rightKey).midnightcontrols$handlePressState(btn.isActive());
|
||||||
|
this.updateForwardButtonsState(btn.isActive());
|
||||||
|
}, 100, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.forwardRightButton.setVisible(true);
|
||||||
|
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX + 20 + 5, sneakButtonY), 20, 20, Text.of(""),
|
||||||
|
btn -> ((KeyBindingAccessor) this.client.options.rightKey).midnightcontrols$handlePressState(btn.isActive()), 20, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY + 20 + 5), 20, 20, Text.of(""),
|
||||||
|
btn -> ((KeyBindingAccessor) this.client.options.backKey).midnightcontrols$handlePressState(btn.isActive()), 40, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX - 20 - 5, sneakButtonY), 20, 20, Text.of(""),
|
||||||
|
btn -> ((KeyBindingAccessor) this.client.options.leftKey).midnightcontrols$handlePressState(btn.isActive()), 60, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||||
|
if (mouseY >= (double) (this.height - 22) && this.client != null && this.client.player != null) {
|
||||||
|
int centerX = this.width / 2;
|
||||||
|
if (mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) {
|
||||||
|
for (int slot = 0; slot < 9; ++slot) {
|
||||||
|
int slotX = centerX - 90 + slot * 20 + 2;
|
||||||
|
if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) {
|
||||||
|
this.client.player.getInventory().selectedSlot = slot;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.mouseClicked(mouseX, mouseY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||||
|
if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) {
|
||||||
|
if (deltaY > 0.01)
|
||||||
|
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 2);
|
||||||
|
else if (deltaY < 0.01)
|
||||||
|
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 1);
|
||||||
|
|
||||||
|
if (deltaX > 0.01)
|
||||||
|
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 2);
|
||||||
|
else if (deltaX < 0.01)
|
||||||
|
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 1);
|
||||||
|
}
|
||||||
|
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui.widget;
|
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsRenderer;
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||||
import me.lambdaurora.spruceui.Position;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import me.lambdaurora.spruceui.SpruceTexts;
|
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||||
import me.lambdaurora.spruceui.widget.AbstractSpruceIconButtonWidget;
|
import dev.lambdaurora.spruceui.widget.AbstractSpruceIconButtonWidget;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +41,7 @@ public class ControllerButtonWidget extends AbstractSpruceIconButtonWidget {
|
|||||||
@Override
|
@Override
|
||||||
public Text getMessage() {
|
public Text getMessage() {
|
||||||
if (this.binding.getButton().length > 1)
|
if (this.binding.getButton().length > 1)
|
||||||
return LiteralText.EMPTY;
|
return Text.of("");
|
||||||
return super.getMessage();
|
return super.getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,8 +51,8 @@ public class ControllerButtonWidget extends AbstractSpruceIconButtonWidget {
|
|||||||
if (this.binding.getButton().length > 1) {
|
if (this.binding.getButton().length > 1) {
|
||||||
x += (this.width / 2 - this.iconWidth / 2) - 4;
|
x += (this.width / 2 - this.iconWidth / 2) - 4;
|
||||||
}
|
}
|
||||||
Pair<Integer, Integer> size = LambdaControlsRenderer.drawButton(matrices, x, this.getY(), this.binding, MinecraftClient.getInstance());
|
var size = MidnightControlsRenderer.drawButton(matrices, x, this.getY(), this.binding, MinecraftClient.getInstance());
|
||||||
this.iconWidth = size.key;
|
this.iconWidth = size.length();
|
||||||
return size.value;
|
return size.height();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui.widget;
|
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import me.lambdaurora.spruceui.Position;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import me.lambdaurora.spruceui.SpruceTexts;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import me.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||||
import me.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||||
import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
|
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
||||||
|
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
||||||
|
|
||||||
@@ -29,7 +32,7 @@ import java.util.stream.Collectors;
|
|||||||
* Represents the controls screen.
|
* Represents the controls screen.
|
||||||
*/
|
*/
|
||||||
public class ControllerControlsWidget extends SpruceContainerWidget {
|
public class ControllerControlsWidget extends SpruceContainerWidget {
|
||||||
final LambdaControlsClient mod;
|
final MidnightControlsClient mod;
|
||||||
private ControlsListWidget bindingsListWidget;
|
private ControlsListWidget bindingsListWidget;
|
||||||
private SpruceButtonWidget resetButton;
|
private SpruceButtonWidget resetButton;
|
||||||
public ButtonBinding focusedBinding;
|
public ButtonBinding focusedBinding;
|
||||||
@@ -38,27 +41,34 @@ public class ControllerControlsWidget extends SpruceContainerWidget {
|
|||||||
|
|
||||||
public ControllerControlsWidget(Position position, int width, int height) {
|
public ControllerControlsWidget(Position position, int width, int height) {
|
||||||
super(position, width, height);
|
super(position, width, height);
|
||||||
this.mod = LambdaControlsClient.get();
|
this.mod = MidnightControlsClient.get();
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void init() {
|
protected void init() {
|
||||||
this.addChild(new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, 18), 310, 20,
|
this.addChild(new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, 18), 310, 20,
|
||||||
new TranslatableText("lambdacontrols.menu.keyboard_controls"),
|
new TranslatableText("midnightcontrols.menu.keyboard_controls"),
|
||||||
btn -> this.client.openScreen(new ControlsOptionsScreen(null, this.client.options))));
|
btn -> this.client.setScreen(new ControlsOptionsScreen(null, this.client.options))));
|
||||||
this.bindingsListWidget = new ControlsListWidget(Position.of(this, 0, 43), this.width, this.height - 43 - 35, this);
|
this.bindingsListWidget = new ControlsListWidget(Position.of(this, 0, 43), this.width, this.height - 43 - 35, this);
|
||||||
|
this.bindingsListWidget.setBackground(new MidnightControlsSettingsScreen.MidnightControlsBackground(130));
|
||||||
this.addChild(this.bindingsListWidget);
|
this.addChild(this.bindingsListWidget);
|
||||||
this.addChild(this.resetButton = new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, this.height - 29), 150, 20,
|
this.addChild(this.resetButton = new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, this.height - 29), 150, 20,
|
||||||
SpruceTexts.CONTROLS_RESET_ALL,
|
SpruceTexts.CONTROLS_RESET_ALL,
|
||||||
btn -> InputManager.streamBindings().collect(Collectors.toSet()).forEach(binding -> this.mod.config.setButtonBinding(binding, binding.getDefaultButton()))));
|
btn -> InputManager.streamBindings().collect(Collectors.toSet()).forEach(binding -> MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
public void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||||
drawCenteredText(matrices, this.client.textRenderer, new TranslatableText("lambdacontrols.menu.title.controller_controls"),
|
drawCenteredText(matrices, this.client.textRenderer, new TranslatableText("midnightcontrols.menu.title.controller_controls"),
|
||||||
this.getX() + this.width / 2, this.getY() + 4, 16777215);
|
this.getX() + this.width / 2, this.getY() + 4, 16777215);
|
||||||
this.resetButton.setActive(InputManager.streamBindings().anyMatch(Predicates.not(ButtonBinding::isDefault)));
|
this.resetButton.setActive(InputManager.streamBindings().anyMatch(Predicates.not(ButtonBinding::isDefault)));
|
||||||
super.renderWidget(matrices, mouseX, mouseY, delta);
|
super.renderWidget(matrices, mouseX, mouseY, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void finishBindingEdit(int... buttons) {
|
||||||
|
if (this.focusedBinding == null) return;
|
||||||
|
MidnightControlsConfig.setButtonBinding(this.focusedBinding, buttons);
|
||||||
|
this.focusedBinding = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,34 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.gui.widget;
|
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.ButtonCategory;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||||
import me.lambdaurora.spruceui.Position;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import me.lambdaurora.spruceui.SpruceTexts;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import me.lambdaurora.spruceui.navigation.NavigationDirection;
|
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||||
import me.lambdaurora.spruceui.navigation.NavigationUtils;
|
import dev.lambdaurora.spruceui.navigation.NavigationDirection;
|
||||||
import me.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
import dev.lambdaurora.spruceui.navigation.NavigationUtils;
|
||||||
import me.lambdaurora.spruceui.widget.SpruceSeparatorWidget;
|
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||||
import me.lambdaurora.spruceui.widget.SpruceWidget;
|
import dev.lambdaurora.spruceui.widget.SpruceSeparatorWidget;
|
||||||
import me.lambdaurora.spruceui.widget.container.SpruceEntryListWidget;
|
import dev.lambdaurora.spruceui.widget.SpruceWidget;
|
||||||
import me.lambdaurora.spruceui.widget.container.SpruceParentWidget;
|
import dev.lambdaurora.spruceui.widget.container.SpruceEntryListWidget;
|
||||||
|
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import net.minecraft.text.MutableText;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
@@ -36,7 +35,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a control list widget.
|
* Represents a control list widget.
|
||||||
@@ -89,19 +90,20 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
this.bindingName = I18n.translate(this.binding.getTranslationKey());
|
this.bindingName = I18n.translate(this.binding.getTranslationKey());
|
||||||
this.editButton = new ControllerButtonWidget(Position.of(this, parent.getWidth() / 2 - 8, 0), 110, this.binding, btn -> {
|
this.editButton = new ControllerButtonWidget(Position.of(this, parent.getWidth() / 2 - 8, 0), 110, this.binding, btn -> {
|
||||||
gui.focusedBinding = binding;
|
gui.focusedBinding = binding;
|
||||||
LambdaControlsClient.get().input.beginControlsInput(gui);
|
MidnightControlsClient.get().input.beginControlsInput(gui);
|
||||||
}) {
|
}) {
|
||||||
protected Optional<Text> getNarrationMessage() {
|
protected Text getNarrationMessage() {
|
||||||
return Optional.of(binding.isNotBound() ? new TranslatableText("narrator.controls.unbound", bindingName) : new TranslatableText("narrator.controls.bound", bindingName, super.getNarrationMessage()));
|
return binding.isNotBound() ? new TranslatableText("narrator.controls.unbound", bindingName)
|
||||||
|
: new TranslatableText("narrator.controls.bound", bindingName, super.getNarrationMessage());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.children.add(editButton);
|
this.children.add(editButton);
|
||||||
this.resetButton = new SpruceButtonWidget(Position.of(this,
|
this.resetButton = new SpruceButtonWidget(Position.of(this,
|
||||||
this.editButton.getPosition().getRelativeX() + this.editButton.getWidth() + 2, 0),
|
this.editButton.getPosition().getRelativeX() + this.editButton.getWidth() + 2, 0),
|
||||||
44, 20, new TranslatableText("controls.reset"),
|
44, 20, new TranslatableText("controls.reset"),
|
||||||
btn -> LambdaControlsClient.get().config.setButtonBinding(binding, binding.getDefaultButton())) {
|
btn -> MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton())) {
|
||||||
protected Optional<Text> getNarrationMessage() {
|
protected Text getNarrationMessage() {
|
||||||
return Optional.of(new TranslatableText("narrator.controls.reset", bindingName));
|
return new TranslatableText("narrator.controls.reset", bindingName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.children.add(this.resetButton);
|
this.children.add(this.resetButton);
|
||||||
@@ -109,12 +111,12 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
this.editButton.getPosition().getRelativeX() + this.editButton.getWidth() + 2, 0),
|
this.editButton.getPosition().getRelativeX() + this.editButton.getWidth() + 2, 0),
|
||||||
this.resetButton.getWidth(), this.resetButton.getHeight(), SpruceTexts.GUI_UNBIND,
|
this.resetButton.getWidth(), this.resetButton.getHeight(), SpruceTexts.GUI_UNBIND,
|
||||||
btn -> {
|
btn -> {
|
||||||
LambdaControlsClient.get().config.setButtonBinding(binding, UNBOUND);
|
MidnightControlsConfig.setButtonBinding(binding, UNBOUND);
|
||||||
gui.focusedBinding = null;
|
gui.focusedBinding = null;
|
||||||
LambdaControlsClient.get().input.beginControlsInput(null);
|
MidnightControlsClient.get().input.beginControlsInput(null);
|
||||||
}) {
|
}) {
|
||||||
protected Optional<Text> getNarrationMessage() {
|
protected Text getNarrationMessage() {
|
||||||
return Optional.of(new TranslatableText("lambdacontrols.narrator.unbound", bindingName));
|
return new TranslatableText("midnightcontrols.narrator.unbound", bindingName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.children.add(this.unbindButton);
|
this.children.add(this.unbindButton);
|
||||||
@@ -151,7 +153,7 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean onMouseClick(double mouseX, double mouseY, int button) {
|
protected boolean onMouseClick(double mouseX, double mouseY, int button) {
|
||||||
Iterator<SpruceWidget> it = this.children().iterator();
|
var it = this.children().iterator();
|
||||||
|
|
||||||
SpruceWidget element;
|
SpruceWidget element;
|
||||||
do {
|
do {
|
||||||
@@ -229,12 +231,11 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
protected void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
protected void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||||
boolean focused = gui.focusedBinding == this.binding;
|
boolean focused = gui.focusedBinding == this.binding;
|
||||||
|
|
||||||
TextRenderer textRenderer = ControlsListWidget.this.client.textRenderer;
|
var textRenderer = ControlsListWidget.this.client.textRenderer;
|
||||||
String bindingName = this.bindingName;
|
|
||||||
int height = this.getHeight();
|
int height = this.getHeight();
|
||||||
//float textX = (float) (this.getX() + 70 - ControlsListWidget.this.maxTextLength);
|
//float textX = (float) (this.getX() + 70 - ControlsListWidget.this.maxTextLength);
|
||||||
int textY = this.getY() + height / 2;
|
int textY = this.getY() + height / 2;
|
||||||
textRenderer.draw(matrices, bindingName, this.getX(), (float) (textY - 9 / 2), 16777215);
|
textRenderer.draw(matrices, this.bindingName, this.getX(), (float) (textY - 9 / 2), 16777215);
|
||||||
|
|
||||||
this.resetButton.setVisible(!focused);
|
this.resetButton.setVisible(!focused);
|
||||||
this.unbindButton.setVisible(focused);
|
this.unbindButton.setVisible(focused);
|
||||||
@@ -242,14 +243,14 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
|
|
||||||
this.editButton.update();
|
this.editButton.update();
|
||||||
if (focused) {
|
if (focused) {
|
||||||
MutableText text = new LiteralText("> ").formatted(Formatting.WHITE);
|
var text = new LiteralText("> ").formatted(Formatting.WHITE);
|
||||||
text.append(this.editButton.getMessage().copy().formatted(Formatting.YELLOW));
|
text.append(this.editButton.getMessage().copy().formatted(Formatting.YELLOW));
|
||||||
this.editButton.setMessage(text.append(new LiteralText(" <").formatted(Formatting.WHITE)));
|
this.editButton.setMessage(text.append(new LiteralText(" <").formatted(Formatting.WHITE)));
|
||||||
} else if (!this.binding.isNotBound() && InputManager.hasDuplicatedBindings(this.binding)) {
|
} else if (!this.binding.isNotBound() && InputManager.hasDuplicatedBindings(this.binding)) {
|
||||||
MutableText text = this.editButton.getMessage().copy();
|
var text = this.editButton.getMessage().copy();
|
||||||
this.editButton.setMessage(text.formatted(Formatting.RED));
|
this.editButton.setMessage(text.formatted(Formatting.RED));
|
||||||
} else if (this.binding.isNotBound()) {
|
} else if (this.binding.isNotBound()) {
|
||||||
MutableText text = this.editButton.getMessage().copy();
|
var text = this.editButton.getMessage().copy();
|
||||||
this.editButton.setMessage(text.formatted(Formatting.GOLD));
|
this.editButton.setMessage(text.formatted(Formatting.GOLD));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
||||||
|
|
||||||
|
import dev.lambdaurora.spruceui.Position;
|
||||||
|
import dev.lambdaurora.spruceui.widget.SpruceTexturedButtonWidget;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class SilentTexturedButtonWidget extends SpruceTexturedButtonWidget {
|
||||||
|
public SilentTexturedButtonWidget(Position position, int width, int height, Text message, PressAction action, int u, int v, int hoveredVOffset, Identifier texture) {
|
||||||
|
super(position, width, height, message, action, u, v, hoveredVOffset, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SilentTexturedButtonWidget(Position position, int width, int height, Text message, boolean showMessage, PressAction action, int u, int v, int hoveredVOffset, Identifier texture) {
|
||||||
|
super(position, width, height, message, showMessage, action, u, v, hoveredVOffset, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SilentTexturedButtonWidget(Position position, int width, int height, Text message, PressAction action, int u, int v, int hoveredVOffset, Identifier texture, int textureWidth, int textureHeight) {
|
||||||
|
super(position, width, height, message, action, u, v, hoveredVOffset, texture, textureWidth, textureHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SilentTexturedButtonWidget(Position position, int width, int height, Text message, boolean showMessage, PressAction action, int u, int v, int hoveredVOffset, Identifier texture, int textureWidth, int textureHeight) {
|
||||||
|
super(position, width, height, message, showMessage, action, u, v, hoveredVOffset, texture, textureWidth, textureHeight);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void playDownSound() {}
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.advancement.Advancement;
|
import net.minecraft.advancement.Advancement;
|
||||||
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
||||||
@@ -1,20 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.gui.widget.AbstractButtonWidget;
|
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
@Mixin(AbstractButtonWidget.class)
|
@Mixin(ClickableWidget.class)
|
||||||
public interface AbstractButtonWidgetAccessor {
|
public interface ClickableWidgetAccessor {
|
||||||
@Accessor("height")
|
@Accessor("height")
|
||||||
int getHeight();
|
int getHeight();
|
||||||
|
@Accessor("focused")
|
||||||
|
void setFocused(boolean value);
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
import dev.lambdaurora.lambdacontrols.client.controller.MovementHandler;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.MovementHandler;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.input.Input;
|
import net.minecraft.client.input.Input;
|
||||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
@@ -31,7 +32,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
*/
|
*/
|
||||||
@Mixin(ClientPlayerEntity.class)
|
@Mixin(ClientPlayerEntity.class)
|
||||||
public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity {
|
public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity {
|
||||||
private boolean lambdacontrols$driftingPrevented = false;
|
private boolean midnightcontrols$driftingPrevented = false;
|
||||||
|
|
||||||
|
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
|
||||||
|
super(world, profile);
|
||||||
|
}
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
protected abstract boolean hasMovementInput();
|
protected abstract boolean hasMovementInput();
|
||||||
@@ -46,23 +51,23 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
|
|||||||
@Shadow
|
@Shadow
|
||||||
protected abstract boolean isCamera();
|
protected abstract boolean isCamera();
|
||||||
|
|
||||||
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
|
@Shadow protected int ticksLeftToDoubleTapSprint;
|
||||||
super(world, profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
|
@Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
|
||||||
public void onMove(MovementType type, Vec3d movement, CallbackInfo ci) {
|
public void onMove(MovementType type, Vec3d movement, CallbackInfo ci) {
|
||||||
LambdaControlsClient mod = LambdaControlsClient.get();
|
if (!MidnightControlsConfig.doubleTapToSprint) ticksLeftToDoubleTapSprint = 0;
|
||||||
|
if (!MidnightControls.isExtrasLoaded) return;
|
||||||
if (type == MovementType.SELF) {
|
if (type == MovementType.SELF) {
|
||||||
if (this.abilities.flying && (!mod.config.hasFlyDrifting() || !mod.config.hasFlyVerticalDrifting())) {
|
if (this.getAbilities().flying && (!MidnightControlsConfig.flyDrifting || !MidnightControlsConfig.verticalFlyDrifting)) {
|
||||||
if (!this.hasMovementInput()) {
|
if (!this.hasMovementInput()) {
|
||||||
if (!this.lambdacontrols$driftingPrevented) {
|
if (!this.midnightcontrols$driftingPrevented) {
|
||||||
if (!mod.config.hasFlyDrifting())
|
if (!MidnightControlsConfig.flyDrifting)
|
||||||
this.setVelocity(this.getVelocity().multiply(0, 1.0, 0));
|
this.setVelocity(this.getVelocity().multiply(0, 1.0, 0));
|
||||||
}
|
}
|
||||||
this.lambdacontrols$driftingPrevented = true;
|
this.midnightcontrols$driftingPrevented = true;
|
||||||
} else
|
} else
|
||||||
this.lambdacontrols$driftingPrevented = false;
|
this.midnightcontrols$driftingPrevented = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,8 +79,8 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
|
|||||||
|
|
||||||
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z"))
|
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z"))
|
||||||
public void onTickMovement(CallbackInfo ci) {
|
public void onTickMovement(CallbackInfo ci) {
|
||||||
if (this.abilities.flying && this.isCamera()) {
|
if (this.getAbilities().flying && this.isCamera()) {
|
||||||
if (LambdaControlsClient.get().config.hasFlyVerticalDrifting())
|
if (MidnightControlsConfig.verticalFlyDrifting || !MidnightControls.isExtrasLoaded)
|
||||||
return;
|
return;
|
||||||
int moving = 0;
|
int moving = 0;
|
||||||
if (this.input.sneaking) {
|
if (this.input.sneaking) {
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import eu.midnightdust.lib.util.screen.TexturedOverlayButtonWidget;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
||||||
|
import net.minecraft.client.gui.screen.option.GameOptionsScreen;
|
||||||
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
|
import net.minecraft.client.option.GameOptions;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the new controls settings button.
|
||||||
|
*/
|
||||||
|
@Mixin(ControlsOptionsScreen.class)
|
||||||
|
public abstract class ControlsOptionsScreenMixin extends GameOptionsScreen {
|
||||||
|
@Unique private final boolean showAlternativeButton = FabricLoader.getInstance().isModLoaded("crawl");
|
||||||
|
public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text text) {
|
||||||
|
super(parent, gameOptions, text);
|
||||||
|
}
|
||||||
|
@Inject(method = "init", at = @At(value = "INVOKE", ordinal = 1, shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;"))
|
||||||
|
private void addAlternativeControllerButton(CallbackInfo ci) {
|
||||||
|
if (showAlternativeButton) {
|
||||||
|
this.addDrawableChild(new TexturedOverlayButtonWidget(this.width / 2 + 158, this.height / 6 - 12, 20, 20,0,0,20, new Identifier("midnightcontrols", "textures/gui/midnightcontrols_button.png"), 32, 64, (button) -> {
|
||||||
|
this.client.setScreen(new MidnightControlsSettingsScreen(this, false));
|
||||||
|
}, new TranslatableText("midnightcontrols.menu.title.controller")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Inject(method = "init", at = @At(value = "INVOKE", ordinal = 4, shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;"))
|
||||||
|
private void addControllerButton(CallbackInfo ci) {
|
||||||
|
if (!showAlternativeButton) {
|
||||||
|
int i = this.width / 2 - 155;
|
||||||
|
int j = i + 160;
|
||||||
|
int k = this.height / 6 - 12 + 48;
|
||||||
|
this.addDrawableChild(new ButtonWidget(j, k, 150, 20, new TranslatableText("midnightcontrols.menu.title.controller").append("..."), (button) -> {
|
||||||
|
this.client.setScreen(new MidnightControlsSettingsScreen(this, false));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
import net.minecraft.item.ItemGroup;
|
import net.minecraft.item.ItemGroup;
|
||||||
@@ -26,33 +26,35 @@ public interface CreativeInventoryScreenAccessor {
|
|||||||
/**
|
/**
|
||||||
* Gets the selected tab.
|
* Gets the selected tab.
|
||||||
*
|
*
|
||||||
* @return The selected tab index.
|
* @return the selected tab index
|
||||||
*/
|
*/
|
||||||
@Accessor("selectedTab")
|
@Accessor("selectedTab")
|
||||||
int getSelectedTab();
|
static int getSelectedTab() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the selected tab.
|
* Sets the selected tab.
|
||||||
*
|
*
|
||||||
* @param group The tab's item group.
|
* @param group the tab's item group
|
||||||
*/
|
*/
|
||||||
@Invoker("setSelectedTab")
|
@Invoker("setSelectedTab")
|
||||||
void lambdacontrols$setSelectedTab(@NotNull ItemGroup group);
|
void midnightcontrols$setSelectedTab(@NotNull ItemGroup group);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the slot belongs to the creative inventory or not.
|
* Returns whether the slot belongs to the creative inventory or not.
|
||||||
*
|
*
|
||||||
* @param slot The slot to check.
|
* @param slot the slot to check
|
||||||
* @return True if the slot is from the creative inventory, else false.
|
* @return true if the slot is from the creative inventory, else false
|
||||||
*/
|
*/
|
||||||
@Invoker("isCreativeInventorySlot")
|
@Invoker("isCreativeInventorySlot")
|
||||||
boolean lambdacontrols$isCreativeInventorySlot(@Nullable Slot slot);
|
boolean midnightcontrols$isCreativeInventorySlot(@Nullable Slot slot);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the current tab has a scrollbar or not.
|
* Returns whether the current tab has a scrollbar or not.
|
||||||
*
|
*
|
||||||
* @return True if the current tab has a scrollbar, else false.
|
* @return true if the current tab has a scrollbar, else false
|
||||||
*/
|
*/
|
||||||
@Invoker("hasScrollbar")
|
@Invoker("hasScrollbar")
|
||||||
boolean lambdacontrols$hasScrollbar();
|
boolean midnightcontrols$hasScrollbar();
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
import net.minecraft.client.gui.widget.EntryListWidget;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -16,5 +16,5 @@ import org.spongepowered.asm.mixin.gen.Invoker;
|
|||||||
@Mixin(EntryListWidget.class)
|
@Mixin(EntryListWidget.class)
|
||||||
public interface EntryListWidgetAccessor {
|
public interface EntryListWidgetAccessor {
|
||||||
@Invoker("moveSelection")
|
@Invoker("moveSelection")
|
||||||
void lambdacontrols$moveSelection(EntryListWidget.MoveDirection direction);
|
void midnightcontrols$moveSelection(EntryListWidget.MoveDirection direction);
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.options.GameOptions;
|
import net.minecraft.client.option.GameOptions;
|
||||||
|
import net.minecraft.client.option.Option;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -22,13 +23,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
* Sets the default of the Auto-Jump option to false.
|
* Sets the default of the Auto-Jump option to false.
|
||||||
*/
|
*/
|
||||||
@Mixin(GameOptions.class)
|
@Mixin(GameOptions.class)
|
||||||
public class GameOptionsMixin {
|
public abstract class GameOptionsMixin {
|
||||||
@Shadow
|
|
||||||
public boolean autoJump;
|
@Shadow public boolean autoJump;
|
||||||
|
|
||||||
@Inject(method = "load", at = @At("HEAD"))
|
@Inject(method = "load", at = @At("HEAD"))
|
||||||
public void onInit(CallbackInfo ci) {
|
public void onInit(CallbackInfo ci) {
|
||||||
// Set default value of the Auto-Jump option to false.
|
// Set default value of the Auto-Jump option to false.
|
||||||
this.autoJump = false;
|
autoJump = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.ControlsMode;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.render.GameRenderer;
|
import net.minecraft.client.render.GameRenderer;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
@@ -28,7 +29,7 @@ public class GameRendererMixin {
|
|||||||
|
|
||||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getX()D"))
|
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getX()D"))
|
||||||
private void onRender(float tickDelta, long startTime, boolean fullRender, CallbackInfo ci) {
|
private void onRender(float tickDelta, long startTime, boolean fullRender, CallbackInfo ci) {
|
||||||
if (this.client.currentScreen != null && LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER)
|
if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER)
|
||||||
LambdaControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen);
|
MidnightControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.screen.slot.SlotActionType;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the mixin for the class ContainerScreen.
|
||||||
|
*/
|
||||||
|
@Mixin(HandledScreen.class)
|
||||||
|
public abstract class HandledScreenMixin implements HandledScreenAccessor {
|
||||||
|
@Unique private static float scale = 1f;
|
||||||
|
|
||||||
|
@Accessor("x")
|
||||||
|
public abstract int getX();
|
||||||
|
|
||||||
|
@Accessor("y")
|
||||||
|
public abstract int getY();
|
||||||
|
|
||||||
|
@Invoker("getSlotAt")
|
||||||
|
public abstract Slot midnightcontrols$getSlotAt(double posX, double posY);
|
||||||
|
|
||||||
|
@Invoker("isClickOutsideBounds")
|
||||||
|
public abstract boolean midnightcontrols$isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button);
|
||||||
|
|
||||||
|
|
||||||
|
@Invoker("onMouseClick")
|
||||||
|
public abstract void midnightcontrols$onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
|
||||||
|
|
||||||
|
@Inject(method = "render", at = @At("RETURN"))
|
||||||
|
public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||||
|
var client = MinecraftClient.getInstance();
|
||||||
|
if (client.options.guiScale >= 4) {
|
||||||
|
scale = 0.75f;
|
||||||
|
} else scale = 1f;
|
||||||
|
matrices.push();
|
||||||
|
if (scale != 1f) matrices.scale(scale,scale,scale);
|
||||||
|
int x = 2, y = (int) (client.getWindow().getScaledHeight() * (1 / scale) - 2 - MidnightControlsRenderer.ICON_SIZE);
|
||||||
|
if (MidnightControlsCompat.isEMIPresent()) {
|
||||||
|
x += 40 * (1 / scale);
|
||||||
|
}
|
||||||
|
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "midnightcontrols.action.pickup_all", true, client) + 2;
|
||||||
|
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_B}, "midnightcontrols.action.exit", true, client) + 2;
|
||||||
|
if (MidnightControlsCompat.isReiPresent()) {
|
||||||
|
x = 2;
|
||||||
|
y -= 24;
|
||||||
|
}
|
||||||
|
if (MidnightControlsCompat.isEMIPresent()) {
|
||||||
|
x = (int) (client.getWindow().getScaledWidth() * (1 / scale) - 55 - client.textRenderer.getWidth(new TranslatableText("midnightcontrols.action.pickup"))
|
||||||
|
* (1 / scale) - client.textRenderer.getWidth(new TranslatableText("midnightcontrols.action.quick_move"))
|
||||||
|
- MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.TAKE) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.QUICK_MOVE));
|
||||||
|
}
|
||||||
|
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, "midnightcontrols.action.pickup", true, client);
|
||||||
|
MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, "midnightcontrols.action.quick_move", true, client);
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
@@ -23,16 +23,16 @@ public class KeyBindingMixin implements KeyBindingAccessor {
|
|||||||
private boolean pressed;
|
private boolean pressed;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean lambdacontrols$press() {
|
public boolean midnightcontrols$press() {
|
||||||
boolean oldPressed = this.pressed;
|
boolean oldPressed = this.pressed;
|
||||||
if (!this.pressed)
|
if (!this.pressed)
|
||||||
this.pressed = true;
|
this.pressed = true;
|
||||||
++this.timesPressed;
|
++this.timesPressed;
|
||||||
return oldPressed != this.pressed;
|
return !oldPressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean lambdacontrols$unpress() {
|
public boolean midnightcontrols$unpress() {
|
||||||
if (this.pressed) {
|
if (this.pressed) {
|
||||||
this.pressed = false;
|
this.pressed = false;
|
||||||
return true;
|
return true;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl;
|
||||||
|
import net.minecraft.client.option.KeyBinding;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(value = KeyBindingRegistryImpl.class, remap = false)
|
||||||
|
public interface KeyBindingRegistryImplAccessor {
|
||||||
|
@Accessor @Final
|
||||||
|
static List<KeyBinding> getModdedKeyBindings() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.LambdaControlsFeature;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||||
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsRenderer;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
@@ -29,6 +31,7 @@ import net.minecraft.util.math.BlockPos;
|
|||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -51,10 +54,6 @@ public abstract class MinecraftClientMixin {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public ClientPlayerInteractionManager interactionManager;
|
public ClientPlayerInteractionManager interactionManager;
|
||||||
|
|
||||||
@Shadow
|
|
||||||
@Nullable
|
|
||||||
public ClientWorld world;
|
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
public GameRenderer gameRenderer;
|
public GameRenderer gameRenderer;
|
||||||
@@ -62,13 +61,14 @@ public abstract class MinecraftClientMixin {
|
|||||||
@Shadow
|
@Shadow
|
||||||
private int itemUseCooldown;
|
private int itemUseCooldown;
|
||||||
|
|
||||||
private BlockPos lambdacontrols$lastTargetPos;
|
@Shadow @Nullable public ClientWorld world;
|
||||||
private Vec3d lambdacontrols$lastPos;
|
private BlockPos midnightcontrols$lastTargetPos;
|
||||||
private Direction lambdacontrols$lastTargetSide;
|
private Vec3d midnightcontrols$lastPos;
|
||||||
|
private Direction midnightcontrols$lastTargetSide;
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
private void onInit(CallbackInfo ci) {
|
private void onInit(CallbackInfo ci) {
|
||||||
LambdaControlsClient.get().onMcInit((MinecraftClient) (Object) this);
|
MidnightControlsClient.get().onMcInit((MinecraftClient) (Object) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "tick", at = @At("HEAD"))
|
@Inject(method = "tick", at = @At("HEAD"))
|
||||||
@@ -76,58 +76,74 @@ public abstract class MinecraftClientMixin {
|
|||||||
if (this.player == null)
|
if (this.player == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!LambdaControlsFeature.FAST_BLOCK_PLACING.isAvailable())
|
if (!MidnightControlsFeature.FAST_BLOCK_PLACING.isAvailable())
|
||||||
return;
|
return;
|
||||||
if (this.lambdacontrols$lastPos == null)
|
if (this.midnightcontrols$lastPos == null)
|
||||||
this.lambdacontrols$lastPos = this.player.getPos();
|
this.midnightcontrols$lastPos = this.player.getPos();
|
||||||
|
|
||||||
int cooldown = this.itemUseCooldown;
|
int cooldown = this.itemUseCooldown;
|
||||||
BlockHitResult hitResult;
|
BlockHitResult hitResult;
|
||||||
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.BLOCK && this.player.abilities.flying) {
|
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.BLOCK && this.player.getAbilities().flying) {
|
||||||
hitResult = (BlockHitResult) this.crosshairTarget;
|
hitResult = (BlockHitResult) this.crosshairTarget;
|
||||||
BlockPos targetPos = hitResult.getBlockPos();
|
var targetPos = hitResult.getBlockPos();
|
||||||
Direction side = hitResult.getSide();
|
var side = hitResult.getSide();
|
||||||
|
|
||||||
boolean sidewaysBlockPlacing = this.lambdacontrols$lastTargetPos == null || !targetPos.equals(this.lambdacontrols$lastTargetPos.offset(this.lambdacontrols$lastTargetSide));
|
boolean sidewaysBlockPlacing = this.midnightcontrols$lastTargetPos == null || !targetPos.equals(this.midnightcontrols$lastTargetPos.offset(this.midnightcontrols$lastTargetSide));
|
||||||
boolean backwardsBlockPlacing = this.player.input.movementForward < 0.0f && (this.lambdacontrols$lastTargetPos == null || targetPos.equals(this.lambdacontrols$lastTargetPos.offset(this.lambdacontrols$lastTargetSide)));
|
boolean backwardsBlockPlacing = this.player.input.movementForward < 0.0f && (this.midnightcontrols$lastTargetPos == null || targetPos.equals(this.midnightcontrols$lastTargetPos.offset(this.midnightcontrols$lastTargetSide)));
|
||||||
|
|
||||||
if (cooldown > 1
|
if (cooldown > 1
|
||||||
&& !targetPos.equals(this.lambdacontrols$lastTargetPos)
|
&& !targetPos.equals(this.midnightcontrols$lastTargetPos)
|
||||||
&& (sidewaysBlockPlacing || backwardsBlockPlacing)) {
|
&& (sidewaysBlockPlacing || backwardsBlockPlacing)) {
|
||||||
this.itemUseCooldown = 1;
|
this.itemUseCooldown = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lambdacontrols$lastTargetPos = targetPos.toImmutable();
|
this.midnightcontrols$lastTargetPos = targetPos.toImmutable();
|
||||||
this.lambdacontrols$lastTargetSide = side;
|
this.midnightcontrols$lastTargetSide = side;
|
||||||
}
|
}
|
||||||
// Removed front placing sprinting as way too cheaty.
|
// Removed front placing sprinting as way too cheaty.
|
||||||
/*else if (this.player.isSprinting()) {
|
else if (this.player.isSprinting()) {
|
||||||
hitResult = LambdaControlsClient.get().reacharound.getLastReacharoundResult();
|
hitResult = MidnightControlsClient.get().reacharound.getLastReacharoundResult();
|
||||||
if (hitResult != null) {
|
if (hitResult != null) {
|
||||||
if (cooldown > 0)
|
if (cooldown > 0)
|
||||||
this.itemUseCooldown = 0;
|
this.itemUseCooldown = 0;
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
this.lambdacontrols$lastPos = this.player.getPos();
|
this.midnightcontrols$lastPos = this.player.getPos();
|
||||||
|
}
|
||||||
|
// Applied multiple times for smooth camera turning even on low FPS
|
||||||
|
@Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;startTick()V", shift = At.Shift.BEFORE))
|
||||||
|
private void onPrePreRender(CallbackInfo ci) {
|
||||||
|
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
||||||
|
}
|
||||||
|
@Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Recorder;startTick()V", shift = At.Shift.AFTER))
|
||||||
|
private void onPreRender(CallbackInfo ci) {
|
||||||
|
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "render", at = @At("HEAD"))
|
@Inject(method = "render", at = @At("HEAD"))
|
||||||
private void onRender(boolean fullRender, CallbackInfo ci) {
|
private void onRender(CallbackInfo ci) {
|
||||||
LambdaControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
||||||
|
}
|
||||||
|
@Inject(method = "render", at = @At("TAIL"))
|
||||||
|
private void onPostRender(CallbackInfo ci) {
|
||||||
|
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
||||||
|
}
|
||||||
|
@Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;endTick()V", shift = At.Shift.AFTER))
|
||||||
|
private void onPostPostRender(CallbackInfo ci) {
|
||||||
|
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.AFTER))
|
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.AFTER))
|
||||||
private void renderVirtualCursor(boolean fullRender, CallbackInfo ci) {
|
private void renderVirtualCursor(boolean fullRender, CallbackInfo ci) {
|
||||||
LambdaControlsRenderer.renderVirtualCursor(new MatrixStack(), (MinecraftClient) (Object) this);
|
MidnightControlsRenderer.renderVirtualCursor(new MatrixStack(), (MinecraftClient) (Object) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "doItemUse()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
|
@Inject(method = "doItemUse()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
|
||||||
private void onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand) {
|
private void onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand) {
|
||||||
LambdaControlsClient mod = LambdaControlsClient.get();
|
var mod = MidnightControlsClient.get();
|
||||||
if (!stackInHand.isEmpty() && this.player.pitch > 35.0F && mod.reacharound.isReacharoundAvailable()) {
|
if (!stackInHand.isEmpty() && this.player.getPitch(0.f) > 35.0F && mod.reacharound.isReacharoundAvailable()) {
|
||||||
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.MISS && this.player.isOnGround()) {
|
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.MISS && this.player.isOnGround()) {
|
||||||
if (!stackInHand.isEmpty() && stackInHand.getItem() instanceof BlockItem) {
|
if (!stackInHand.isEmpty() && stackInHand.getItem() instanceof BlockItem) {
|
||||||
BlockHitResult hitResult = mod.reacharound.getLastReacharoundResult();
|
var hitResult = mod.reacharound.getLastReacharoundResult();
|
||||||
|
|
||||||
if (hitResult == null)
|
if (hitResult == null)
|
||||||
return;
|
return;
|
||||||
@@ -135,7 +151,7 @@ public abstract class MinecraftClientMixin {
|
|||||||
hitResult = mod.reacharound.withSideForReacharound(hitResult, stackInHand);
|
hitResult = mod.reacharound.withSideForReacharound(hitResult, stackInHand);
|
||||||
|
|
||||||
int previousStackCount = stackInHand.getCount();
|
int previousStackCount = stackInHand.getCount();
|
||||||
ActionResult result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult);
|
var result = this.interactionManager.interactBlock(this.player, world, hand, hitResult);
|
||||||
if (result.isAccepted()) {
|
if (result.isAccepted()) {
|
||||||
if (result.shouldSwingHand()) {
|
if (result.shouldSwingHand()) {
|
||||||
this.player.swingHand(hand);
|
this.player.swingHand(hand);
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.Mouse;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds extra access to the mouse.
|
||||||
|
*/
|
||||||
|
@Mixin(Mouse.class)
|
||||||
|
public abstract class MouseMixin implements MouseAccessor {
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private MinecraftClient client;
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
public abstract void setLeftButtonClicked(boolean value);
|
||||||
|
|
||||||
|
@Invoker("onCursorPos")
|
||||||
|
public abstract void midnightcontrols$onCursorPos(long window, double x, double y);
|
||||||
|
|
||||||
|
@Inject(method = "onMouseButton", at = @At(value = "TAIL"))
|
||||||
|
private void onMouseBackButton(long window, int button, int action, int mods, CallbackInfo ci) {
|
||||||
|
if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && MinecraftClient.getInstance().currentScreen != null) {
|
||||||
|
if (MidnightControlsClient.get().input.tryGoBack(MinecraftClient.getInstance().currentScreen)) {
|
||||||
|
action = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void isCursorLocked(CallbackInfoReturnable<Boolean> ci) {
|
||||||
|
if (this.client.currentScreen == null) {
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse) {
|
||||||
|
ci.setReturnValue(true);
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void onCursorLocked(CallbackInfo ci) {
|
||||||
|
if (/*config.getControlsMode() == ControlsMode.TOUCHSCREEN
|
||||||
|
||*/ (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse))
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||||
import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget;
|
import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget;
|
||||||
@@ -29,5 +29,5 @@ public interface RecipeBookWidgetAccessor {
|
|||||||
void setCurrentTab(RecipeGroupButtonWidget currentTab);
|
void setCurrentTab(RecipeGroupButtonWidget currentTab);
|
||||||
|
|
||||||
@Invoker("refreshResults")
|
@Invoker("refreshResults")
|
||||||
void lambdacontrols$refreshResults(boolean resetCurrentPage);
|
void midnightcontrols$refreshResults(boolean resetCurrentPage);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.Selectable;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mixin(Screen.class)
|
||||||
|
public interface ScreenAccessor {
|
||||||
|
@Accessor
|
||||||
|
List<Selectable> getSelectables();
|
||||||
|
@Accessor @Nullable
|
||||||
|
Selectable getSelected();
|
||||||
|
}
|
||||||
@@ -1,17 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import net.minecraft.block.Block;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import net.minecraft.block.BlockState;
|
|
||||||
import net.minecraft.block.ShapeContext;
|
import net.minecraft.block.ShapeContext;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.render.*;
|
import net.minecraft.client.render.*;
|
||||||
@@ -19,14 +18,10 @@ import net.minecraft.client.util.math.MatrixStack;
|
|||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.ItemPlacementContext;
|
import net.minecraft.item.ItemPlacementContext;
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.item.ItemUsageContext;
|
import net.minecraft.item.ItemUsageContext;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
|
||||||
import net.minecraft.util.hit.HitResult;
|
import net.minecraft.util.hit.HitResult;
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Matrix4f;
|
import net.minecraft.util.math.Matrix4f;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
import net.minecraft.util.shape.VoxelShape;
|
import net.minecraft.util.shape.VoxelShape;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -68,32 +63,32 @@ public abstract class WorldRendererMixin {
|
|||||||
)
|
)
|
||||||
private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer,
|
private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer,
|
||||||
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
||||||
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !LambdaControlsClient.get().config.shouldRenderReacharoundOutline())
|
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !MidnightControlsConfig.shouldRenderReacharoundOutline)
|
||||||
return;
|
return;
|
||||||
BlockHitResult result = LambdaControlsClient.get().reacharound.getLastReacharoundResult();
|
var result = MidnightControlsClient.get().reacharound.getLastReacharoundResult();
|
||||||
if (result == null)
|
if (result == null)
|
||||||
return;
|
return;
|
||||||
BlockPos blockPos = result.getBlockPos();
|
var blockPos = result.getBlockPos();
|
||||||
if (this.world.getWorldBorder().contains(blockPos)) {
|
if (this.world.getWorldBorder().contains(blockPos)) {
|
||||||
ItemStack stack = this.client.player.getStackInHand(Hand.MAIN_HAND);
|
var stack = this.client.player.getStackInHand(Hand.MAIN_HAND);
|
||||||
if (stack == null || !(stack.getItem() instanceof BlockItem))
|
if (stack == null || !(stack.getItem() instanceof BlockItem))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LambdaControlsClient mod = LambdaControlsClient.get();
|
var mod = MidnightControlsClient.get();
|
||||||
|
|
||||||
Block block = ((BlockItem) stack.getItem()).getBlock();
|
var block = ((BlockItem) stack.getItem()).getBlock();
|
||||||
result = mod.reacharound.withSideForReacharound(result, block);
|
result = mod.reacharound.withSideForReacharound(result, block);
|
||||||
ItemPlacementContext context = new ItemPlacementContext(new ItemUsageContext(this.client.player, Hand.MAIN_HAND, result));
|
var context = new ItemPlacementContext(new ItemUsageContext(this.client.player, Hand.MAIN_HAND, result));
|
||||||
|
|
||||||
BlockState placementState = block.getPlacementState(context);
|
var placementState = block.getPlacementState(context);
|
||||||
if (placementState == null)
|
if (placementState == null)
|
||||||
return;
|
return;
|
||||||
Vec3d pos = camera.getPos();
|
var pos = camera.getPos();
|
||||||
|
|
||||||
VoxelShape outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
|
var outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
|
||||||
int[] color = mod.config.getReacharoundOutlineColor();
|
int[] color = MidnightControlsConfig.reacharoundOutlineColor;
|
||||||
|
|
||||||
VertexConsumer vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
|
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
|
||||||
drawShapeOutline(matrices, vertexConsumer, outlineShape,
|
drawShapeOutline(matrices, vertexConsumer, outlineShape,
|
||||||
(double) blockPos.getX() - pos.getX(), (double) blockPos.getY() - pos.getY(), (double) blockPos.getZ() - pos.getZ(),
|
(double) blockPos.getX() - pos.getX(), (double) blockPos.getY() - pos.getY(), (double) blockPos.getZ() - pos.getZ(),
|
||||||
color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
|
color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.Config;
|
import com.electronwill.nightconfig.core.Config;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
import net.minecraft.client.font.TextRenderer;
|
||||||
@@ -31,6 +31,6 @@ public class DummyRingAction extends RingAction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
public void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
||||||
drawCenteredString(matrices, textRenderer, this.getName(), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff);
|
drawCenteredText(matrices, textRenderer, this.getName(), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.Config;
|
import com.electronwill.nightconfig.core.Config;
|
||||||
import dev.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
import net.minecraft.client.font.TextRenderer;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -39,14 +40,11 @@ public class KeyBindingRingAction extends RingAction {
|
|||||||
public void onAction(@NotNull RingButtonMode mode) {
|
public void onAction(@NotNull RingButtonMode mode) {
|
||||||
KeyBindingAccessor accessor = (KeyBindingAccessor) this.binding;
|
KeyBindingAccessor accessor = (KeyBindingAccessor) this.binding;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case PRESS:
|
case PRESS, HOLD -> accessor.midnightcontrols$handlePressState(this.activated);
|
||||||
case HOLD:
|
case TOGGLE -> {
|
||||||
accessor.lambdacontrols_handlePressState(this.activated);
|
accessor.midnightcontrols$handlePressState(!this.binding.isPressed());
|
||||||
break;
|
|
||||||
case TOGGLE:
|
|
||||||
accessor.lambdacontrols_handlePressState(!this.binding.isPressed());
|
|
||||||
this.activated = !this.binding.isPressed();
|
this.activated = !this.binding.isPressed();
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,40 +1,41 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.Config;
|
import com.electronwill.nightconfig.core.Config;
|
||||||
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a key binding ring.
|
* Represents a key binding ring.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.5.0
|
* @version 1.7.0
|
||||||
* @since 1.4.0
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public final class LambdaRing {
|
public final class MidnightRing {
|
||||||
public static final int ELEMENT_SIZE = 50;
|
public static final int ELEMENT_SIZE = 50;
|
||||||
|
|
||||||
private final Object2ObjectMap<String, RingAction.Factory> actionFactories = new Object2ObjectOpenHashMap<>();
|
private final Map<String, RingAction.Factory> actionFactories = new Object2ObjectOpenHashMap<>();
|
||||||
private final List<RingPage> pages = new ArrayList<>(Collections.singletonList(RingPage.DEFAULT));
|
private final List<RingPage> pages = new ArrayList<>(Collections.singletonList(RingPage.DEFAULT));
|
||||||
private final LambdaControlsClient mod;
|
private final MidnightControlsClient mod;
|
||||||
private int currentPage = 0;
|
private int currentPage = 0;
|
||||||
|
|
||||||
public LambdaRing(@NotNull LambdaControlsClient mod) {
|
public MidnightRing(@NotNull MidnightControlsClient mod) {
|
||||||
this.mod = mod;
|
this.mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,14 +49,12 @@ public final class LambdaRing {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the ring from configuration.
|
* Loads the ring from configuration.
|
||||||
*
|
|
||||||
* @param config The configuration.
|
|
||||||
*/
|
*/
|
||||||
public void load(@NotNull Config config) {
|
public void load() {
|
||||||
List<Config> configPages = config.get("ring.pages");
|
List<Config> configPages = null;
|
||||||
if (configPages != null) {
|
if (configPages != null) {
|
||||||
this.pages.clear();
|
this.pages.clear();
|
||||||
for (Config configPage : configPages) {
|
for (var configPage : configPages) {
|
||||||
RingPage.parseRingPage(configPage).ifPresent(this.pages::add);
|
RingPage.parseRingPage(configPage).ifPresent(this.pages::add);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.Config;
|
import com.electronwill.nightconfig.core.Config;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
import net.minecraft.client.font.TextRenderer;
|
||||||
@@ -40,7 +40,7 @@ public abstract class RingAction extends DrawableHelper implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Gets the text name of the ring action.
|
* Gets the text name of the ring action.
|
||||||
*
|
*
|
||||||
* @return The text name.
|
* @return the text name
|
||||||
*/
|
*/
|
||||||
public Text getTextName() {
|
public Text getTextName() {
|
||||||
return new TranslatableText(this.getName());
|
return new TranslatableText(this.getName());
|
||||||
@@ -49,7 +49,7 @@ public abstract class RingAction extends DrawableHelper implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the action is activated or not.
|
* Returns whether the action is activated or not.
|
||||||
*
|
*
|
||||||
* @return True if the action is activated, else false.
|
* @return true if the action is activated, else false
|
||||||
*/
|
*/
|
||||||
public boolean isActivated() {
|
public boolean isActivated() {
|
||||||
return this.activated;
|
return this.activated;
|
||||||
@@ -64,7 +64,7 @@ public abstract class RingAction extends DrawableHelper implements Nameable {
|
|||||||
public abstract void onAction(@NotNull RingButtonMode mode);
|
public abstract void onAction(@NotNull RingButtonMode mode);
|
||||||
|
|
||||||
public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
||||||
fill(matrices, x, y, x + LambdaRing.ELEMENT_SIZE, y + LambdaRing.ELEMENT_SIZE, hovered ? 0xbb777777 : 0xbb000000);
|
fill(matrices, x, y, x + MidnightRing.ELEMENT_SIZE, y + MidnightRing.ELEMENT_SIZE, hovered ? 0xbb777777 : 0xbb000000);
|
||||||
drawIcon(matrices, textRenderer, x, y, hovered);
|
drawIcon(matrices, textRenderer, x, y, hovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of LambdaControls.
|
* This file is part of midnightcontrols.
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license. For more information,
|
* Licensed under the MIT license. For more information,
|
||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dev.lambdaurora.lambdacontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
@@ -37,10 +37,10 @@ public enum RingButtonMode implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the next ring button mode available.
|
* Returns the next ring button mode available.
|
||||||
*
|
*
|
||||||
* @return The next ring button mode.
|
* @return the next ring button mode
|
||||||
*/
|
*/
|
||||||
public @NotNull RingButtonMode next() {
|
public @NotNull RingButtonMode next() {
|
||||||
RingButtonMode[] v = values();
|
var v = values();
|
||||||
if (v.length == this.ordinal() + 1)
|
if (v.length == this.ordinal() + 1)
|
||||||
return v[0];
|
return v[0];
|
||||||
return v[this.ordinal() + 1];
|
return v[this.ordinal() + 1];
|
||||||
@@ -49,16 +49,16 @@ public enum RingButtonMode implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Returns the translation key of this ring button mode.
|
* Returns the translation key of this ring button mode.
|
||||||
*
|
*
|
||||||
* @return The translation key of this ring button mode.
|
* @return the translation key of this ring button mode
|
||||||
*/
|
*/
|
||||||
public @NotNull String getTranslationKey() {
|
public @NotNull String getTranslationKey() {
|
||||||
return "lambdacontrols.ring.button_mode." + this.getName();
|
return "midnightcontrols.ring.button_mode." + this.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the translated name of this ring button mode.
|
* Gets the translated name of this ring button mode.
|
||||||
*
|
*
|
||||||
* @return The translated name of this ring button mode.
|
* @return the translated name of this ring button mode
|
||||||
*/
|
*/
|
||||||
public @NotNull Text getTranslatedText() {
|
public @NotNull Text getTranslatedText() {
|
||||||
return this.text;
|
return this.text;
|
||||||