mirror of
https://github.com/TeamMidnightDust/MidnightControls.git
synced 2025-12-13 15:25:08 +01:00
Compare commits
168 Commits
v1.7.1
...
architectu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54a43d41c0 | ||
|
|
c86df8714c | ||
|
|
ccad5e1d44 | ||
|
|
58fa3b5bc1 | ||
|
|
0f407ac245 | ||
|
|
7375e5ad20 | ||
|
|
7b723513ae | ||
|
|
0dfd1994dc | ||
|
|
ecb7cfd888 | ||
|
|
18e69c1cb3 | ||
|
|
f5be8eb14e | ||
|
|
4a502730bf | ||
|
|
f263908f5f | ||
|
|
28de7312f8 | ||
|
|
1231c231a9 | ||
|
|
24e58027b2 | ||
|
|
33845e111b | ||
|
|
86622962f8 | ||
|
|
73c5fe1a82 | ||
|
|
70d923f959 | ||
|
|
0ef59057af | ||
|
|
9ebd1a9cea | ||
|
|
bb5c6976c0 | ||
|
|
041eeb29aa | ||
|
|
662bac3053 | ||
|
|
50103ce4cf | ||
|
|
9e12381471 | ||
|
|
945b01a8d6 | ||
|
|
8aa006429d | ||
|
|
114a72cdde | ||
|
|
25e9c9afe3 | ||
|
|
d313115388 | ||
|
|
e46e855961 | ||
|
|
38229bc827 | ||
|
|
f004f0a32d | ||
|
|
c07f3d94dd | ||
|
|
6007ef315d | ||
|
|
1e2dd30e3a | ||
|
|
1c26eeed5e | ||
|
|
f14387b6b4 | ||
|
|
1344a949cd | ||
|
|
65a0b1cf1f | ||
|
|
23f7b2e199 | ||
|
|
e35850c5d5 | ||
|
|
78900ac83e | ||
|
|
7d791fac89 | ||
|
|
bf60595c12 | ||
|
|
b96547dafb | ||
|
|
ab869f4f76 | ||
|
|
84df412162 | ||
|
|
afb80fd89c | ||
|
|
b835a6c4ca | ||
|
|
3eec0dda4a | ||
|
|
a23e8b8975 | ||
|
|
1aa449b5bd | ||
|
|
35ab81f696 | ||
|
|
e08547a641 | ||
|
|
c93cc729f4 | ||
|
|
1595fffc2c | ||
|
|
953df7a8c4 | ||
|
|
a3b8d7cbb5 | ||
|
|
929639c081 | ||
|
|
abcfd4c98c | ||
|
|
24d169b4c2 | ||
|
|
c0af00f2a3 | ||
|
|
333fc7f300 | ||
|
|
dbb6e926e6 | ||
|
|
78ada44d73 | ||
|
|
a55e506af0 | ||
|
|
540920009f | ||
|
|
044bbfe9ed | ||
|
|
f782e17349 | ||
|
|
abcbf20eaf | ||
|
|
86c96c8a3e | ||
|
|
310af56162 | ||
|
|
cd416cf022 | ||
|
|
78df229dd2 | ||
|
|
9bcc63fcef | ||
|
|
202ff888be | ||
|
|
da467619cb | ||
|
|
0d2bd6e4cb | ||
|
|
241228dcde | ||
|
|
45149af859 | ||
|
|
bdb3c36518 | ||
|
|
f82ee2e24a | ||
|
|
27221b62cd | ||
|
|
9e3b2ae060 | ||
|
|
838fab2c63 | ||
|
|
2cbe02ebb2 | ||
|
|
ba74d98109 | ||
|
|
d3a787090e | ||
|
|
00780e13fd | ||
|
|
a5554ee21d | ||
|
|
728a2d4603 | ||
|
|
eb54245c21 | ||
|
|
e6fcd1469c | ||
|
|
8a30b5ee73 | ||
|
|
43ffd89a61 | ||
|
|
8a9866f92f | ||
|
|
b12413cbcd | ||
|
|
9f62538197 | ||
|
|
ba5143403d | ||
|
|
454afa92ec | ||
|
|
8e05b658c2 | ||
|
|
cba8a4e1d4 | ||
|
|
dd0795bc56 | ||
|
|
566c26ac17 | ||
|
|
e203e26c3f | ||
|
|
797d1463a6 | ||
|
|
3e665a14fd | ||
|
|
2b143c6bf1 | ||
|
|
ab317f3d31 | ||
|
|
2c11a23914 | ||
|
|
6df3e4454b | ||
|
|
afee0b407d | ||
|
|
d32aefccac | ||
|
|
98797b03ea | ||
|
|
e1d53ee463 | ||
|
|
233ae36343 | ||
|
|
eb4f30913a | ||
|
|
1186c9c241 | ||
|
|
de7cf8a307 | ||
|
|
15510b5997 | ||
|
|
cb56632ec4 | ||
|
|
9d11d08807 | ||
|
|
54f731c7f0 | ||
|
|
3e3ab8743d | ||
|
|
ae3d6cc846 | ||
|
|
00c68004e8 | ||
|
|
f0f6a443bf | ||
|
|
d8ff51b3d3 | ||
|
|
0315784a47 | ||
|
|
3a4d23fb91 | ||
|
|
8bce9170a2 | ||
|
|
ec0c334d4a | ||
|
|
b4209785e0 | ||
|
|
fa3d56eb25 | ||
|
|
60bd283c4c | ||
|
|
889a5d8d58 | ||
|
|
febf171b88 | ||
|
|
d133fed2f6 | ||
|
|
9a61a13fb3 | ||
|
|
e97223e316 | ||
|
|
f16f7416ea | ||
|
|
c086ecfcef | ||
|
|
66cdca30fe | ||
|
|
6e49667ada | ||
|
|
d4c3208cee | ||
|
|
35a4fbee1b | ||
|
|
2aac2ad4e7 | ||
|
|
4b2919bfca | ||
|
|
1c999137ba | ||
|
|
d48952fec9 | ||
|
|
9deab7228d | ||
|
|
b4d82a7230 | ||
|
|
36e241e438 | ||
|
|
bdbee99fe2 | ||
|
|
439cd0858e | ||
|
|
617648cf57 | ||
|
|
89914a1b6e | ||
|
|
c272fb457f | ||
|
|
308b41094f | ||
|
|
bf7209083a | ||
|
|
187844db2b | ||
|
|
24ced76d06 | ||
|
|
aa75a58a4d | ||
|
|
1f675622f0 | ||
|
|
2d902bbf3c |
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve
|
||||||
title: ''
|
title: 'Bug: TITLE HERE'
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
@@ -21,15 +21,17 @@ Steps to reproduce the behavior:
|
|||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots or videos to help explain your problem.
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
**Desktop (please complete the following information):**
|
||||||
- OS: [e.g. Linux]
|
- OS: [e.g. Windows / Linux / MacOS]
|
||||||
- Minecraft [e.g. 1.14.4]
|
- Minecraft [e.g. 1.20.4]
|
||||||
- Fabric [e.g. fabric 0.7.2+build.174]
|
- Modloader [e.g. Fabric Loader 0.15.6]
|
||||||
- Mods [e.g. aurora_keystrokes v1.0.0, modmenu v1.7.15]
|
- Fabric/Quilt Libraries [e.g. Fabric Api 0.96.1+1.20.4]
|
||||||
|
- Mods [e.g. Puzzle v1.6.1, LilTaterReloaded v1.1.15]
|
||||||
- Version [e.g. 1.0.0]
|
- Version [e.g. 1.0.0]
|
||||||
- Branch [e.g. dev]
|
- Remove this line if you actually completed it
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
In case of a crash, please provide the crash log.
|
||||||
|
|||||||
40
.github/ISSUE_TEMPLATE/controller_support.md
vendored
Normal file
40
.github/ISSUE_TEMPLATE/controller_support.md
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
name: Controller support
|
||||||
|
about: Report a problem related to a specific controller
|
||||||
|
title: 'Controller Issues: CONTROLLER NAME HERE'
|
||||||
|
labels: controller
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the current state**
|
||||||
|
A clear and concise description of current state of support for the controller and the issues.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
If needed, specify steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots or videos to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- Have you checked #263 for your controller? [e.g. Yes/No]
|
||||||
|
- Connection method [e.g. Wired / Bluetooth]
|
||||||
|
|
||||||
|
- OS: [e.g. Windows / Linux / MacOS]
|
||||||
|
- Minecraft [e.g. 1.20.4]
|
||||||
|
- Modloader [e.g. Fabric Loader 0.15.6]
|
||||||
|
- Fabric/Quilt Libraries [e.g. Fabric Api 0.96.1+1.20.4]
|
||||||
|
- Mods [e.g. Puzzle v1.6.1, LilTaterReloaded v1.1.15]
|
||||||
|
- Version [e.g. 1.0.0]
|
||||||
|
- Remove this line if you actually completed it
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
|
In case of a crash, please provide the crash log.
|
||||||
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an idea for this project
|
about: Suggest an idea for this project
|
||||||
title: ''
|
title: 'Feature: TITLE HERE'
|
||||||
labels: enhancement
|
labels: enhancement
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
@@ -17,4 +17,4 @@ A clear and concise description of what you want to happen.
|
|||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots/videos about the feature request here.
|
||||||
|
|||||||
20
.github/ISSUE_TEMPLATE/mod_support.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/mod_support.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Mod Support
|
||||||
|
about: Compatibility improvements with a specific mod (not for crashes)
|
||||||
|
title: 'Mod Support: MOD NAME HERE'
|
||||||
|
labels: mod compatibility
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your compatibility request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I've always wanted to [...]
|
||||||
|
|
||||||
|
**Describe the way of compatibility you'd imagine**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative mods or workarounds you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots/videos about the compatibility request here.
|
||||||
29
.github/workflows/build.yml
vendored
Normal file
29
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: Build with Gradle
|
||||||
|
|
||||||
|
on: [ push, pull_request ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Set up Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
- name: Set up JDK 21
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 21
|
||||||
|
check-latest: true
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew build
|
||||||
|
- name: Upload artifacts to GitHub
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: MidnightControls-Artifacts
|
||||||
|
path: |
|
||||||
|
fabric/build/libs/
|
||||||
|
neoforge/build/libs/
|
||||||
23
.github/workflows/gradlebuild.yml
vendored
23
.github/workflows/gradlebuild.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
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/
|
|
||||||
23
.github/workflows/modrinth_update.yml
vendored
23
.github/workflows/modrinth_update.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
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
|
|
||||||
40
.github/workflows/gradlepublish.yml → .github/workflows/publish.yml
vendored
Executable file → Normal file
40
.github/workflows/gradlepublish.yml → .github/workflows/publish.yml
vendored
Executable file → Normal file
@@ -1,30 +1,26 @@
|
|||||||
name: Gradle Package
|
name: Publish to Modrinth
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
release:
|
||||||
tags:
|
types:
|
||||||
- '*'
|
- published
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
publish:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- name: Checkout Repository
|
||||||
- name: Set up JDK 16
|
uses: actions/checkout@v4
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
with:
|
||||||
java-version: 16
|
persist-credentials: false
|
||||||
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
- name: Set up Gradle
|
||||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
- name: Set up JDK 21
|
||||||
- name: Build with Gradle
|
uses: actions/setup-java@v4
|
||||||
run: ./gradlew build
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
with:
|
with:
|
||||||
name: Artifacts
|
distribution: 'temurin'
|
||||||
path: ./build/libs/
|
java-version: 21
|
||||||
|
check-latest: true
|
||||||
# The USERNAME and PASSWORD need to correspond to the credentials environment variables used in
|
# The USERNAME and PASSWORD need to correspond to the credentials environment variables used in
|
||||||
# the publishing section of your build.gradle
|
# the publishing section of your build.gradle
|
||||||
- name: Publish to GitHub Packages and other Mavens
|
- name: Publish to GitHub Packages and other Mavens
|
||||||
@@ -38,3 +34,7 @@ jobs:
|
|||||||
midnightcontrols_MAVEN: ${{ secrets.MAVEN_URL }}
|
midnightcontrols_MAVEN: ${{ secrets.MAVEN_URL }}
|
||||||
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
|
- name: Publish to Modrinth
|
||||||
|
env:
|
||||||
|
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||||
|
run: ./gradlew publishModrinth
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
[](https://github.com/TeamMidnightDust/MidnightControls/releases)
|
[](https://github.com/TeamMidnightDust/MidnightControls/releases)
|
||||||

|

|
||||||
[![Mod loader: Quilt/Fabric]][Quilt]
|
[![Mod loader: Quilt/Fabric]][Quilt]
|
||||||
[](https://www.oracle.com/java/technologies/downloads/#java17)
|
[](https://www.oracle.com/java/technologies/downloads/#java21)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
A Fabric Minecraft mod which adds better controls, reach-around and controller support.
|
A Fabric Minecraft mod which adds better controls, reach-around and controller support.
|
||||||
@@ -62,6 +62,10 @@ Enter the folder created and run:
|
|||||||
```
|
```
|
||||||
After this is done, everything should be built just fine!
|
After this is done, everything should be built just fine!
|
||||||
|
|
||||||
|
## FAQ:
|
||||||
|
### The controller does not work, and it's name appears in orange, what can I do?
|
||||||
|
Create a custom mapping as pointed out in the [wiki](https://midnightdust.eu/wiki/midnightcontrols/)
|
||||||
|
|
||||||
[Quilt]: https://quiltmc.org
|
[Quilt]: https://quiltmc.org
|
||||||
|
|
||||||
[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: 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==
|
||||||
|
|||||||
307
build.gradle
307
build.gradle
@@ -1,269 +1,88 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '0.12-SNAPSHOT'
|
id "architectury-plugin" version "3.4-SNAPSHOT"
|
||||||
id 'java-library'
|
id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false
|
||||||
id 'maven-publish'
|
id "me.shedaniel.unified-publishing" version "0.1.+" apply false
|
||||||
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||||
id 'com.modrinth.minotaur' version '1.2.+'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder
|
architectury {
|
||||||
import com.google.gson.JsonObject
|
minecraft = rootProject.minecraft_version
|
||||||
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
|
|
||||||
version = "${project.mod_version}+${getMCVersionString()}"
|
|
||||||
archivesBaseName = project.archives_base_name
|
|
||||||
|
|
||||||
// This field defines the Java version your mod target.
|
|
||||||
def targetJavaVersion = 17
|
|
||||||
|
|
||||||
boolean isMCVersionNonRelease() {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
def version = project.minecraft_version.split('\\.')
|
|
||||||
return version[0] + '.' + version[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
mavenCentral()
|
|
||||||
maven { url 'https://aperlambda.github.io/maven' }
|
|
||||||
maven {
|
maven {
|
||||||
name 'Gegy'
|
url = "https://api.modrinth.com/maven"
|
||||||
url 'https://maven.gegy.dev'
|
|
||||||
}
|
}
|
||||||
maven {
|
flatDir {
|
||||||
name = "CottonMC"
|
dirs("localMaven")
|
||||||
url = "https://server.bbkr.space/artifactory/libs-release"
|
|
||||||
}
|
|
||||||
maven { url "https://maven.terraformersmc.com/releases/" }
|
|
||||||
maven { url 'https://maven.kosmx.dev' }
|
|
||||||
maven { url 'https://maven.isxander.dev/releases' }
|
|
||||||
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 {
|
|
||||||
shadow
|
|
||||||
api.extendsFrom shadow
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
//to change the versions see the gradle.properties file
|
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
|
||||||
|
|
||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
|
||||||
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}"
|
|
||||||
|
|
||||||
// Compatibility mods
|
|
||||||
|
|
||||||
// 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}"
|
|
||||||
|
|
||||||
modImplementation "io.github.cottonmc:LibGui:${project.libgui_version}"
|
|
||||||
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 "dev.isxander:yet-another-config-lib:${project.yacl_version}"
|
|
||||||
modImplementation "maven.modrinth:inventory-tabs-updated:${project.inventorytabs_version}"
|
|
||||||
modImplementation "maven.modrinth:bedrockify:${project.bedrockify_version}"
|
|
||||||
// Required for Inventory Tabs
|
|
||||||
modApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") {
|
|
||||||
exclude(group: "net.fabricmc.fabric-api")
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
sourceCompatibility = JavaVersion.toVersion(targetJavaVersion)
|
|
||||||
targetCompatibility = JavaVersion.toVersion(targetJavaVersion)
|
|
||||||
|
|
||||||
withSourcesJar()
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach {
|
|
||||||
it.options.encoding = 'UTF-8'
|
|
||||||
|
|
||||||
it.options.release.set(targetJavaVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
processResources {
|
|
||||||
inputs.property 'version', project.version
|
|
||||||
|
|
||||||
filesMatching('fabric.mod.json') {
|
|
||||||
expand 'version': project.version
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task publishModrinth(type: TaskModrinthUpload) {
|
subprojects {
|
||||||
dependsOn(build)
|
apply plugin: "dev.architectury.loom"
|
||||||
onlyIf {
|
repositories {
|
||||||
System.getenv('MODRINTH_TOKEN')
|
maven {
|
||||||
}
|
url = "https://api.modrinth.com/maven"
|
||||||
|
}
|
||||||
token = System.getenv('MODRINTH_TOKEN')
|
maven { url 'https://jitpack.io' }
|
||||||
projectId = project.modrinth_id
|
flatDir {
|
||||||
versionNumber = version
|
dirs("../localMaven")
|
||||||
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
|
dependencies {
|
||||||
doFirst {
|
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
|
||||||
final def client = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
|
// The following line declares the mojmap mappings, you may use other mappings as well
|
||||||
final def patch = new HttpPatch((String) (apiURL + '/v1/mod/' + projectId))
|
//mappings loom.officialMojangMappings()
|
||||||
patch.addHeader("Authorization", token)
|
// The following line declares the yarn mappings you may select this one as well.
|
||||||
|
mappings loom.layered {
|
||||||
var json = new JsonObject()
|
it.mappings("net.fabricmc:yarn:$rootProject.yarn_mappings:v2")
|
||||||
json.addProperty("body", parseReadme())
|
it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version")
|
||||||
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()}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure the maven publication
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
mavenJava(MavenPublication) {
|
|
||||||
artifact(sourcesJar) {
|
|
||||||
builtBy remapSourcesJar
|
|
||||||
}
|
|
||||||
|
|
||||||
pom {
|
allprojects {
|
||||||
name = 'midnightcontrols'
|
apply plugin: "java"
|
||||||
description = 'Adds better controls, and controller support.'
|
apply plugin: "architectury-plugin"
|
||||||
}
|
apply plugin: "maven-publish"
|
||||||
|
|
||||||
pom.withXml {
|
archivesBaseName = rootProject.archives_base_name
|
||||||
def dependenciesNode = asNode().appendNode('dependencies')
|
version = rootProject.mod_version
|
||||||
|
group = rootProject.maven_group
|
||||||
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()
|
maven { url 'https://aperlambda.github.io/maven' }
|
||||||
maven {
|
}
|
||||||
name 'GithubPackages'
|
dependencies {
|
||||||
url uri('https://maven.pkg.github.com/LambdAurora/midnightcontrols')
|
implementation('org.aperlambda:lambdajcommon:1.8.1') {
|
||||||
credentials {
|
exclude group: 'com.google.code.gson'
|
||||||
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
|
exclude group: 'com.google.guava'
|
||||||
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def midnightcontrolsMaven = System.getenv('midnightcontrols_MAVEN')
|
|
||||||
if (midnightcontrolsMaven) {
|
|
||||||
maven {
|
|
||||||
name 'midnightcontrolsMaven'
|
|
||||||
url uri(midnightcontrolsMaven)
|
|
||||||
credentials {
|
|
||||||
username = project.findProperty('gpr.user') ?: System.getenv('MAVEN_USERNAME')
|
|
||||||
password = project.findProperty('gpr.key') ?: System.getenv('MAVEN_PASSWORD')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
options.release = 21
|
||||||
|
}
|
||||||
|
ext {
|
||||||
|
releaseChangelog = {
|
||||||
|
def changes = new StringBuilder()
|
||||||
|
changes << "## MidnightControls v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/MidnightControls/commits/)"
|
||||||
|
def proc = "git log --max-count=1 --pretty=format:%s".execute()
|
||||||
|
proc.in.eachLine { line ->
|
||||||
|
def processedLine = line.toString()
|
||||||
|
if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) {
|
||||||
|
changes << "\n- ${processedLine.capitalize()}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proc.waitFor()
|
||||||
|
return changes.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withSourcesJar()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
common/build.gradle
Normal file
65
common/build.gradle
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
architectury {
|
||||||
|
common(rootProject.enabled_platforms.split(","))
|
||||||
|
}
|
||||||
|
loom {
|
||||||
|
accessWidenerPath = file("src/main/resources/midnightcontrols.accesswidener")
|
||||||
|
}
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name 'Gegy'
|
||||||
|
url 'https://maven.gegy.dev'
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
name = "CottonMC"
|
||||||
|
url = "https://server.bbkr.space/artifactory/libs-release"
|
||||||
|
}
|
||||||
|
maven { url "https://maven.terraformersmc.com/releases/" }
|
||||||
|
maven { url 'https://maven.kosmx.dev' }
|
||||||
|
maven { url 'https://maven.isxander.dev/releases' }
|
||||||
|
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'}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
|
||||||
|
// Do NOT use other classes from fabric loader
|
||||||
|
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||||
|
// Using the Fabric version of midnightlib here to create a common config and get useful utilities
|
||||||
|
// Just make sure NOT to use classes from the .fabric classpath
|
||||||
|
modCompileOnlyApi "maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric"
|
||||||
|
modCompileOnlyApi "maven.modrinth:obsidianui:${rootProject.obsidianui_version}-fabric"
|
||||||
|
modCompileOnlyApi ("com.terraformersmc:modmenu:${project.modmenu_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compatibility mods
|
||||||
|
modCompileOnlyApi "io.github.cottonmc:LibGui:${project.libgui_version}"
|
||||||
|
modCompileOnlyApi "org.quiltmc:quilt-json5:1.0.0"
|
||||||
|
modImplementation "maven.modrinth:sodium:${project.sodium_version}-fabric"
|
||||||
|
modCompileOnlyApi "maven.modrinth:emi:${project.emi_version}"
|
||||||
|
modImplementation "maven.modrinth:emotecraft:${project.emotecraft_version}"
|
||||||
|
modCompileOnlyApi "io.github.kosmx:bendy-lib:${project.bendylib_version}"
|
||||||
|
modCompileOnlyApi "dev.isxander:yet-another-config-lib:${project.yacl_version}"
|
||||||
|
modCompileOnlyApi "maven.modrinth:inventory-tabs-updated:${project.inventorytabs_version}"
|
||||||
|
modCompileOnlyApi "maven.modrinth:bedrockify:${project.bedrockify_version}"
|
||||||
|
// Required for Inventory Tabs
|
||||||
|
modCompileOnlyApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
mavenCommon(MavenPublication) {
|
||||||
|
artifactId = rootProject.archives_base_name
|
||||||
|
from components.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||||
|
repositories {
|
||||||
|
// Add repositories to publish to here.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols;
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
import dev.lambdaurora.spruceui.util.Nameable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.thinkingstudio.obsidianui.util.Nameable;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -22,7 +22,7 @@ import java.util.Optional;
|
|||||||
* @version 1.7.0
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum ControlsMode implements Nameable {
|
public enum ControlsMode {
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
CONTROLLER,
|
CONTROLLER,
|
||||||
TOUCHSCREEN;
|
TOUCHSCREEN;
|
||||||
@@ -49,7 +49,6 @@ public enum ControlsMode implements Nameable {
|
|||||||
return "midnightcontrols.controls_mode." + this.getName();
|
return "midnightcontrols.controls_mode." + this.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.name().toLowerCase();
|
return this.name().toLowerCase();
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.lib.util.PlatformFunctions;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the MidnightControls mod.
|
||||||
|
*
|
||||||
|
* @author LambdAurora & Motschen
|
||||||
|
* @version 1.8.0
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class MidnightControls {
|
||||||
|
public static boolean isExtrasLoaded;
|
||||||
|
|
||||||
|
public static final Logger logger = LogManager.getLogger("MidnightControls");
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
isExtrasLoaded = PlatformFunctions.isModLoaded("midnightcontrols-extra");
|
||||||
|
log("Initializing MidnightControls...");
|
||||||
|
}
|
||||||
|
public static Identifier id(String path) {
|
||||||
|
return Identifier.of(MidnightControlsConstants.NAMESPACE, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a message to the terminal.
|
||||||
|
*
|
||||||
|
* @param info the message to print
|
||||||
|
*/
|
||||||
|
public static void log(String info) {
|
||||||
|
logger.info("[MidnightControls] {}", info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a warning to the terminal.
|
||||||
|
*
|
||||||
|
* @param warning the warning to print
|
||||||
|
*/
|
||||||
|
public static void warn(String warning) {
|
||||||
|
logger.warn("[MidnightControls] {}", warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,8 @@ package eu.midnightdust.midnightcontrols;
|
|||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the constants used by MidnightControls.
|
* Represents the constants used by MidnightControls.
|
||||||
*
|
*
|
||||||
@@ -21,7 +23,7 @@ import net.minecraft.util.Identifier;
|
|||||||
*/
|
*/
|
||||||
public class MidnightControlsConstants {
|
public class MidnightControlsConstants {
|
||||||
public static final String NAMESPACE = "midnightcontrols";
|
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 = id("controls_mode");
|
||||||
public static final Identifier FEATURE_CHANNEL = new Identifier(NAMESPACE, "feature");
|
public static final Identifier FEATURE_CHANNEL = id("feature");
|
||||||
public static final Identifier HELLO_CHANNEL = new Identifier("lambdacontrols", "hello");
|
public static final Identifier HELLO_CHANNEL = id("hello");
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols;
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
import dev.lambdaurora.spruceui.util.Nameable;
|
import org.thinkingstudio.obsidianui.util.Nameable;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -44,6 +44,7 @@ public class MidnightControlsFeature implements Nameable {
|
|||||||
this.setEnabled(this.defaultEnabled = enabled);
|
this.setEnabled(this.defaultEnabled = enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public MidnightControlsFeature(@NotNull String key) {
|
public MidnightControlsFeature(@NotNull String key) {
|
||||||
this(key, false, false);
|
this(key, false, false);
|
||||||
}
|
}
|
||||||
@@ -51,6 +52,7 @@ public class MidnightControlsFeature implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Allows the feature.
|
* Allows the feature.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void allow() {
|
public void allow() {
|
||||||
this.setAllowed(true);
|
this.setAllowed(true);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
* 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 eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
|
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.RingScreen;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.MouseClickInterceptor;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import org.thinkingstudio.obsidianui.hud.HudManager;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
|
||||||
|
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.option.KeyBinding;
|
||||||
|
import net.minecraft.client.toast.SystemToast;
|
||||||
|
import net.minecraft.client.util.InputUtil;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the midnightcontrols client mod.
|
||||||
|
*
|
||||||
|
* @author Motschen, LambdAurora
|
||||||
|
* @version 1.10.0
|
||||||
|
* @since 1.1.0
|
||||||
|
*/
|
||||||
|
public class MidnightControlsClient extends MidnightControls {
|
||||||
|
public static boolean lateInitDone = false;
|
||||||
|
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(id("look_up"),
|
||||||
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.midnightcontrols");
|
||||||
|
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(id("look_right"),
|
||||||
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.midnightcontrols");
|
||||||
|
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(id("look_down"),
|
||||||
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.midnightcontrols");
|
||||||
|
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(id("look_left"),
|
||||||
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.midnightcontrols");
|
||||||
|
public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(id("ring"),
|
||||||
|
InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), "key.categories.midnightcontrols");
|
||||||
|
public static final Identifier CONTROLLER_BUTTONS = id("textures/gui/controller_buttons.png");
|
||||||
|
public static final Identifier CONTROLLER_EXPANDED = id("textures/gui/controller_expanded.png");
|
||||||
|
public static final Identifier CONTROLLER_AXIS = id("textures/gui/controller_axis.png");
|
||||||
|
public static final Identifier WAYLAND_CURSOR_TEXTURE_LIGHT = id("cursor/light/mouse_pointer");
|
||||||
|
public static final Identifier WAYLAND_CURSOR_TEXTURE_DARK = id("cursor/dark/mouse_pointer");
|
||||||
|
public static final File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt");
|
||||||
|
public static MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
public static final MidnightInput input = new MidnightInput();
|
||||||
|
public static final MidnightRing ring = new MidnightRing();
|
||||||
|
public static final MidnightReacharound reacharound = new MidnightReacharound();
|
||||||
|
public static final MouseClickInterceptor clickInterceptor = new MouseClickInterceptor();
|
||||||
|
public static boolean isWayland;
|
||||||
|
private static MidnightControlsHud hud;
|
||||||
|
private static ControlsMode previousControlsMode;
|
||||||
|
|
||||||
|
public static void initClient() {
|
||||||
|
client = MinecraftClient.getInstance();
|
||||||
|
ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY);
|
||||||
|
|
||||||
|
int delay = 0; // delay for 0 sec.
|
||||||
|
int period = 1; // repeat every 0.001 sec. (1000 times a second)
|
||||||
|
Timer timer = new Timer();
|
||||||
|
timer.scheduleAtFixedRate(new TimerTask() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if (lateInitDone && client.isRunning()) {
|
||||||
|
if (MidnightControlsConfig.controlsMode != ControlsMode.DEFAULT && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput)) {
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) input.tickCameraStick();
|
||||||
|
input.updateCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception | Error e) {
|
||||||
|
MidnightControls.logger.error("Exception encountered in camera loop: ",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, delay, period);
|
||||||
|
|
||||||
|
HudManager.register(hud = new MidnightControlsHud());
|
||||||
|
isWayland = GLFW.glfwGetVersionString().contains("Wayland");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when Minecraft is initializing.
|
||||||
|
*/
|
||||||
|
public static void onMcInit(@NotNull MinecraftClient client) {
|
||||||
|
ButtonBinding.init(client.options);
|
||||||
|
MidnightControlsConfig.load();
|
||||||
|
if (MidnightControlsConfig.configVersion < 2) {
|
||||||
|
MidnightControlsConfig.mouseScreens.remove("me.jellysquid.mods.sodium.client.gui");
|
||||||
|
MidnightControlsConfig.mouseScreens.remove("net.coderbot.iris.gui");
|
||||||
|
MidnightControlsConfig.mouseScreens.remove("net.minecraft.class_5375");
|
||||||
|
MidnightControlsConfig.mouseScreens.remove("net.minecraft.client.gui.screen.pack.PackScreen");
|
||||||
|
MidnightControlsConfig.configVersion = 2;
|
||||||
|
MidnightControlsConfig.write(MidnightControlsConstants.NAMESPACE);
|
||||||
|
}
|
||||||
|
hud.setVisible(MidnightControlsConfig.hudEnable);
|
||||||
|
Controller.updateMappings();
|
||||||
|
try {
|
||||||
|
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
||||||
|
if (event == GLFW.GLFW_CONNECTED) {
|
||||||
|
var controller = Controller.byId(jid);
|
||||||
|
client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.connected", jid),
|
||||||
|
Text.literal(controller.getName())));
|
||||||
|
} else if (event == GLFW.GLFW_DISCONNECTED) {
|
||||||
|
client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.disconnected", jid),
|
||||||
|
null));
|
||||||
|
}
|
||||||
|
|
||||||
|
switchControlsMode();
|
||||||
|
});
|
||||||
|
} catch (Exception e) {e.fillInStackTrace();}
|
||||||
|
|
||||||
|
MidnightControlsCompat.init();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This method is called to initialize keybindings
|
||||||
|
*/
|
||||||
|
public static void initKeybindings() {
|
||||||
|
if (lateInitDone) return;
|
||||||
|
if (KeyBindingIDAccessor.getKEYS_BY_ID() == null || KeyBindingIDAccessor.getKEYS_BY_ID().isEmpty()) return;
|
||||||
|
if (PlatformFunctions.isModLoaded("voxelmap") && !KeyBindingIDAccessor.getKEYS_BY_ID().containsKey("key.minimap.toggleingamewaypoints")) return;
|
||||||
|
if (PlatformFunctions.isModLoaded("wynntils") && KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().noneMatch(b -> Objects.equals(b.getValue().getCategory(), "Wynntils"))) return;
|
||||||
|
for (int i = 0; i < KeyBindingIDAccessor.getKEYS_BY_ID().size(); ++i) {
|
||||||
|
KeyBinding keyBinding = KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().toList().get(i).getValue();
|
||||||
|
if (MidnightControlsConfig.excludedKeybindings.stream().noneMatch(excluded -> keyBinding.getTranslationKey().startsWith(excluded))) {
|
||||||
|
if (!keyBinding.getTranslationKey().contains(MidnightControlsConstants.NAMESPACE)) {
|
||||||
|
AtomicReference<ButtonCategory> category = new AtomicReference<>();
|
||||||
|
InputManager.streamCategories().forEach(buttonCategory -> {
|
||||||
|
if (buttonCategory.getIdentifier().equals(validVanillaId(keyBinding.getCategory())))
|
||||||
|
category.set(buttonCategory);
|
||||||
|
});
|
||||||
|
if (category.get() == null) {
|
||||||
|
category.set(new ButtonCategory(validVanillaId(keyBinding.getCategory())));
|
||||||
|
InputManager.registerCategory(category.get());
|
||||||
|
}
|
||||||
|
ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getTranslationKey()).category(category.get()).linkKeybind(keyBinding).register();
|
||||||
|
if (MidnightControlsConfig.debug) {
|
||||||
|
MidnightControls.log(keyBinding.getTranslationKey());
|
||||||
|
MidnightControls.log(String.valueOf(buttonBinding));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InputManager.loadButtonBindings();
|
||||||
|
lateInitDone = true;
|
||||||
|
}
|
||||||
|
private static Identifier validVanillaId(String path) {
|
||||||
|
for(int i = 0; i < path.length(); ++i) {
|
||||||
|
if (!Identifier.isPathCharacterValid(path.charAt(i))) {
|
||||||
|
path = path.replace(path.charAt(i), '_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Identifier.ofVanilla(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called every Minecraft tick.
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
*/
|
||||||
|
public static void onTick(@NotNull MinecraftClient client) {
|
||||||
|
initKeybindings();
|
||||||
|
input.tick();
|
||||||
|
reacharound.tick();
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput))
|
||||||
|
input.tickController();
|
||||||
|
|
||||||
|
if (BINDING_RING.wasPressed()) {
|
||||||
|
ring.loadFromUnbound();
|
||||||
|
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, Text.translatable("midnightcontrols.controller.tutorial.title"),
|
||||||
|
Text.translatable("midnightcontrols.controller.tutorial.description", Text.translatable("options.title"), Text.translatable("controls.title"),
|
||||||
|
Text.translatable("midnightcontrols.menu.title.controller"))));
|
||||||
|
MidnightControlsConfig.enableHints = false;
|
||||||
|
MidnightControlsConfig.save();
|
||||||
|
}
|
||||||
|
RainbowColor.tick();
|
||||||
|
TouchInput.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when opening a screen.
|
||||||
|
*/
|
||||||
|
public static void onScreenOpen(Screen screen) {
|
||||||
|
client = MinecraftClient.getInstance();
|
||||||
|
if (screen == null && MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) {
|
||||||
|
screen = new TouchscreenOverlay();
|
||||||
|
screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||||
|
client.skipGameRender = false;
|
||||||
|
client.currentScreen = screen;
|
||||||
|
} else if (screen != null) {
|
||||||
|
MidnightControlsClient.input.onScreenOpen(client.getWindow().getWidth(), client.getWindow().getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when leaving a server.
|
||||||
|
*/
|
||||||
|
public static void onLeave() {
|
||||||
|
MidnightControlsFeature.resetAllAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches the controls mode if the auto switch is enabled.
|
||||||
|
*/
|
||||||
|
public static void switchControlsMode() {
|
||||||
|
if (MidnightControlsConfig.autoSwitchMode) {
|
||||||
|
if (MidnightControlsConfig.getController().isGamepad()) {
|
||||||
|
previousControlsMode = MidnightControlsConfig.controlsMode;
|
||||||
|
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||||
|
} else {
|
||||||
|
if (previousControlsMode == null) {
|
||||||
|
previousControlsMode = ControlsMode.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
MidnightControlsConfig.controlsMode = previousControlsMode;
|
||||||
|
}
|
||||||
|
NetworkUtil.sendPayloadC2S(new ControlsModePayload(MidnightControlsConfig.controlsMode.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the HUD is enabled or not.
|
||||||
|
*
|
||||||
|
* @param enabled true if the HUD is enabled, else false
|
||||||
|
*/
|
||||||
|
public static void setHudEnabled(boolean enabled) {
|
||||||
|
MidnightControlsConfig.hudEnable = enabled;
|
||||||
|
hud.setVisible(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final MidnightControlsClient INSTANCE = new MidnightControlsClient();
|
||||||
|
/**
|
||||||
|
* Gets the midnightcontrols client instance.
|
||||||
|
*
|
||||||
|
* @return the midnightcontrols client instance
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static MidnightControlsClient get() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.google.common.collect.Maps;
|
||||||
|
import com.mojang.blaze3d.platform.GLX;
|
||||||
|
import eu.midnightdust.lib.config.MidnightConfig;
|
||||||
|
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.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.TouchMode;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.ChatScreen;
|
||||||
|
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||||
|
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 final String CONTROLLER = "controller";
|
||||||
|
public static final String TOUCH = "touch";
|
||||||
|
public static final String GAMEPLAY = "gameplay";
|
||||||
|
public static final String SCREENS = "screens";
|
||||||
|
public static final String VISUAL = "visual";
|
||||||
|
public static final String MISC = "misc";
|
||||||
|
public static boolean isEditing = false;
|
||||||
|
@Hidden @Entry public static int configVersion = 2;
|
||||||
|
// General
|
||||||
|
@Comment(category = CONTROLLER, centered = true, name="\uD83C\uDFAE General") public static Comment _general;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true;
|
||||||
|
// HUD
|
||||||
|
@Comment(category = VISUAL, centered = true, name="\uD83D\uDDB9 Hud") public static Comment _hud;
|
||||||
|
@Entry(category = VISUAL, name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true;
|
||||||
|
@Entry(category = VISUAL, name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT;
|
||||||
|
@Entry(category = VISUAL, name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT;
|
||||||
|
// Gameplay
|
||||||
|
@Comment(category = GAMEPLAY, centered = true, name="\uD83D\uDECB Comfort") public static Comment _comfort;
|
||||||
|
@Entry(category = GAMEPLAY, name = "Enable Hints") public static boolean enableHints = true;
|
||||||
|
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true;
|
||||||
|
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.double_tap_to_sprint") public static boolean doubleTapToSprint = true;
|
||||||
|
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.controller_toggle_sneak") public static boolean controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue();
|
||||||
|
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.controller_toggle_sprint") public static boolean controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue();
|
||||||
|
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra")
|
||||||
|
@Comment(category = GAMEPLAY, centered = true, name="✨ Extras") public static Comment _extras;
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra")
|
||||||
|
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fast_block_placing") public static boolean fastBlockPlacing = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra")
|
||||||
|
@Entry(category = GAMEPLAY, 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.
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra")
|
||||||
|
@Entry(category = GAMEPLAY, 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.
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra")
|
||||||
|
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra")
|
||||||
|
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra")
|
||||||
|
@Comment(category = VISUAL, centered = true, name="⊽ Reacharound") public static Comment _reacharoundOutline;
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra")
|
||||||
|
@Entry(category = VISUAL, name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true;
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra", requiredOption = "shouldRenderReacharoundOutline")
|
||||||
|
@Entry(category = VISUAL, name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff";
|
||||||
|
@Condition(requiredModId = "midnightcontrols-extra", requiredOption = "shouldRenderReacharoundOutline")
|
||||||
|
@Entry(category = VISUAL, name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102;
|
||||||
|
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDCF7 Camera Settings") public static Comment _cameraSettings;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double rotationSpeed = 35.0; //used for x-axis, name kept for compatibility
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.y_axis_rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double yAxisRotationSpeed = rotationSpeed;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.camera_mode") public static CameraMode cameraMode = CameraMode.FLAT;
|
||||||
|
@Comment(category = SCREENS, centered = true, name="\uD83D\uDDB1 Mouse Behaviour") public static Comment _mouseBehaviour;
|
||||||
|
@Entry(category = SCREENS, name = "midnightcontrols.menu.mouse_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double mouseSpeed = 25.0;
|
||||||
|
@Entry(category = SCREENS, name = "midnightcontrols.menu.joystick_as_mouse") public static boolean joystickAsMouse = false;
|
||||||
|
@Entry(category = SCREENS, name = "Mouse screens") public static List<String> mouseScreens = Lists.newArrayList("net.minecraft.client.gui.screen.advancement",
|
||||||
|
"net.minecraft.class_457", "net.minecraft.class_408", "net.minecraft.class_3872", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen",
|
||||||
|
"hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen",
|
||||||
|
"me.shedaniel.clothconfig2.gui.ClothConfigScreen", "com.mamiyaotaru.voxelmap.gui.GuiWaypoints", "com.mamiyaotaru.voxelmap.gui.GuiPersistentMap");
|
||||||
|
@Entry(category = SCREENS, name = "Arrow screens") public static List<String> arrowScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName());
|
||||||
|
@Entry(category = SCREENS, name = "WASD screens") public static List<String> wasdScreens = Lists.newArrayList("com.ultreon.devices.core.Laptop");
|
||||||
|
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDC40 Eye Tracking") public static Comment _eyeTracker;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.eye_tracker_deadzone", isSlider = true, min = 0, max = 0.4) public static double eyeTrackerDeadzone = 0.05;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false;
|
||||||
|
@Comment(category = SCREENS, centered = true, name="\uD83D\uDC46 Virtual Mouse") public static Comment _virtualMouse;
|
||||||
|
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false;
|
||||||
|
@Condition(requiredOption = "virtualMouse", visibleButLocked = true)
|
||||||
|
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
|
||||||
|
@Entry(category = SCREENS, name = "midnightcontrols.menu.hide_cursor") public static boolean hideNormalMouse = false;
|
||||||
|
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_keyboard") public static boolean virtualKeyboard = false;
|
||||||
|
@Entry(category = CONTROLLER, name = "Controller ID") @Hidden public static Object controllerID = 0;
|
||||||
|
@Entry(category = CONTROLLER, name = "2nd Controller ID") @Hidden public static Object secondControllerID = -1;
|
||||||
|
@Comment(category = TOUCH, centered = true, name="\uD83E\uDE84 Behaviour") public static Comment _touchBehaviour;
|
||||||
|
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_with_controller") public static boolean touchInControllerMode = false;
|
||||||
|
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double touchSpeed = 50.0;
|
||||||
|
@Entry(category = TOUCH, name = "midnightcontrols.menu.invert_touch") public static boolean invertTouch = false;
|
||||||
|
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_mode") public static TouchMode touchMode = TouchMode.CROSSHAIR;
|
||||||
|
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_break_delay", isSlider = true, min = 50, max = 500) public static int touchBreakDelay = 120;
|
||||||
|
@Comment(category = TOUCH, centered = true, name="\uD83D\uDCA1 Visuals") public static Comment _visuals;
|
||||||
|
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_transparency", isSlider = true, min = 0, max = 100) public static int touchTransparency = 75;
|
||||||
|
@Entry(category = TOUCH, name = "Touch Outline Color", isColor = true) public static String touchOutlineColorHex = "#ffffff";
|
||||||
|
@Entry(category = TOUCH, name = "Touch Outline Alpha", isSlider = true, min = 0, max = 255) public static int touchOutlineColorAlpha = 150;
|
||||||
|
@Comment(category = TOUCH, centered = true, name="\uD83E\uDDEA Advanced") public static Comment _advanced;
|
||||||
|
@Entry(category = TOUCH, name = "Screens with close button") public static List<String> closeButtonScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName(), AdvancementsScreen.class.getCanonicalName(), RingScreen.class.getCanonicalName());
|
||||||
|
@Entry(category = TOUCH, name = "Left Touch button bindings") public static List<String> leftTouchBinds = Lists.newArrayList("debug_screen", "screenshot","toggle_perspective");
|
||||||
|
@Entry(category = TOUCH, name = "Right Touch button bindings") public static List<String> rightTouchBinds = Lists.newArrayList("screenshot","toggle_perspective", "use");
|
||||||
|
|
||||||
|
@Entry @Hidden public static Map<String, String> BINDING = new HashMap<>();
|
||||||
|
|
||||||
|
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
|
||||||
|
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDD79 Max Analog Stick Values") public static Comment _maxAnalogValues;
|
||||||
|
@Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = 1;
|
||||||
|
@Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = 1;
|
||||||
|
@Entry(category = CONTROLLER, name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = 1;
|
||||||
|
@Entry(category = CONTROLLER, name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = 1;
|
||||||
|
@Comment(category = CONTROLLER, centered = true, name="☠ Dead Zones") public static Comment _deadZones;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.right_dead_zone", isSlider = true, min = 0.05, max = 1) public static double rightDeadZone = 0.25;
|
||||||
|
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.25;
|
||||||
|
@Entry(category = CONTROLLER, name = "Trigger Dead-Zone", isSlider = true, min = 0.05, max = 1) public static double triggerDeadZone = 0.1;
|
||||||
|
@Comment(category = CONTROLLER, centered = true, name="☆ Other Options") public static Comment _otherOptions;
|
||||||
|
@Entry(category = CONTROLLER, name = "Trigger button fix") public static boolean triggerFix = true;
|
||||||
|
@Entry(category = CONTROLLER, name = "Excluded Controllers (Name Regex)") public static List<String> excludedControllers = Lists.newArrayList(".*(Keyboard)$", ".*(Touchpad)$", ".*(Pen)$", ".*(Finger)$");
|
||||||
|
@Comment(category = SCREENS, centered = true, name="\uD83D\uDD27 UI Modifications") public static Comment _uiMods;
|
||||||
|
@Entry(category = SCREENS, name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false;
|
||||||
|
@Entry(category = SCREENS, name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true;
|
||||||
|
@Entry(category = MISC, name = "midnightcontrols.menu.virtual_keyboard_layout") public static String keyboardLayout = "en_US:qwerty";
|
||||||
|
@Entry(category = MISC, name = "Debug") public static boolean debug = false;
|
||||||
|
@Entry(category = MISC, name = "Excluded Keybindings") public static List<String> excludedKeybindings = Lists.newArrayList("key.forward", "key.left", "key.back", "key.right", "key.jump", "key.sneak", "key.sprint", "key.inventory",
|
||||||
|
"key.swapOffhand", "key.drop", "key.use", "key.attack", "key.chat", "key.playerlist", "key.screenshot", "key.togglePerspective", "key.smoothCamera", "key.fullscreen", "key.saveToolbarActivator", "key.loadToolbarActivator",
|
||||||
|
"key.pickItem", "key.hotbar.1", "key.hotbar.2", "key.hotbar.3", "key.hotbar.4", "key.hotbar.5", "key.hotbar.6", "key.hotbar.7", "key.hotbar.8", "key.hotbar.9");
|
||||||
|
@Entry(category = MISC, name = "Ring Bindings (WIP)") @Hidden public static List<String> ringBindings = new ArrayList<>();
|
||||||
|
@Entry(category = MISC, name = "Ignored Unbound Keys") public static List<String> ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab");
|
||||||
|
@Entry @Hidden public static Map<String, Map<String, String>> controllerBindingProfiles = new HashMap<>();
|
||||||
|
private static Map<String, String> currentBindingProfile = new HashMap<>();
|
||||||
|
private static Controller prevController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the configuration
|
||||||
|
*/
|
||||||
|
public static void load() {
|
||||||
|
MidnightControlsConfig.init(MidnightControlsConstants.NAMESPACE, MidnightControlsConfig.class);
|
||||||
|
MidnightControls.log("Configuration loaded.");
|
||||||
|
// Controller controls.
|
||||||
|
InputManager.loadButtonBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the configuration.
|
||||||
|
*/
|
||||||
|
public static void save() {
|
||||||
|
MidnightControlsConfig.write(MidnightControlsConstants.NAMESPACE);
|
||||||
|
MidnightControls.log("Configuration saved.");
|
||||||
|
MidnightControlsFeature.refreshEnabled();
|
||||||
|
}
|
||||||
|
public static void updateBindingsForController(Controller controller) {
|
||||||
|
if (controller.isConnected() && controller.isGamepad() && controllerBindingProfiles.containsKey(controller.getGuid()))
|
||||||
|
currentBindingProfile = controllerBindingProfiles.get(controller.getGuid());
|
||||||
|
else currentBindingProfile = Maps.newHashMap(BINDING);
|
||||||
|
InputManager.loadButtonBindings();
|
||||||
|
}
|
||||||
|
public static Map<String, String> getBindingsForController() {
|
||||||
|
return currentBindingProfile;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
if (prevController != controller) updateBindingsForController(controller);
|
||||||
|
prevController = controller;
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the used controller.
|
||||||
|
*
|
||||||
|
* @param controller the controller
|
||||||
|
*/
|
||||||
|
public static void setController(Controller controller) {
|
||||||
|
MidnightControlsConfig.controllerID = controller.id();
|
||||||
|
MidnightControlsConfig.write(MidnightControlsConstants.NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
return switch (axis) {
|
||||||
|
case GLFW_GAMEPAD_AXIS_LEFT_X -> MidnightControlsConfig.maxAnalogValueLeftX;
|
||||||
|
case GLFW_GAMEPAD_AXIS_LEFT_Y -> MidnightControlsConfig.maxAnalogValueLeftY;
|
||||||
|
case GLFW_GAMEPAD_AXIS_RIGHT_X -> MidnightControlsConfig.maxAnalogValueRightX;
|
||||||
|
default -> MidnightControlsConfig.maxAnalogValueRightY;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAxisMaxValue(int axis, double value) {
|
||||||
|
switch (axis) {
|
||||||
|
case GLFW_GAMEPAD_AXIS_LEFT_X -> MidnightControlsConfig.maxAnalogValueLeftX = value;
|
||||||
|
case GLFW_GAMEPAD_AXIS_LEFT_Y -> MidnightControlsConfig.maxAnalogValueLeftY = value;
|
||||||
|
case GLFW_GAMEPAD_AXIS_RIGHT_X -> MidnightControlsConfig.maxAnalogValueRightX = value;
|
||||||
|
default -> MidnightControlsConfig.maxAnalogValueRightY = 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 = getBindingsForController().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) {
|
||||||
|
MidnightControls.warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
||||||
|
MidnightControlsConfig.setButtonBinding(button, new int[]{-1});
|
||||||
|
}
|
||||||
|
|
||||||
|
button.setButton(buttons);
|
||||||
|
} catch (Exception e) {
|
||||||
|
MidnightControls.warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
||||||
|
setButtonBinding(button, button.getButton());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkValidity(@NotNull ButtonBinding binding, @NotNull String input, String group) {
|
||||||
|
if (group == null) {
|
||||||
|
MidnightControls.warn("Malformed config value \"" + input + "\" for binding \"" + binding.getName() + "\".");
|
||||||
|
setButtonBinding(binding, binding.getButton());
|
||||||
|
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);
|
||||||
|
getBindingsForController().put("controller.controls." + binding.getName(), binding.getButtonCode());
|
||||||
|
if (controllerBindingProfiles.containsKey(getController().getGuid())) controllerBindingProfiles.get(getController().getGuid()).put("controller.controls." + binding.getName(), binding.getButtonCode());
|
||||||
|
else BINDING.put("controller.controls." + binding.getName(), binding.getButtonCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isBackButton(int btn, boolean isBtn, ButtonState state) {
|
||||||
|
if (!isBtn && state == ButtonState.NONE)
|
||||||
|
return false;
|
||||||
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false) == ButtonBinding.axisAsButton(btn, state == ButtonState.PRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isForwardButton(int btn, boolean isBtn, ButtonState state) {
|
||||||
|
if (!isBtn && state == ButtonState.NONE)
|
||||||
|
return false;
|
||||||
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true) == ButtonBinding.axisAsButton(btn, state == ButtonState.PRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isLeftButton(int btn, boolean isBtn, ButtonState state) {
|
||||||
|
if (!isBtn && state == ButtonState.NONE)
|
||||||
|
return false;
|
||||||
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false) == ButtonBinding.axisAsButton(btn, state == ButtonState.PRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRightButton(int btn, boolean isBtn, ButtonState state) {
|
||||||
|
if (!isBtn && state == ButtonState.NONE)
|
||||||
|
return false;
|
||||||
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true) == ButtonBinding.axisAsButton(btn, state == ButtonState.PRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue();
|
||||||
|
controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue();
|
||||||
|
fastBlockPlacing = false;
|
||||||
|
flyDrifting = true;
|
||||||
|
verticalFlyDrifting = true;
|
||||||
|
horizontalReacharound = false;
|
||||||
|
verticalReacharound = false;
|
||||||
|
shouldRenderReacharoundOutline = true;
|
||||||
|
reacharoundOutlineColorHex = "#ffffff";
|
||||||
|
reacharoundOutlineColorAlpha = 102;
|
||||||
|
rightDeadZone = 0.25;
|
||||||
|
leftDeadZone = 0.25;
|
||||||
|
invertRightYAxis = false;
|
||||||
|
invertRightXAxis = false;
|
||||||
|
rotationSpeed = 35.0;
|
||||||
|
yAxisRotationSpeed = rotationSpeed;
|
||||||
|
mouseSpeed = 25.0;
|
||||||
|
unfocusedInput = false;
|
||||||
|
virtualMouse = false;
|
||||||
|
virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
|
||||||
|
virtualKeyboard = false;
|
||||||
|
controllerID = 0;
|
||||||
|
secondControllerID = -1;
|
||||||
|
controllerType = ControllerType.DEFAULT;
|
||||||
|
mouseScreens = Lists.newArrayList("net.minecraft.client.gui.screen.advancement", "net.minecraft.class_457", "net.minecraft.class_408", "net.minecraft.class_3872", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen", "me.shedaniel.clothconfig2.gui.ClothConfigScreen", "com.mamiyaotaru.voxelmap.gui.GuiWaypoints", "com.mamiyaotaru.voxelmap.gui.GuiPersistentMap");
|
||||||
|
BINDING = new HashMap<>();
|
||||||
|
maxAnalogValueLeftX = 1;
|
||||||
|
maxAnalogValueLeftY = 1;
|
||||||
|
maxAnalogValueRightX = 1;
|
||||||
|
maxAnalogValueRightY = 1;
|
||||||
|
triggerFix = true;
|
||||||
|
enableHints = true;
|
||||||
|
shortcutInControls = true;
|
||||||
|
ringBindings = new ArrayList<>();
|
||||||
|
ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab");
|
||||||
|
controllerBindingProfiles = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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") && GLX._getCpuInfo().contains("AMD Custom APU")) return ControllerType.STEAM_DECK;
|
||||||
|
else if (controller.contains("steam")) return ControllerType.STEAM_CONTROLLER;
|
||||||
|
else if (controller.contains("dualsense") || controller.contains("ps5")) return ControllerType.DUALSENSE;
|
||||||
|
else if (controller.contains("dualshock") || controller.contains("ps4") || controller.contains("sony")) return ControllerType.DUALSHOCK;
|
||||||
|
else if (controller.contains("switch") || controller.contains("joy-con") || controller.contains("wii") || controller.contains("nintendo")) return ControllerType.SWITCH;
|
||||||
|
else if (controller.contains("ouya")) return ControllerType.OUYA;
|
||||||
|
else return ControllerType.DEFAULT;
|
||||||
|
}
|
||||||
|
public static boolean doMixedInput() {
|
||||||
|
return touchInControllerMode && controlsMode == ControlsMode.CONTROLLER;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.KeyboardLayoutManager;
|
||||||
|
import net.minecraft.resource.ResourceManager;
|
||||||
|
import net.minecraft.resource.SynchronousResourceReloader;
|
||||||
|
|
||||||
|
public class MidnightControlsReloadListener implements SynchronousResourceReloader {
|
||||||
|
public static final MidnightControlsReloadListener INSTANCE = new MidnightControlsReloadListener();
|
||||||
|
|
||||||
|
private MidnightControlsReloadListener() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload(ResourceManager manager) {
|
||||||
|
manager.findResources("keyboard_layouts", path -> path.toString().startsWith("midnightcontrols") && path.toString().endsWith(".json")).forEach(KeyboardLayoutManager::loadLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,819 @@
|
|||||||
|
/*
|
||||||
|
* 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.ImmutableSet;
|
||||||
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.LibGuiCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.YACLCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.InventoryUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.storage.ButtonStorage;
|
||||||
|
import net.minecraft.client.gui.screen.option.KeybindsScreen;
|
||||||
|
import net.minecraft.client.gui.widget.EntryListWidget;
|
||||||
|
import net.minecraft.client.gui.widget.PressableWidget;
|
||||||
|
import net.minecraft.client.gui.widget.SliderWidget;
|
||||||
|
import net.minecraft.entity.vehicle.BoatEntity;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.container.SpruceEntryListWidget;
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
|
||||||
|
import org.thinkingstudio.obsidianui.navigation.NavigationDirection;
|
||||||
|
import org.thinkingstudio.obsidianui.screen.SpruceScreen;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.AbstractSprucePressableButtonWidget;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.SpruceElement;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.SpruceLabelWidget;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.container.SpruceParentWidget;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.Element;
|
||||||
|
import net.minecraft.client.gui.ParentElement;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
||||||
|
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.MerchantScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.StonecutterScreen;
|
||||||
|
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
|
||||||
|
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
|
||||||
|
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
||||||
|
import net.minecraft.text.TranslatableTextContent;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.lwjgl.glfw.GLFWGamepadState;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the midnightcontrols' input handler.
|
||||||
|
*
|
||||||
|
* @author Motschen, LambdAurora
|
||||||
|
* @version 1.10.0
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class MidnightInput {
|
||||||
|
public static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
||||||
|
// Cooldowns
|
||||||
|
public int actionGuiCooldown = 0;
|
||||||
|
public int joystickCooldown = 0;
|
||||||
|
public boolean ignoreNextARelease = false;
|
||||||
|
public boolean ignoreNextXRelease = false;
|
||||||
|
private double targetYaw = 0.0;
|
||||||
|
private double targetPitch = 0.0;
|
||||||
|
private float prevXAxis = 0.f;
|
||||||
|
private float prevYAxis = 0.f;
|
||||||
|
public float mouseSpeedX = 0.f;
|
||||||
|
public float mouseSpeedY = 0.f;
|
||||||
|
public int inventoryInteractionCooldown = 0;
|
||||||
|
public int screenCloseCooldown = 0;
|
||||||
|
|
||||||
|
private ControllerControlsWidget controlsInput = null;
|
||||||
|
|
||||||
|
public MidnightInput() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called every Minecraft tick.
|
||||||
|
*/
|
||||||
|
public void tick() {
|
||||||
|
this.targetYaw = 0.F;
|
||||||
|
this.targetPitch = 0.F;
|
||||||
|
|
||||||
|
// Handles the key bindings.
|
||||||
|
if (MidnightControlsClient.BINDING_LOOK_UP.isPressed()) {
|
||||||
|
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_Y, -0.8F, 0d));
|
||||||
|
} else if (MidnightControlsClient.BINDING_LOOK_DOWN.isPressed()) {
|
||||||
|
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 0d));
|
||||||
|
}
|
||||||
|
if (MidnightControlsClient.BINDING_LOOK_LEFT.isPressed()) {
|
||||||
|
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_X, -0.8F, 0d));
|
||||||
|
} else if (MidnightControlsClient.BINDING_LOOK_RIGHT.isPressed()) {
|
||||||
|
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 0d));
|
||||||
|
}
|
||||||
|
|
||||||
|
InputManager.INPUT_MANAGER.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called every Minecraft tick for controller input update.
|
||||||
|
*/
|
||||||
|
public void tickController() {
|
||||||
|
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.
|
||||||
|
if (this.actionGuiCooldown > 0)
|
||||||
|
--this.actionGuiCooldown;
|
||||||
|
if (this.screenCloseCooldown > 0)
|
||||||
|
--this.screenCloseCooldown;
|
||||||
|
if (this.joystickCooldown > 0)
|
||||||
|
--this.joystickCooldown;
|
||||||
|
|
||||||
|
InputManager.updateStates();
|
||||||
|
|
||||||
|
var controller = MidnightControlsConfig.getController();
|
||||||
|
|
||||||
|
if (controller.isConnected()) {
|
||||||
|
var state = controller.getState();
|
||||||
|
this.fetchButtonInput(state, false);
|
||||||
|
this.fetchTriggerInput(state, false);
|
||||||
|
this.fetchJoystickInput(state, false, false);
|
||||||
|
}
|
||||||
|
MidnightControlsConfig.getSecondController().filter(Controller::isConnected)
|
||||||
|
.ifPresent(joycon -> {
|
||||||
|
var state = joycon.getState();
|
||||||
|
this.fetchButtonInput(state, true);
|
||||||
|
this.fetchTriggerInput(state, true);
|
||||||
|
this.fetchJoystickInput(state, true, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
boolean allowInput = this.controlsInput == null || this.controlsInput.focusedBinding == null;
|
||||||
|
|
||||||
|
if (allowInput)
|
||||||
|
InputManager.updateBindings();
|
||||||
|
|
||||||
|
if (this.controlsInput != null) {
|
||||||
|
InputManager.STATES.forEach((num, button) -> {
|
||||||
|
if (button.isPressed()) System.out.println(num);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
|
||||||
|
if (MidnightControlsConfig.debug) MidnightControls.log("Starting MidnightInput Button Edit");
|
||||||
|
if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) {
|
||||||
|
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
||||||
|
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
||||||
|
buttons[i] = this.controlsInput.currentButtons.get(i);
|
||||||
|
this.controlsInput.finishBindingEdit(buttons);
|
||||||
|
this.controlsInput = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.inventoryInteractionCooldown > 0)
|
||||||
|
this.inventoryInteractionCooldown--;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This method is called 1000 times a second for smooth camera input
|
||||||
|
*/
|
||||||
|
public void tickCameraStick() {
|
||||||
|
var controller = MidnightControlsConfig.getController();
|
||||||
|
|
||||||
|
if (controller.isConnected()) {
|
||||||
|
this.fetchJoystickInput(controller.getState(), false, true);
|
||||||
|
}
|
||||||
|
MidnightControlsConfig.getSecondController().filter(Controller::isConnected)
|
||||||
|
.ifPresent(joycon -> this.fetchJoystickInput(joycon.getState(), true, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called before the screen is rendered.
|
||||||
|
*
|
||||||
|
* @param screen the screen to render
|
||||||
|
*/
|
||||||
|
public void onPreRenderScreen(@NotNull Screen screen) {
|
||||||
|
if (!isScreenInteractive(screen)) {
|
||||||
|
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called to update the camera
|
||||||
|
*/
|
||||||
|
public void updateCamera() {
|
||||||
|
if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var player = client.player;
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.targetYaw != 0.f || this.targetPitch != 0.f) {
|
||||||
|
float rotationYaw = (float) (client.player.lastYaw + (this.targetYaw * 0.175));
|
||||||
|
float rotationPitch = (float) (client.player.lastPitch + (this.targetPitch * 0.175));
|
||||||
|
client.player.lastYaw = rotationYaw;
|
||||||
|
client.player.lastPitch = MathHelper.clamp(rotationPitch, -90.f, 90.f);
|
||||||
|
client.player.setYaw(rotationYaw);
|
||||||
|
client.player.setPitch(MathHelper.clamp(rotationPitch, -90.f, 90.f));
|
||||||
|
if (client.player.isRiding() && client.player.getVehicle() != null) {
|
||||||
|
client.player.getVehicle().onPassengerLookAround(client.player);
|
||||||
|
}
|
||||||
|
client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when a Screen is opened.
|
||||||
|
*
|
||||||
|
* @param windowWidth the window width
|
||||||
|
* @param windowHeight the window height
|
||||||
|
*/
|
||||||
|
public void onScreenOpen(int windowWidth, int windowHeight) {
|
||||||
|
if (client.currentScreen == null) {
|
||||||
|
this.mouseSpeedX = this.mouseSpeedY = 0.0F;
|
||||||
|
InputManager.INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight);
|
||||||
|
} else if (isScreenInteractive(client.currentScreen) && MidnightControlsConfig.virtualMouse) {
|
||||||
|
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), 0, 0);
|
||||||
|
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
||||||
|
}
|
||||||
|
this.inventoryInteractionCooldown = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beginControlsInput(ControllerControlsWidget widget) {
|
||||||
|
this.controlsInput = widget;
|
||||||
|
if (widget != null) {
|
||||||
|
this.controlsInput.currentButtons.clear();
|
||||||
|
this.controlsInput.waiting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchButtonInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
||||||
|
var buffer = gamepadState.buttons();
|
||||||
|
for (int i = 0; i < buffer.limit(); i++) {
|
||||||
|
int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||||
|
boolean pressed = buffer.get() == (byte) 1;
|
||||||
|
var state = ButtonState.NONE;
|
||||||
|
var previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
|
||||||
|
|
||||||
|
if (pressed != previousState.isPressed()) {
|
||||||
|
state = pressed ? ButtonState.PRESS : ButtonState.RELEASE;
|
||||||
|
this.handleButton(ButtonStorage.of(btn, state));
|
||||||
|
if (pressed)
|
||||||
|
BUTTON_COOLDOWNS.put(btn, 5);
|
||||||
|
} else if (pressed) {
|
||||||
|
state = ButtonState.REPEAT;
|
||||||
|
if (BUTTON_COOLDOWNS.getOrDefault(btn, 0) == 0) {
|
||||||
|
BUTTON_COOLDOWNS.put(btn, 5);
|
||||||
|
this.handleButton(ButtonStorage.of(btn, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InputManager.STATES.put(btn, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil();
|
||||||
|
|
||||||
|
private void fetchJoystickInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon, boolean cameraTick) {
|
||||||
|
var buffer = gamepadState.axes();
|
||||||
|
|
||||||
|
polarUtil.calculate(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X), buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y), 1, MidnightControlsConfig.leftDeadZone);
|
||||||
|
float leftX = polarUtil.polarX;
|
||||||
|
float leftY = polarUtil.polarY;
|
||||||
|
polarUtil.calculate(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X), buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y), 1, MidnightControlsConfig.rightDeadZone);
|
||||||
|
float rightX = polarUtil.polarX;
|
||||||
|
float rightY = polarUtil.polarY;
|
||||||
|
|
||||||
|
boolean isRadialMenu = client.currentScreen instanceof RingScreen || (PlatformFunctions.isModLoaded("emotecraft") && EmotecraftCompat.isEmotecraftScreen(client.currentScreen));
|
||||||
|
|
||||||
|
if (!isRadialMenu) {
|
||||||
|
for (int i = cameraTick ? GLFW_GAMEPAD_AXIS_RIGHT_X : 0; i < (cameraTick ? GLFW_GAMEPAD_AXIS_LEFT_TRIGGER : GLFW_GAMEPAD_AXIS_RIGHT_X); i++) {
|
||||||
|
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||||
|
float value = buffer.get(i);
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case GLFW_GAMEPAD_AXIS_LEFT_X -> {
|
||||||
|
if (MidnightControlsConfig.analogMovement) value = leftX;
|
||||||
|
}
|
||||||
|
case GLFW_GAMEPAD_AXIS_LEFT_Y -> {
|
||||||
|
if (MidnightControlsConfig.analogMovement) value = leftY;
|
||||||
|
}
|
||||||
|
case GLFW_GAMEPAD_AXIS_RIGHT_X -> value = rightX;
|
||||||
|
case GLFW_GAMEPAD_AXIS_RIGHT_Y -> value = rightY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y)
|
||||||
|
value *= -1.0F;
|
||||||
|
|
||||||
|
this.handleJoystickAxis(AxisStorage.of(axis, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
boolean leftStickActive = leftX != 0 || leftY != 0;
|
||||||
|
handleRadialMenu(leftStickActive ? leftX : rightX, leftStickActive ? leftY : rightY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchTriggerInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
||||||
|
var buffer = gamepadState.axes();
|
||||||
|
|
||||||
|
for (int i = GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; i <= GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER; i++) {
|
||||||
|
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||||
|
float value = buffer.get(i);
|
||||||
|
|
||||||
|
this.handleTriggerAxis(AxisStorage.of(axis, value, MidnightControlsConfig.triggerDeadZone));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleButton(ButtonStorage storage) {
|
||||||
|
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
||||||
|
if (storage.state == ButtonState.PRESS && !this.controlsInput.currentButtons.contains(storage.button)) {
|
||||||
|
this.controlsInput.currentButtons.add(storage.button);
|
||||||
|
|
||||||
|
var buttons = new int[this.controlsInput.currentButtons.size()];
|
||||||
|
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
||||||
|
buttons[i] = this.controlsInput.currentButtons.get(i);
|
||||||
|
this.controlsInput.focusedBinding.setButton(buttons);
|
||||||
|
|
||||||
|
this.controlsInput.waiting = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.currentScreen != null && storage.state.isPressed() && storage.button == GLFW_GAMEPAD_BUTTON_Y &&
|
||||||
|
MidnightControlsConfig.arrowScreens.contains(client.currentScreen.getClass().getCanonicalName())) {
|
||||||
|
pressKeyboardKey(client, GLFW.GLFW_KEY_ENTER);
|
||||||
|
this.screenCloseCooldown = 5;
|
||||||
|
}
|
||||||
|
else if (storage.state.isPressed()) {
|
||||||
|
if (client.currentScreen != null && storage.isDpad() && this.actionGuiCooldown == 0) {
|
||||||
|
switch (storage.button) {
|
||||||
|
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||||
|
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||||
|
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> this.handleLeftRight(client.currentScreen, false);
|
||||||
|
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> this.handleLeftRight(client.currentScreen, true);
|
||||||
|
}
|
||||||
|
if (MidnightControlsConfig.wasdScreens.contains(client.currentScreen.getClass().getCanonicalName())) {
|
||||||
|
switch (storage.button) {
|
||||||
|
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> pressKeyboardKey(client, GLFW.GLFW_KEY_W);
|
||||||
|
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> pressKeyboardKey(client, GLFW.GLFW_KEY_S);
|
||||||
|
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> pressKeyboardKey(client, GLFW.GLFW_KEY_A);
|
||||||
|
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> pressKeyboardKey(client, GLFW.GLFW_KEY_D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
|
||||||
|
if (this.actionGuiCooldown == 0) {
|
||||||
|
var focused = client.currentScreen.getFocused();
|
||||||
|
if (focused != null && isScreenInteractive(client.currentScreen)) {
|
||||||
|
if (this.handleAButton(client.currentScreen, focused)) {
|
||||||
|
this.actionGuiCooldown = 5; // Set the cooldown to 5 ticks to avoid unintended button presses.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PlatformFunctions.isModLoaded("libgui")) LibGuiCompat.handlePress(client.currentScreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storage.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 && client.currentScreen != null) {
|
||||||
|
var accessor = (MouseAccessor) client.mouse;
|
||||||
|
accessor.midnightcontrols$onCursorPos(client.getWindow().getHandle(), client.mouse.getX(), client.mouse.getY());
|
||||||
|
switch (storage.state) {
|
||||||
|
// Button pressed
|
||||||
|
case PRESS -> accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 1, 0);
|
||||||
|
case RELEASE -> { // Button released
|
||||||
|
accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 0, 0);
|
||||||
|
client.currentScreen.setDragging(false);
|
||||||
|
}
|
||||||
|
case REPEAT -> client.currentScreen.setDragging(true); // Button held down / dragging
|
||||||
|
}
|
||||||
|
this.screenCloseCooldown = 5;
|
||||||
|
} else {
|
||||||
|
this.ignoreNextARelease = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_X && client.currentScreen != null && !isScreenInteractive(client.currentScreen)
|
||||||
|
&& this.actionGuiCooldown == 0) {
|
||||||
|
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();
|
||||||
|
if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt(
|
||||||
|
mouseX, mouseY) != null) return;
|
||||||
|
if (!this.ignoreNextXRelease && client.currentScreen != null) {
|
||||||
|
if (storage.state == ButtonState.PRESS) client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2);
|
||||||
|
else if (storage.state == ButtonState.RELEASE) client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2);
|
||||||
|
this.screenCloseCooldown = 5;
|
||||||
|
} else {
|
||||||
|
this.ignoreNextXRelease = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void handleTriggerAxis(AxisStorage storage) {
|
||||||
|
storage.setupButtonStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleJoystickAxis(AxisStorage storage) {
|
||||||
|
storage.setupButtonStates();
|
||||||
|
|
||||||
|
this.handleJoystickMovement(storage);
|
||||||
|
|
||||||
|
if (this.handleScreenScrolling(client.currentScreen, storage)) return;
|
||||||
|
|
||||||
|
storage.absValue = (float) MathHelper.clamp(storage.absValue / MidnightControlsConfig.getAxisMaxValue(storage.axis), 0.f, 1.f);
|
||||||
|
if (client.currentScreen == null) {
|
||||||
|
// Handles the look direction.
|
||||||
|
this.handleLook(storage);
|
||||||
|
} else {
|
||||||
|
boolean allowMouseControl = true;
|
||||||
|
|
||||||
|
if (this.actionGuiCooldown == 0 && MidnightControlsConfig.isMovementAxis(storage.axis) && isScreenInteractive(client.currentScreen)) {
|
||||||
|
if (MidnightControlsConfig.isForwardButton(storage.axis, false, storage.buttonState)) {
|
||||||
|
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||||
|
} else if (MidnightControlsConfig.isBackButton(storage.axis, false, storage.buttonState)) {
|
||||||
|
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||||
|
} else if (MidnightControlsConfig.isLeftButton(storage.axis, false, storage.buttonState)) {
|
||||||
|
allowMouseControl = this.handleLeftRight(client.currentScreen, false);
|
||||||
|
} else if (MidnightControlsConfig.isRightButton(storage.axis, false, storage.buttonState)) {
|
||||||
|
allowMouseControl = this.handleLeftRight(client.currentScreen, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float movementX = 0.f;
|
||||||
|
float movementY = 0.f;
|
||||||
|
|
||||||
|
if (MidnightControlsConfig.isBackButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
||||||
|
movementY = storage.absValue;
|
||||||
|
} else if (MidnightControlsConfig.isForwardButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
||||||
|
movementY = -storage.absValue;
|
||||||
|
} else if (MidnightControlsConfig.isLeftButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
||||||
|
movementX = -storage.absValue;
|
||||||
|
} else if (MidnightControlsConfig.isRightButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
||||||
|
movementX = storage.absValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.currentScreen != null && allowMouseControl) {
|
||||||
|
boolean moving = movementY != 0 || movementX != 0;
|
||||||
|
if (moving) {
|
||||||
|
/*
|
||||||
|
Updates the target mouse position when the initial movement stick movement is detected.
|
||||||
|
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) < storage.deadZone && Math.abs(prevYAxis) < storage.deadZone) {
|
||||||
|
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mouseSpeedX = movementX;
|
||||||
|
this.mouseSpeedY = movementY;
|
||||||
|
} else {
|
||||||
|
this.mouseSpeedX = 0.f;
|
||||||
|
this.mouseSpeedY = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(this.mouseSpeedX) >= .05f || Math.abs(this.mouseSpeedY) >= .05f) {
|
||||||
|
InputManager.queueMoveMousePosition(
|
||||||
|
this.mouseSpeedX * MidnightControlsConfig.mouseSpeed,
|
||||||
|
this.mouseSpeedY * MidnightControlsConfig.mouseSpeed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryUtil.moveMouseToClosestSlot(client.currentScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.prevXAxis = movementX;
|
||||||
|
this.prevYAxis = movementY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleJoystickMovement(AxisStorage storage) {
|
||||||
|
float axisValue = storage.absValue;
|
||||||
|
if (!MidnightControlsConfig.analogMovement || (client.player != null && client.player.getVehicle() instanceof BoatEntity)) {
|
||||||
|
axisValue = (float) (storage.absValue - storage.deadZone);
|
||||||
|
axisValue /= (float) (1.0 - storage.deadZone);
|
||||||
|
axisValue *= (float) storage.deadZone;
|
||||||
|
}
|
||||||
|
axisValue = (float) Math.min(axisValue / MidnightControlsConfig.getAxisMaxValue(storage.axis), 1);
|
||||||
|
if (AxisStorage.isLeftAxis(storage.axis)) MidnightControlsCompat.handleMovement(storage, axisValue);
|
||||||
|
InputManager.BUTTON_VALUES.put(storage.getButtonId(true), storage.polarity == AxisStorage.Polarity.PLUS ? axisValue : 0.f);
|
||||||
|
InputManager.BUTTON_VALUES.put(storage.getButtonId(false), storage.polarity == AxisStorage.Polarity.MINUS ? axisValue : 0.f);
|
||||||
|
storage.absValue = axisValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleScreenScrolling(Screen screen, AxisStorage storage) {
|
||||||
|
if (screen == null) return false;
|
||||||
|
// @TODO allow rebinding to left stick
|
||||||
|
int preferredAxis = true ? GLFW_GAMEPAD_AXIS_RIGHT_Y : GLFW_GAMEPAD_AXIS_LEFT_Y;
|
||||||
|
|
||||||
|
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
||||||
|
if (storage.buttonState != ButtonState.NONE && !this.controlsInput.currentButtons.contains(storage.getButtonId(storage.buttonState == ButtonState.PRESS))) {
|
||||||
|
|
||||||
|
this.controlsInput.currentButtons.add(storage.getButtonId(storage.buttonState == ButtonState.PRESS));
|
||||||
|
|
||||||
|
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
||||||
|
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
||||||
|
buttons[i] = this.controlsInput.currentButtons.get(i);
|
||||||
|
this.controlsInput.focusedBinding.setButton(buttons);
|
||||||
|
|
||||||
|
this.controlsInput.waiting = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (storage.absValue >= storage.deadZone) {
|
||||||
|
if (screen instanceof CreativeInventoryScreen creativeInventoryScreen) {
|
||||||
|
if (storage.axis == preferredAxis) {
|
||||||
|
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
||||||
|
if (accessor.midnightcontrols$hasScrollbar() && storage.absValue >= storage.deadZone) {
|
||||||
|
creativeInventoryScreen.mouseScrolled(0.0, 0.0, 0, -(storage.value * 0.0175f));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (screen instanceof AdvancementsScreen advancementsScreen) {
|
||||||
|
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X || storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||||
|
var accessor = (AdvancementsScreenAccessor) advancementsScreen;
|
||||||
|
AdvancementTab tab = accessor.getSelectedTab();
|
||||||
|
tab.move(storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X ? -storage.value * 1.0 : 0.0, storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y ? -storage.value * 5.0 : 0.0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (screen != null) {
|
||||||
|
if (storage.axis == preferredAxis && !handleListWidgetScrolling(screen.children(), storage.value)) {
|
||||||
|
try {
|
||||||
|
screen.mouseScrolled(0.0, 0.0, 0, -(storage.value * 0.0175f));
|
||||||
|
} catch (NullPointerException ignored) {}
|
||||||
|
} else if (isScreenInteractive(screen)) {
|
||||||
|
if (joystickCooldown == 0) {
|
||||||
|
switch (storage.axis) {
|
||||||
|
case GLFW_GAMEPAD_AXIS_LEFT_Y -> {
|
||||||
|
this.changeFocus(screen, storage.value > 0 ? NavigationDirection.UP : NavigationDirection.DOWN);
|
||||||
|
joystickCooldown = 4;
|
||||||
|
}
|
||||||
|
case GLFW_GAMEPAD_AXIS_LEFT_X -> {
|
||||||
|
this.handleLeftRight(screen, storage.value > 0);
|
||||||
|
joystickCooldown = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public void handleRadialMenu(float x, float y) {
|
||||||
|
int index = -1;
|
||||||
|
float border = 0.3f;
|
||||||
|
if (x < -border) {
|
||||||
|
index = 3;
|
||||||
|
if (y < -border) index = 0;
|
||||||
|
else if (y > border) index = 5;
|
||||||
|
} else if (x > border) {
|
||||||
|
index = 4;
|
||||||
|
if (y < -border) index = 2;
|
||||||
|
else if (y > border) index = 7;
|
||||||
|
} else {
|
||||||
|
if (y < -border) index = 1;
|
||||||
|
else if (y > border) index = 6;
|
||||||
|
}
|
||||||
|
if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index;
|
||||||
|
if (PlatformFunctions.isModLoaded("emotecraft") && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleListWidgetScrolling(List<? extends Element> children, float value) {
|
||||||
|
return children.stream().filter(element -> element instanceof SpruceEntryListWidget)
|
||||||
|
.map(element -> (SpruceEntryListWidget<?>) element)
|
||||||
|
.filter(AbstractSpruceWidget::isFocusedOrHovered)
|
||||||
|
.anyMatch(element -> {
|
||||||
|
element.mouseScrolled(0.0, 0.0, 0, -value);
|
||||||
|
return true;
|
||||||
|
}) ||
|
||||||
|
children.stream().filter(element -> element instanceof EntryListWidget)
|
||||||
|
.map(element -> (EntryListWidget<?>) element)
|
||||||
|
.filter(element -> element.getType().isFocused())
|
||||||
|
.anyMatch(element -> {
|
||||||
|
element.mouseScrolled(0.0, 0.0, 0, -value);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
|
||||||
|
if (focused instanceof PressableWidget widget) {
|
||||||
|
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
|
||||||
|
widget.onPress();
|
||||||
|
return true;
|
||||||
|
} else if (focused instanceof AbstractSprucePressableButtonWidget widget) {
|
||||||
|
widget.playDownSound();
|
||||||
|
widget.onPress();
|
||||||
|
return true;
|
||||||
|
} else if (focused instanceof SpruceLabelWidget labelWidget) {
|
||||||
|
labelWidget.onPress();
|
||||||
|
return true;
|
||||||
|
} else if (focused instanceof WorldListWidget list) {
|
||||||
|
list.getSelectedAsOptional().ifPresent(WorldListWidget.WorldEntry::play);
|
||||||
|
return true;
|
||||||
|
} else if (focused instanceof MultiplayerServerListWidget list) {
|
||||||
|
var entry = list.getSelectedOrNull();
|
||||||
|
if (entry instanceof MultiplayerServerListWidget.LanServerEntry || entry instanceof MultiplayerServerListWidget.ServerEntry) {
|
||||||
|
((MultiplayerScreen) screen).select(entry);
|
||||||
|
((MultiplayerScreen) screen).connect();
|
||||||
|
}
|
||||||
|
} else if (focused instanceof SpruceParentWidget) {
|
||||||
|
var childFocused = ((SpruceParentWidget<?>) focused).getFocused();
|
||||||
|
if (childFocused != null)
|
||||||
|
return this.handleAButton(screen, childFocused);
|
||||||
|
} else if (focused instanceof ParentElement widget) {
|
||||||
|
var childFocused = widget.getFocused();
|
||||||
|
if (childFocused != null)
|
||||||
|
return this.handleAButton(screen, childFocused);
|
||||||
|
} else if (PlatformFunctions.isModLoaded("yet-another-config-lib") && YACLCompat.handleAButton(screen, focused)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else pressKeyboardKey(screen, GLFW_KEY_ENTER);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the left and right buttons.
|
||||||
|
*
|
||||||
|
* @param screen the current screen
|
||||||
|
* @param right true if the right button is pressed, else false
|
||||||
|
*/
|
||||||
|
private boolean handleLeftRight(@NotNull Screen screen, boolean right) {
|
||||||
|
if (screen instanceof SpruceScreen spruceScreen) {
|
||||||
|
spruceScreen.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
||||||
|
this.actionGuiCooldown = 5;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (PlatformFunctions.isModLoaded("yet-another-config-lib") && YACLCompat.handleLeftRight(screen, right)) {
|
||||||
|
this.actionGuiCooldown = 5;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var focused = screen.getFocused();
|
||||||
|
if (focused != null)
|
||||||
|
if (this.handleRightLeftElement(focused, right))
|
||||||
|
return this.changeFocus(screen, right ? NavigationDirection.RIGHT : NavigationDirection.LEFT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleRightLeftElement(@NotNull Element element, boolean right) {
|
||||||
|
switch (element) {
|
||||||
|
case SpruceElement spruceElement -> {
|
||||||
|
if (spruceElement.requiresCursor())
|
||||||
|
return true;
|
||||||
|
return !spruceElement.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
||||||
|
}
|
||||||
|
case SliderWidget slider -> {
|
||||||
|
if (slider.active) {
|
||||||
|
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.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// case AlwaysSelectedEntryListWidget<?> alwaysSelectedEntryListWidget -> {
|
||||||
|
// //TODO ((EntryListWidgetAccessor) element).midnightcontrols$moveSelection(right ? EntryListWidget.MoveDirection.DOWN : EntryListWidget.MoveDirection.UP);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
case ParentElement entryList -> {
|
||||||
|
var focused = entryList.getFocused();
|
||||||
|
if (focused == null)
|
||||||
|
return true;
|
||||||
|
return this.handleRightLeftElement(focused, right);
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private double prevX = 0;
|
||||||
|
private double prevY = 0;
|
||||||
|
private double xValue;
|
||||||
|
private AxisStorage.Polarity xPolarity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the look direction input.
|
||||||
|
*
|
||||||
|
* @param storage the state of the provided axis
|
||||||
|
*/
|
||||||
|
public void handleLook(AxisStorage storage) {
|
||||||
|
if (client.player == null || !(storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y || storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X)) return;
|
||||||
|
// Handles the look direction.
|
||||||
|
if (MidnightControlsConfig.cameraMode == CameraMode.FLAT) handleFlatLook(storage);
|
||||||
|
else handleAdaptiveLook(storage);
|
||||||
|
MidnightControlsCompat.handleCamera(this.targetYaw, this.targetPitch);
|
||||||
|
}
|
||||||
|
private void handleFlatLook(AxisStorage storage) {
|
||||||
|
if (storage.polarity != AxisStorage.Polarity.ZERO) {
|
||||||
|
double rotation = Math.pow(storage.value, 2.0) * 0.11D * storage.polarity.multiplier;
|
||||||
|
|
||||||
|
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) this.targetPitch = rotation * MidnightControlsConfig.getRightYAxisSign() * MidnightControlsConfig.yAxisRotationSpeed / 2;
|
||||||
|
else this.targetYaw = rotation * MidnightControlsConfig.getRightXAxisSign() * MidnightControlsConfig.rotationSpeed / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void handleAdaptiveLook(AxisStorage storage) {
|
||||||
|
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
|
||||||
|
xValue = storage.value;
|
||||||
|
xPolarity = storage.polarity;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
double yStep = (MidnightControlsConfig.yAxisRotationSpeed / 50) * 0.6000000238418579 + 0.20000000298023224;
|
||||||
|
double xStep = (MidnightControlsConfig.rotationSpeed / 50) * 0.6000000238418579 + 0.20000000298023224;
|
||||||
|
float yValue = storage.value;
|
||||||
|
AxisStorage.Polarity yPolarity = storage.polarity;
|
||||||
|
|
||||||
|
double cursorDeltaX = 2 * xValue - this.prevX;
|
||||||
|
double cursorDeltaY = 2 * yValue - this.prevY;
|
||||||
|
boolean slowdown = client.options.getPerspective().isFirstPerson() && Objects.requireNonNull(client.player).isUsingSpyglass();
|
||||||
|
double x = cursorDeltaX * xStep * (slowdown ? xStep : 1);
|
||||||
|
double y = cursorDeltaY * yStep * (slowdown ? yStep : 1);
|
||||||
|
|
||||||
|
double powXValue = Math.pow(x, 2.0);
|
||||||
|
double powYValue = Math.pow(y, 2.0);
|
||||||
|
|
||||||
|
if (xPolarity != AxisStorage.Polarity.ZERO) {
|
||||||
|
double sign = MidnightControlsConfig.getRightXAxisSign() * MidnightControlsConfig.rotationSpeed;
|
||||||
|
this.targetYaw = sign * powXValue * 0.11D * xPolarity.multiplier;
|
||||||
|
}
|
||||||
|
if (yPolarity != AxisStorage.Polarity.ZERO) {
|
||||||
|
double sign = MidnightControlsConfig.getRightYAxisSign() * MidnightControlsConfig.yAxisRotationSpeed;
|
||||||
|
this.targetPitch = sign * powYValue * 0.11D * yPolarity.multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.prevY = yValue;
|
||||||
|
this.prevX = xValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void handleTouchscreenLook(AxisStorage storage) {
|
||||||
|
if (storage.polarity != AxisStorage.Polarity.ZERO) {
|
||||||
|
double rotation = storage.value * 0.11D * MidnightControlsConfig.touchSpeed/5;
|
||||||
|
|
||||||
|
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) this.targetPitch = rotation;
|
||||||
|
else this.targetYaw = rotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean changeFocus(@NotNull Screen screen, NavigationDirection direction) {
|
||||||
|
if (!isScreenInteractive(screen) && !screen.getClass().getCanonicalName().contains("me.jellysquid.mods.sodium.client.gui")) return false;
|
||||||
|
try {
|
||||||
|
if (screen instanceof SpruceScreen spruceScreen) {
|
||||||
|
if (spruceScreen.onNavigation(direction, false)) {
|
||||||
|
this.actionGuiCooldown = 5;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
switch (direction) {
|
||||||
|
case UP -> pressKeyboardKey(screen, GLFW.GLFW_KEY_UP);
|
||||||
|
case DOWN -> pressKeyboardKey(screen, GLFW.GLFW_KEY_DOWN);
|
||||||
|
case LEFT -> pressKeyboardKey(screen, GLFW.GLFW_KEY_LEFT);
|
||||||
|
case RIGHT -> pressKeyboardKey(screen, GLFW.GLFW_KEY_RIGHT);
|
||||||
|
}
|
||||||
|
this.actionGuiCooldown = 5;
|
||||||
|
return true;
|
||||||
|
} catch (Exception exception) {MidnightControls.warn("Unknown exception encountered while trying to change focus: "+exception);}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to go back.
|
||||||
|
*
|
||||||
|
* @param screen the current screen
|
||||||
|
* @return true if successful, else false
|
||||||
|
*/
|
||||||
|
public boolean tryGoBack(@NotNull Screen screen) {
|
||||||
|
var set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
|
||||||
|
if (screen instanceof KeybindsScreen) return false;
|
||||||
|
|
||||||
|
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||||
|
.map(element -> (PressableWidget) element)
|
||||||
|
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
|
||||||
|
.anyMatch(element -> {
|
||||||
|
if (element.getMessage().getContent() instanceof TranslatableTextContent translatableText) {
|
||||||
|
if (set.stream().anyMatch(key -> translatableText.getKey().equals(key))) {
|
||||||
|
element.onPress();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isScreenInteractive(@NotNull Screen screen) {
|
||||||
|
return !(screen instanceof HandledScreen || MidnightControlsConfig.joystickAsMouse || MidnightControlsConfig.mouseScreens.stream().anyMatch(a -> screen.getClass().toString().contains(a))
|
||||||
|
|| (screen instanceof SpruceScreen && ((SpruceScreen) screen).requiresCursor())
|
||||||
|
|| MidnightControlsCompat.requireMouseOnScreen(screen));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pressKeyboardKey(MinecraftClient client, int key) {
|
||||||
|
client.keyboard.onKey(client.getWindow().getHandle(), key, 0, 1, 0);
|
||||||
|
}
|
||||||
|
public void pressKeyboardKey(Screen screen, int key) {
|
||||||
|
screen.keyPressed(key, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ import net.minecraft.block.BlockState;
|
|||||||
import net.minecraft.block.FluidBlock;
|
import net.minecraft.block.FluidBlock;
|
||||||
import net.minecraft.block.SlabBlock;
|
import net.minecraft.block.SlabBlock;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributes;
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
@@ -27,6 +28,8 @@ import net.minecraft.world.RaycastContext;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the reach-around API of midnightcontrols.
|
* Represents the reach-around API of midnightcontrols.
|
||||||
*
|
*
|
||||||
@@ -38,10 +41,10 @@ public class MidnightReacharound {
|
|||||||
private boolean lastReacharoundVertical = false;
|
private boolean lastReacharoundVertical = false;
|
||||||
private boolean onSlab = false;
|
private boolean onSlab = false;
|
||||||
|
|
||||||
public void tick(@NotNull MinecraftClient client) {
|
public void tick() {
|
||||||
this.lastReacharoundResult = this.tryVerticalReachAround(client);
|
this.lastReacharoundResult = this.tryVerticalReachAround();
|
||||||
if (this.lastReacharoundResult == null) {
|
if (this.lastReacharoundResult == null) {
|
||||||
this.lastReacharoundResult = this.tryHorizontalReachAround(client);
|
this.lastReacharoundResult = this.tryHorizontalReachAround();
|
||||||
this.lastReacharoundVertical = false;
|
this.lastReacharoundVertical = false;
|
||||||
} else this.lastReacharoundVertical = true;
|
} else this.lastReacharoundVertical = true;
|
||||||
}
|
}
|
||||||
@@ -73,17 +76,16 @@ public class MidnightReacharound {
|
|||||||
return MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable();
|
return MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getPlayerRange(@NotNull MinecraftClient client) {
|
public static float getPlayerRange(@NotNull MinecraftClient client) {
|
||||||
return client.interactionManager != null ? client.interactionManager.getReachDistance() : 0.f;
|
return client.player != null ? Double.valueOf(client.player.getAttributeValue(EntityAttributes.BLOCK_INTERACTION_RANGE)).floatValue() : 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
|
||||||
* @return a block hit result if vertical reach-around is possible, else {@code 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() {
|
||||||
if (!MidnightControlsFeature.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
|
||||||
@@ -101,7 +103,7 @@ public class MidnightReacharound {
|
|||||||
BlockPos blockPos = result.getBlockPos().down();
|
BlockPos blockPos = result.getBlockPos().down();
|
||||||
BlockState state = client.world.getBlockState(blockPos);
|
BlockState state = client.world.getBlockState(blockPos);
|
||||||
|
|
||||||
if (client.player.getBlockPos().getY() - blockPos.getY() > 1 && (client.world.isAir(blockPos) || state.getMaterial().isReplaceable())) {
|
if (client.player.getBlockPos().getY() - blockPos.getY() > 1 && (client.world.isAir(blockPos) || state.isReplaceable())) {
|
||||||
return new BlockHitResult(result.getPos(), Direction.DOWN, blockPos, false);
|
return new BlockHitResult(result.getPos(), Direction.DOWN, blockPos, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,39 +114,46 @@ public class MidnightReacharound {
|
|||||||
/**
|
/**
|
||||||
* 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
|
|
||||||
* @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() {
|
||||||
if (!MidnightControlsFeature.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
|
if (client.world != null && client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS
|
||||||
&& client.player.isOnGround() && client.player.getPitch(0.f) > 35.f) {
|
&& client.player.isOnGround() && client.player.getPitch(0.f) >= 35.f) {
|
||||||
if (client.player.isRiding())
|
if (client.player.isRiding())
|
||||||
return null;
|
return null;
|
||||||
var playerPos = client.player.getBlockPos().down();
|
// Temporary pos, do not use
|
||||||
|
Vec3d playerPosi = client.player.getPos();
|
||||||
|
|
||||||
|
// Imitates var playerPos = client.player.getBlockPos().down();
|
||||||
|
Vec3d playerPos = new Vec3d(playerPosi.getX(), playerPosi.getY() - 1.0, playerPosi.getZ());
|
||||||
if (client.player.getY() - playerPos.getY() - 1.0 >= 0.25) {
|
if (client.player.getY() - playerPos.getY() - 1.0 >= 0.25) {
|
||||||
playerPos = playerPos.up();
|
// Imitates playerPos = playerPos.up();
|
||||||
|
playerPos = playerPosi;
|
||||||
this.onSlab = true;
|
this.onSlab = true;
|
||||||
} else {
|
} else {
|
||||||
this.onSlab = false;
|
this.onSlab = false;
|
||||||
}
|
}
|
||||||
var targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
|
var targetPos = new Vec3d(client.crosshairTarget.getPos().getX(), client.crosshairTarget.getPos().getY(), client.crosshairTarget.getPos().getZ()).subtract(playerPos);
|
||||||
var vector = new BlockPos.Mutable(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
|
var vector = new Vec3d(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
|
||||||
var blockPos = playerPos.add(vector);
|
var blockPos = playerPos.add(vector);
|
||||||
|
|
||||||
|
// Some functions still need BlockPos, so this is here to let that happen
|
||||||
|
var blockyPos = BlockPos.ofFloored(blockPos);
|
||||||
|
|
||||||
var direction = client.player.getHorizontalFacing();
|
var direction = client.player.getHorizontalFacing();
|
||||||
|
|
||||||
var state = client.world.getBlockState(blockPos);
|
var state = client.world.getBlockState(blockyPos);
|
||||||
if (!state.isAir())
|
if (!state.isAir())
|
||||||
return null;
|
return null;
|
||||||
var adjacentBlockState = client.world.getBlockState(blockPos.offset(direction.getOpposite()));
|
var adjacentBlockState = client.world.getBlockState(blockyPos.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(new Vec3d(blockPos.getX(),blockPos.getY(),blockPos.getZ()), direction, blockPos, false);
|
return new BlockHitResult(blockPos, direction, blockyPos, false);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -9,14 +9,7 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
|
||||||
import me.juancarloscp52.bedrockify.client.BedrockifyClient;
|
import me.juancarloscp52.bedrockify.client.BedrockifyClient;
|
||||||
import me.juancarloscp52.bedrockify.client.BedrockifyClientSettings;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents HQM compatibility handler.
|
* Represents HQM compatibility handler.
|
||||||
@@ -28,7 +21,7 @@ import java.util.Optional;
|
|||||||
public class BedrockifyCompat implements CompatHandler {
|
public class BedrockifyCompat implements CompatHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(@NotNull MidnightControlsClient mod) {
|
public void handle() {
|
||||||
BedrockifyClient.getInstance().settings.disableFlyingMomentum = false;
|
BedrockifyClient.getInstance().settings.disableFlyingMomentum = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
||||||
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;
|
||||||
@@ -26,12 +27,20 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public interface CompatHandler {
|
public interface CompatHandler {
|
||||||
|
/**
|
||||||
|
* Handles compatibility of a mod.
|
||||||
|
*/
|
||||||
|
default void handle() {
|
||||||
|
handle(MidnightControlsClient.get());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles compatibility of a mod.
|
* Handles compatibility of a mod.
|
||||||
*
|
*
|
||||||
* @param mod this mod instance
|
* @param mod this mod instance
|
||||||
*/
|
*/
|
||||||
void handle(@NotNull MidnightControlsClient mod);
|
@Deprecated
|
||||||
|
default void handle(@NotNull MidnightControlsClient mod) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles custom camera updates
|
* Handles custom camera updates
|
||||||
@@ -40,6 +49,32 @@ public interface CompatHandler {
|
|||||||
*/
|
*/
|
||||||
default void handleCamera(@NotNull MinecraftClient client, double targetYaw, double targetPitch) {};
|
default void handleCamera(@NotNull MinecraftClient client, double targetYaw, double targetPitch) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles movement for players as well as vehicles
|
||||||
|
*
|
||||||
|
* @param storage the storage containing info about the current axis
|
||||||
|
* @param adjustedValue the value of the axis, adjusted for max values and non-analogue movement, recommended for player movement
|
||||||
|
*/
|
||||||
|
default void handleMovement(@NotNull MinecraftClient client, AxisStorage storage, float adjustedValue) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles custom tab behavior
|
||||||
|
*
|
||||||
|
* @param forward whether the direction is forward or backward
|
||||||
|
*/
|
||||||
|
default boolean handleTabs(Screen screen, boolean forward) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles custom page behavior
|
||||||
|
*
|
||||||
|
* @param forward whether the direction is forward or backward
|
||||||
|
*/
|
||||||
|
default boolean handlePages(Screen screen, boolean forward) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the mouse is required on the specified screen.
|
* Returns whether the mouse is required on the specified screen.
|
||||||
*
|
*
|
||||||
@@ -1,42 +1,41 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import dev.emi.emi.EmiConfig;
|
import dev.emi.emi.api.EmiApi;
|
||||||
import dev.emi.emi.screen.EmiScreen;
|
import dev.emi.emi.config.EmiConfig;
|
||||||
import dev.emi.emi.screen.EmiScreenManager;
|
import dev.emi.emi.screen.EmiScreenManager;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
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;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||||
|
|
||||||
public class EMICompat implements CompatHandler {
|
public class EMICompat implements CompatHandler {
|
||||||
public static boolean handleTabs(boolean direction) {
|
public static boolean handleEmiPages(boolean direction) {
|
||||||
if (isEMIEnabled() && MidnightControlsClient.get().input.actionGuiCooldown == 0 && EmiScreenManager.searchLeft != null && EmiScreenManager.searchRight != null) {
|
if (isEMIEnabled() && MidnightControlsClient.input.actionGuiCooldown == 0 && EmiScreenManager.getSearchPanel() != null && EmiScreenManager.getSearchPanel().pageLeft != null && EmiScreenManager.getSearchPanel().pageRight != null) {
|
||||||
if (direction) EmiScreenManager.searchRight.onPress();
|
if (direction) EmiScreenManager.getSearchPanel().pageRight.onPress();
|
||||||
else EmiScreenManager.searchLeft.onPress();
|
else EmiScreenManager.getSearchPanel().pageLeft.onPress();
|
||||||
MidnightControlsClient.get().input.actionGuiCooldown = 5;
|
MidnightControlsClient.input.actionGuiCooldown = 5;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void handle(@NotNull MidnightControlsClient mod) {
|
public void handle() {
|
||||||
ButtonCategory category = new ButtonCategory(new Identifier("midnightcontrols","category.emi"));
|
ButtonCategory category = new ButtonCategory(id("category.emi"));
|
||||||
InputManager.registerCategory(category);
|
InputManager.registerCategory(category);
|
||||||
new ButtonBinding.Builder("emi_page_left")
|
new ButtonBinding.Builder("emi_page_left")
|
||||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||||
.category(category)
|
.category(category)
|
||||||
.action((client,action,value,buttonState)->handleTabs(false)).cooldown()
|
.action((client,action,value,buttonState)->handleEmiPages(false)).cooldown()
|
||||||
.filter(((client, buttonBinding) -> client.currentScreen instanceof HandledScreen<?> || client.currentScreen instanceof EmiScreen))
|
.filter(((buttonBinding) -> EmiApi.getHandledScreen() != null))
|
||||||
.register();
|
.register();
|
||||||
new ButtonBinding.Builder("emi_page_right")
|
new ButtonBinding.Builder("emi_page_right")
|
||||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||||
.category(category)
|
.category(category)
|
||||||
.action((client,action,value,buttonState)->handleTabs(true)).cooldown()
|
.action((client,action,value,buttonState)->handleEmiPages(true)).cooldown()
|
||||||
.filter(((client, buttonBinding) -> client.currentScreen instanceof HandledScreen<?> || client.currentScreen instanceof EmiScreen))
|
.filter(((buttonBinding) -> EmiApi.getHandledScreen() != null))
|
||||||
.register();
|
.register();
|
||||||
}
|
}
|
||||||
public static boolean isEMIEnabled() {
|
public static boolean isEMIEnabled() {
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
|
||||||
|
import io.github.kosmx.emotes.arch.screen.ingame.FastMenuScreen;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import org.joml.Vector2i;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
public class EmotecraftCompat {
|
||||||
|
private static final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
|
||||||
|
public static void openEmotecraftScreen(Screen parent) {
|
||||||
|
client.setScreen(new FastMenuScreen(parent));
|
||||||
|
}
|
||||||
|
public static boolean isEmotecraftScreen(Screen screen) {
|
||||||
|
return screen instanceof FastMenuScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int prevIndex = -1;
|
||||||
|
public static void handleEmoteSelector(int index) {
|
||||||
|
try {
|
||||||
|
if (client.currentScreen instanceof FastMenuScreen) {
|
||||||
|
boolean stickReleased = index == -1 && prevIndex != -1;
|
||||||
|
var pos = calcMousePos(stickReleased ? prevIndex : index);
|
||||||
|
InputManager.queueMousePosition(pos.x, pos.y);
|
||||||
|
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
||||||
|
|
||||||
|
if (stickReleased) {
|
||||||
|
((MouseAccessor) client.mouse).midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_PRESS, 0);
|
||||||
|
prevIndex = -1;
|
||||||
|
}
|
||||||
|
else prevIndex = index;
|
||||||
|
} else prevIndex = -1;
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
public static Vector2i calcMousePos(int index) {
|
||||||
|
int x = client.getWindow().getWidth() / 2;
|
||||||
|
int y = client.getWindow().getHeight() / 2;
|
||||||
|
switch (index) {
|
||||||
|
case 0, 3, 5 -> x -= 275;
|
||||||
|
case 2, 4, 7 -> x += 275;
|
||||||
|
}
|
||||||
|
switch (index) {
|
||||||
|
case 0, 1, 2 -> y -= 275;
|
||||||
|
case 5, 6, 7 -> y += 275;
|
||||||
|
}
|
||||||
|
return new Vector2i(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,10 +9,8 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
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 java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -30,7 +28,7 @@ public class HQMCompat implements CompatHandler {
|
|||||||
private Optional<Class<?>> guiBaseClass;
|
private Optional<Class<?>> guiBaseClass;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(@NotNull MidnightControlsClient mod) {
|
public void handle() {
|
||||||
this.guiBaseClass = LambdaReflection.getClass(GUI_BASE_CLASS_PATH);
|
this.guiBaseClass = LambdaReflection.getClass(GUI_BASE_CLASS_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5,29 +5,39 @@ import net.minecraft.client.gui.screen.Screen;
|
|||||||
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;
|
||||||
|
|
||||||
public class InventoryTabsCompat {
|
public class InventoryTabsCompat implements CompatHandler {
|
||||||
|
@Override
|
||||||
public static void handleInventoryTabs(Screen screen, boolean next) {
|
public boolean handleTabs(Screen screen, boolean next) {
|
||||||
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
||||||
TabManager tabManager = TabManager.getInstance();
|
TabManager tabManager = TabManager.getInstance();
|
||||||
int tabIndex = tabManager.tabs.indexOf(tabManager.currentTab);
|
int tabIndex = tabManager.tabs.indexOf(tabManager.currentTab);
|
||||||
if (next) {
|
if (next) {
|
||||||
if (tabIndex < tabManager.tabs.size() - 1) tabManager.onTabClick(tabManager.tabs.get(tabIndex + 1));
|
if (tabIndex < tabManager.tabs.size() - 1) tabManager.onTabClick(tabManager.tabs.get(tabIndex + 1));
|
||||||
else tabManager.onTabClick(tabManager.tabs.get(0));
|
else tabManager.onTabClick(tabManager.tabs.getFirst());
|
||||||
} else {
|
} else {
|
||||||
if (tabIndex > 0) tabManager.onTabClick(tabManager.tabs.get(tabIndex - 1));
|
if (tabIndex > 0) tabManager.onTabClick(tabManager.tabs.get(tabIndex - 1));
|
||||||
else tabManager.onTabClick(tabManager.tabs.get(tabManager.tabs.size() - 1));
|
else tabManager.onTabClick(tabManager.tabs.getLast());
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
public static void handleInventoryPage(Screen screen, boolean next) {
|
@Override
|
||||||
|
public boolean handlePages(Screen screen, boolean next) {
|
||||||
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
||||||
TabManager tabManager = TabManager.getInstance();
|
TabManager tabManager = TabManager.getInstance();
|
||||||
if (next) {
|
if (next) {
|
||||||
if (tabManager.canGoForwardAPage()) tabManager.setCurrentPage(tabManager.currentPage + 1);
|
if (tabManager.canGoForwardAPage()) {
|
||||||
|
tabManager.setCurrentPage(tabManager.currentPage + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tabManager.canGoBackAPage()) tabManager.setCurrentPage(tabManager.currentPage - 1);
|
if (tabManager.canGoBackAPage()) {
|
||||||
|
tabManager.setCurrentPage(tabManager.currentPage - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
||||||
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;
|
||||||
@@ -23,41 +23,49 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.MidnightControls.log;
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a compatibility handler.
|
* Represents a compatibility handler.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora, Motschen
|
||||||
* @version 1.5.0
|
* @version 1.10.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class MidnightControlsCompat {
|
public class MidnightControlsCompat {
|
||||||
|
@Deprecated // INTERNAL -> PLEASE USE streamCompatHandlers() INSTEAD
|
||||||
public 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
|
|
||||||
*/
|
*/
|
||||||
public static void init(@NotNull MidnightControlsClient mod) {
|
public static void init() {
|
||||||
// "okzoomer" is the mod ID used by Fabric-compatible versions of Ok Zoomer. (5.0.0-beta.6 and below.)
|
if (PlatformFunctions.isModLoaded("emi")) {
|
||||||
// "ok_zoomer" is the mod ID used by Quilt-exclusive versions of Ok Zoomer. (5.0.0-beta.7 and above.)
|
log("Adding EMI compatibility...");
|
||||||
if (FabricLoader.getInstance().isModLoaded("okzoomer") || FabricLoader.getInstance().isModLoaded("ok_zoomer")) {
|
registerCompatHandler(new EMICompat());
|
||||||
mod.log("Adding Ok Zoomer compatibility...");
|
|
||||||
HANDLERS.add(new OkZoomerCompat());
|
|
||||||
}
|
}
|
||||||
if (isEMIPresent()) {
|
if (PlatformFunctions.isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
|
||||||
mod.log("Adding EMI compatibility...");
|
log("Adding HQM compatibility...");
|
||||||
HANDLERS.add(new EMICompat());
|
registerCompatHandler(new HQMCompat());
|
||||||
}
|
}
|
||||||
if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
|
if (PlatformFunctions.isModLoaded("bedrockify")) {
|
||||||
mod.log("Adding HQM compatibility...");
|
log("Adding Bedrockify compatibility...");
|
||||||
HANDLERS.add(new HQMCompat());
|
registerCompatHandler(new BedrockifyCompat());
|
||||||
}
|
}
|
||||||
if (FabricLoader.getInstance().isModLoaded("bedrockify")) {
|
if (PlatformFunctions.isModLoaded("yet-another-config-lib")) {
|
||||||
mod.log("Adding Bedrockify compatibility...");
|
log("Adding YACL compatibility...");
|
||||||
HANDLERS.add(new BedrockifyCompat());
|
registerCompatHandler(new YACLCompat());
|
||||||
}
|
}
|
||||||
HANDLERS.forEach(handler -> handler.handle(mod));
|
if (PlatformFunctions.isModLoaded("sodium")) {
|
||||||
|
log("Adding Sodium compatibility...");
|
||||||
|
registerCompatHandler(new SodiumCompat());
|
||||||
|
}
|
||||||
|
if (PlatformFunctions.isModLoaded("inventorytabs")) {
|
||||||
|
log("Adding Inventory Tabs compatibility...");
|
||||||
|
registerCompatHandler(new InventoryTabsCompat());
|
||||||
|
}
|
||||||
|
HANDLERS.forEach(CompatHandler::handle);
|
||||||
InputManager.loadButtonBindings();
|
InputManager.loadButtonBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +94,25 @@ public class MidnightControlsCompat {
|
|||||||
* @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 streamCompatHandlers().anyMatch(handler -> handler.requireMouseOnScreen(screen));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handles custom tabs for modded screens
|
||||||
|
*
|
||||||
|
* @param screen the screen
|
||||||
|
* @return true if the handle was fired and succeed, else false
|
||||||
|
*/
|
||||||
|
public static boolean handleTabs(Screen screen, boolean forward) {
|
||||||
|
return streamCompatHandlers().anyMatch(handler -> handler.handleTabs(screen, forward));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handles custom pages for modded screens
|
||||||
|
*
|
||||||
|
* @param screen the screen
|
||||||
|
* @return true if the handle was fired and succeed, else false
|
||||||
|
*/
|
||||||
|
public static boolean handlePages(Screen screen, boolean forward) {
|
||||||
|
return streamCompatHandlers().anyMatch(handler -> handler.handlePages(screen, forward));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,37 +180,22 @@ public class MidnightControlsCompat {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether Roughly Enough Items is present.
|
* Handles the camera movement.
|
||||||
*
|
*
|
||||||
* @return true if Roughly Enough Items is present, else false
|
* @param targetYaw the target yaw
|
||||||
|
* @param targetPitch the target pitch
|
||||||
*/
|
*/
|
||||||
public static boolean isReiPresent() {
|
public static void handleCamera(double targetYaw, double targetPitch) {
|
||||||
return FabricLoader.getInstance().isModLoaded("roughlyenoughitems");
|
MidnightControlsCompat.HANDLERS.forEach(handler -> handler.handleCamera(client, targetYaw, targetPitch));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Returns whether EMI is present.
|
* Handles movement for players as well as vehicles
|
||||||
*
|
*
|
||||||
* @return true if EMI is present, else false
|
* @param storage the storage containing info about the current axis
|
||||||
|
* @param adjustedValue the value of the axis, adjusted for max values and non-analogue movement, recommended for player movement
|
||||||
*/
|
*/
|
||||||
public static boolean isEMIPresent() {
|
public static void handleMovement(AxisStorage storage, float adjustedValue) {
|
||||||
return FabricLoader.getInstance().isModLoaded("emi");
|
streamCompatHandlers().forEach(handler -> handler.handleMovement(client, storage, adjustedValue));
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns whether InventoryTabs is present.
|
|
||||||
*
|
|
||||||
* @return true if InventoryTabs is present, else false
|
|
||||||
*/
|
|
||||||
public static boolean isInventoryTabsPresent() {
|
|
||||||
return FabricLoader.getInstance().isModLoaded("inventorytabs");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns whether Emotecraft is present.
|
|
||||||
*
|
|
||||||
* @return true if Emotecraft is present, else false
|
|
||||||
*/
|
|
||||||
public static boolean isEmotecraftPresent() {
|
|
||||||
return FabricLoader.getInstance().isModLoaded("emotecraft");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,36 +9,27 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
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;
|
||||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This plugin is only present for the conditional mixins.
|
* This plugin is only present for the conditional mixins.
|
||||||
*
|
*
|
||||||
* @author LambdAurora
|
* @author LambdAurora & Motschen
|
||||||
* @version 1.5.0
|
* @version 1.6.0
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
||||||
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>();
|
private String mixinPackage;
|
||||||
|
|
||||||
public MidnightControlsMixinPlugin() {
|
|
||||||
this.putConditionalMixin("SodiumOptionsGUIAccessor", FabricLoader.getInstance().isModLoaded("sodium"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void putConditionalMixin(@NotNull String path, boolean condition) {
|
|
||||||
this.conditionalMixins.put("eu.midnightdust.midnightcontrols.client.compat.mixin." + path, condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad(String mixinPackage) {
|
public void onLoad(String mixinPackage) {
|
||||||
|
this.mixinPackage = mixinPackage + ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -48,7 +39,13 @@ public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||||
return this.conditionalMixins.getOrDefault(mixinClassName, Boolean.TRUE);
|
final String mixinName = mixinClassName.substring(this.mixinPackage.length());
|
||||||
|
final String packageName = mixinName.substring(0, mixinName.lastIndexOf('.'));
|
||||||
|
|
||||||
|
if (packageName.startsWith("sodium") && !PlatformFunctions.isModLoaded("sodium"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.mixin.sodium.SodiumOptionsGUIAccessor;
|
||||||
|
import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
|
||||||
|
public class SodiumCompat implements CompatHandler {
|
||||||
|
@Override
|
||||||
|
public boolean 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));
|
||||||
|
optionsGUI.setPage(accessor.getPages().get(i));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import dev.isxander.yacl.gui.AbstractWidget;
|
||||||
|
import dev.isxander.yacl.gui.OptionListWidget;
|
||||||
|
import dev.isxander.yacl.gui.YACLScreen;
|
||||||
|
import dev.isxander.yacl.gui.controllers.ControllerWidget;
|
||||||
|
import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement;
|
||||||
|
import net.minecraft.client.gui.Element;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
public class YACLCompat implements CompatHandler {
|
||||||
|
public static boolean handleAButton(Screen screen, Element element) {
|
||||||
|
if (element instanceof AbstractWidget abstractWidget) {
|
||||||
|
// imitate enter key press
|
||||||
|
return abstractWidget.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean handleLeftRight(Screen screen, boolean direction) {
|
||||||
|
if (screen instanceof YACLScreen yaclScreen) {
|
||||||
|
SliderControllerElement focusedSlider = yaclScreen.optionList.children().stream()
|
||||||
|
.filter(OptionListWidget.OptionEntry.class::isInstance)
|
||||||
|
.map(entry -> ((OptionListWidget.OptionEntry) entry).widget)
|
||||||
|
.filter(ControllerWidget.class::isInstance)
|
||||||
|
.map(ControllerWidget.class::cast)
|
||||||
|
.filter(SliderControllerElement.class::isInstance)
|
||||||
|
.map(SliderControllerElement.class::cast)
|
||||||
|
.filter(ControllerWidget::isHovered)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (focusedSlider == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
focusedSlider.incrementValue(direction ? 1 : -1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleTabs(Screen screen, boolean direction) {
|
||||||
|
if (screen instanceof YACLScreen yaclScreen) {
|
||||||
|
int categoryIdx = yaclScreen.getCurrentCategoryIdx();
|
||||||
|
if (direction) categoryIdx++; else categoryIdx--;
|
||||||
|
if (categoryIdx < 0) categoryIdx = yaclScreen.config.categories().size() - 1;
|
||||||
|
if (categoryIdx >= yaclScreen.config.categories().size()) categoryIdx = 0;
|
||||||
|
|
||||||
|
yaclScreen.changeCategory(categoryIdx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.compat.mixin;
|
package eu.midnightdust.midnightcontrols.client.compat.mixin.sodium;
|
||||||
|
|
||||||
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
|
import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||||
import me.jellysquid.mods.sodium.client.gui.options.OptionPage;
|
import net.caffeinemc.mods.sodium.client.gui.options.OptionPage;
|
||||||
import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement;
|
import net.caffeinemc.mods.sodium.client.gui.options.control.ControlElement;
|
||||||
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;
|
||||||
|
|
||||||
@@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
import com.google.common.base.Predicates;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
@@ -18,14 +19,14 @@ import net.minecraft.client.option.KeyBinding;
|
|||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
|
||||||
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,7 +50,7 @@ public class ButtonBinding {
|
|||||||
public static final ButtonBinding CONTROLS_RING = new Builder("controls_ring").buttons(GLFW_GAMEPAD_BUTTON_GUIDE).onlyInGame().cooldown()
|
public static final ButtonBinding CONTROLS_RING = new Builder("controls_ring").buttons(GLFW_GAMEPAD_BUTTON_GUIDE).onlyInGame().cooldown()
|
||||||
.action((client, button1, value, action) -> {
|
.action((client, button1, value, action) -> {
|
||||||
if (action.isPressed()) {
|
if (action.isPressed()) {
|
||||||
MidnightControlsClient.get().ring.loadFromUnbound();
|
MidnightControlsClient.ring.loadFromUnbound();
|
||||||
client.setScreen(new RingScreen());
|
client.setScreen(new RingScreen());
|
||||||
}
|
}
|
||||||
if (action.isUnpressed() && client.currentScreen != null) client.currentScreen.close();
|
if (action.isUnpressed() && client.currentScreen != null) client.currentScreen.close();
|
||||||
@@ -63,7 +64,7 @@ public class ButtonBinding {
|
|||||||
public static final ButtonBinding HOTBAR_RIGHT = new Builder("hotbar_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
public static final ButtonBinding HOTBAR_RIGHT = new Builder("hotbar_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||||
.action(InputHandlers.handleHotbar(true)).onlyInGame().cooldown().register();
|
.action(InputHandlers.handleHotbar(true)).onlyInGame().cooldown().register();
|
||||||
public static final ButtonBinding INVENTORY = new Builder("inventory").buttons(GLFW_GAMEPAD_BUTTON_Y).onlyInGame().cooldown().register();
|
public static final ButtonBinding INVENTORY = new Builder("inventory").buttons(GLFW_GAMEPAD_BUTTON_Y).onlyInGame().cooldown().register();
|
||||||
public static final ButtonBinding EXIT = new Builder("exit").buttons(GLFW_GAMEPAD_BUTTON_B).filter((client, buttonBinding) -> client.currentScreen != null && buttonBinding.cooldown == 0 && INVENTORY.cooldown == 0)
|
public static final ButtonBinding EXIT = new Builder("exit").buttons(GLFW_GAMEPAD_BUTTON_B).filter((buttonBinding) -> client.currentScreen != null && buttonBinding.cooldown == 0 && INVENTORY.cooldown == 0)
|
||||||
.action(InputHandlers.handleExit()).cooldown().register();
|
.action(InputHandlers.handleExit()).cooldown().register();
|
||||||
public static final ButtonBinding JUMP = new Builder("jump").buttons(GLFW_GAMEPAD_BUTTON_A).onlyInGame().register();
|
public static final ButtonBinding JUMP = new Builder("jump").buttons(GLFW_GAMEPAD_BUTTON_A).onlyInGame().register();
|
||||||
public static final ButtonBinding LEFT = new Builder("left").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false))
|
public static final ButtonBinding LEFT = new Builder("left").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false))
|
||||||
@@ -75,9 +76,8 @@ public class ButtonBinding {
|
|||||||
.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)
|
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();
|
.action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.inGameHud.getDebugHud().toggleDebugHud(); 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)
|
||||||
@@ -89,12 +89,12 @@ public class ButtonBinding {
|
|||||||
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
||||||
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register();
|
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register();
|
||||||
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
||||||
.actions(InputHandlers::handleToggleSprint).onlyInGame().register();
|
.actions(InputHandlers::handleToggleSprint).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 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).or((client, binding) -> client.currentScreen != null && client.currentScreen.getClass().toString().contains("sodium"))).cooldown().register();
|
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((binding) -> client.currentScreen != null)).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).or((client, binding) -> client.currentScreen != null && client.currentScreen.getClass().toString().contains("sodium"))).cooldown().register();
|
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((binding) -> client.currentScreen != null)).cooldown().register();
|
||||||
public static final ButtonBinding PAGE_LEFT = new Builder("page_back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
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(30).register();
|
.action(InputHandlers.handlePage(false)).filter(InputHandlers::inInventory).cooldown(30).register();
|
||||||
public static final ButtonBinding PAGE_RIGHT = new Builder("page_next").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
public static final ButtonBinding PAGE_RIGHT = new Builder("page_next").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||||
@@ -113,14 +113,14 @@ public class ButtonBinding {
|
|||||||
private final String key;
|
private final String key;
|
||||||
private final Text text;
|
private final Text text;
|
||||||
private KeyBinding mcKeyBinding = null;
|
private KeyBinding mcKeyBinding = null;
|
||||||
protected PairPredicate<MinecraftClient, ButtonBinding> filter;
|
protected Predicate<ButtonBinding> filter;
|
||||||
private final 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 final boolean hasCooldown;
|
||||||
private int cooldownLength = 5;
|
private int cooldownLength = 5;
|
||||||
private int cooldown = 0;
|
private int cooldown = 0;
|
||||||
boolean pressed = false;
|
private boolean pressed = false;
|
||||||
|
|
||||||
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, Predicate<ButtonBinding> filter, boolean hasCooldown) {
|
||||||
this.setButton(this.defaultButton = defaultButton);
|
this.setButton(this.defaultButton = defaultButton);
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.text = Text.translatable(this.key);
|
this.text = Text.translatable(this.key);
|
||||||
@@ -128,7 +128,7 @@ public class ButtonBinding {
|
|||||||
this.actions.addAll(actions);
|
this.actions.addAll(actions);
|
||||||
this.hasCooldown = hasCooldown;
|
this.hasCooldown = hasCooldown;
|
||||||
}
|
}
|
||||||
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown, int cooldownLength) {
|
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, Predicate<ButtonBinding> filter, boolean hasCooldown, int cooldownLength) {
|
||||||
this.setButton(this.defaultButton = defaultButton);
|
this.setButton(this.defaultButton = defaultButton);
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.text = Text.translatable(this.key);
|
this.text = Text.translatable(this.key);
|
||||||
@@ -139,10 +139,10 @@ public class ButtonBinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ButtonBinding(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.alwaysTrue(), hasCooldown);
|
||||||
}
|
}
|
||||||
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown, int cooldownLength) {
|
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown, int cooldownLength) {
|
||||||
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown, cooldownLength);
|
this(key, defaultButton, Collections.emptyList(), Predicates.alwaysTrue(), hasCooldown, cooldownLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,6 +165,14 @@ public class ButtonBinding {
|
|||||||
if (InputManager.hasBinding(this))
|
if (InputManager.hasBinding(this))
|
||||||
InputManager.sortBindings();
|
InputManager.sortBindings();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Sets the button press state.
|
||||||
|
*
|
||||||
|
* @param pressed whether the button is pressed
|
||||||
|
*/
|
||||||
|
public void setPressed(boolean pressed) {
|
||||||
|
this.pressed = pressed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the bound button is the specified button or not.
|
* Returns whether the bound button is the specified button or not.
|
||||||
@@ -180,8 +188,18 @@ public class ButtonBinding {
|
|||||||
* 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
|
||||||
|
* @deprecated Use {@link #isPressed()} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public boolean isButtonDown() {
|
public boolean isButtonDown() {
|
||||||
|
return isPressed();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns whether this button is down or not.
|
||||||
|
*
|
||||||
|
* @return true if the button is down, else false
|
||||||
|
*/
|
||||||
|
public boolean isPressed() {
|
||||||
return this.pressed;
|
return this.pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,11 +253,10 @@ public class ButtonBinding {
|
|||||||
/**
|
/**
|
||||||
* 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
|
|
||||||
* @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() {
|
||||||
return this.filter.test(client, this);
|
return this.filter.test(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -463,7 +480,7 @@ public class ButtonBinding {
|
|||||||
private final String key;
|
private final String key;
|
||||||
private int[] buttons = new int[0];
|
private int[] buttons = new int[0];
|
||||||
private final List<PressAction> actions = new ArrayList<>();
|
private final List<PressAction> actions = new ArrayList<>();
|
||||||
private PairPredicate<MinecraftClient, ButtonBinding> filter = Predicates.pairAlwaysTrue();
|
private Predicate<ButtonBinding> filter = Predicates.alwaysTrue();
|
||||||
private boolean cooldown = false;
|
private boolean cooldown = false;
|
||||||
private int cooldownLength = 5;
|
private int cooldownLength = 5;
|
||||||
private ButtonCategory category = null;
|
private ButtonCategory category = null;
|
||||||
@@ -482,6 +499,10 @@ public class ButtonBinding {
|
|||||||
public Builder(@NotNull Identifier identifier) {
|
public Builder(@NotNull Identifier identifier) {
|
||||||
this(identifier.getNamespace() + "." + identifier.getPath());
|
this(identifier.getNamespace() + "." + identifier.getPath());
|
||||||
}
|
}
|
||||||
|
@Deprecated
|
||||||
|
public Builder(@NotNull org.aperlambda.lambdacommon.Identifier identifier) {
|
||||||
|
this(identifier.getNamespace() + "." + identifier.getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the default buttons of the {@link ButtonBinding}.
|
* Defines the default buttons of the {@link ButtonBinding}.
|
||||||
@@ -531,7 +552,7 @@ public class 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 Predicate<ButtonBinding> filter) {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -540,8 +561,8 @@ public class ButtonBinding {
|
|||||||
* 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(Predicate)
|
||||||
* @see InputHandlers#inGame(MinecraftClient, ButtonBinding)
|
* @see InputHandlers#inGame(ButtonBinding)
|
||||||
*/
|
*/
|
||||||
public Builder onlyInGame() {
|
public Builder onlyInGame() {
|
||||||
return this.filter(InputHandlers::inGame);
|
return this.filter(InputHandlers::inGame);
|
||||||
@@ -551,8 +572,8 @@ public class ButtonBinding {
|
|||||||
* 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(Predicate)
|
||||||
* @see InputHandlers#inInventory(MinecraftClient, ButtonBinding)
|
* @see InputHandlers#inInventory(ButtonBinding)
|
||||||
*/
|
*/
|
||||||
public Builder onlyInInventory() {
|
public Builder onlyInInventory() {
|
||||||
return this.filter(InputHandlers::inInventory);
|
return this.filter(InputHandlers::inInventory);
|
||||||
@@ -10,8 +10,7 @@
|
|||||||
package eu.midnightdust.midnightcontrols.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 net.minecraft.util.Identifier;
|
||||||
import org.aperlambda.lambdacommon.utils.Identifiable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -26,7 +25,7 @@ import java.util.List;
|
|||||||
* @version 1.1.0
|
* @version 1.1.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class ButtonCategory implements Identifiable {
|
public class ButtonCategory {
|
||||||
private final List<ButtonBinding> bindings = new ArrayList<>();
|
private final List<ButtonBinding> bindings = new ArrayList<>();
|
||||||
private final Identifier id;
|
private final Identifier id;
|
||||||
private final int priority;
|
private final int priority;
|
||||||
@@ -39,6 +38,15 @@ public class ButtonCategory implements Identifiable {
|
|||||||
public ButtonCategory(@NotNull Identifier id) {
|
public ButtonCategory(@NotNull Identifier id) {
|
||||||
this(id, 100);
|
this(id, 100);
|
||||||
}
|
}
|
||||||
|
@Deprecated
|
||||||
|
public ButtonCategory(@NotNull org.aperlambda.lambdacommon.Identifier id, int priority) {
|
||||||
|
this(Identifier.of(id.getNamespace(), id.getName()), priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public ButtonCategory(@NotNull org.aperlambda.lambdacommon.Identifier id) {
|
||||||
|
this(id, 100);
|
||||||
|
}
|
||||||
|
|
||||||
public void registerBinding(@NotNull ButtonBinding binding) {
|
public void registerBinding(@NotNull ButtonBinding binding) {
|
||||||
if (this.bindings.contains(binding))
|
if (this.bindings.contains(binding))
|
||||||
@@ -72,9 +80,9 @@ public class ButtonCategory implements Identifiable {
|
|||||||
*/
|
*/
|
||||||
public @NotNull String getTranslatedName() {
|
public @NotNull String getTranslatedName() {
|
||||||
if (this.id.getNamespace().equals("minecraft"))
|
if (this.id.getNamespace().equals("minecraft"))
|
||||||
return I18n.translate(this.id.getName());
|
return I18n.translate(this.id.getPath());
|
||||||
else
|
else
|
||||||
return I18n.translate(this.id.getNamespace() + "." + this.id.getName());
|
return I18n.translate(this.id.getNamespace() + "." + this.id.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,7 +95,6 @@ public class ButtonCategory implements Identifiable {
|
|||||||
return this.priority;
|
return this.priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Identifier getIdentifier() {
|
public @NotNull Identifier getIdentifier() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ import org.lwjgl.system.MemoryStack;
|
|||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URI;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -32,6 +32,7 @@ import java.util.Comparator;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import static org.lwjgl.BufferUtils.createByteBuffer;
|
import static org.lwjgl.BufferUtils.createByteBuffer;
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ import static org.lwjgl.BufferUtils.createByteBuffer;
|
|||||||
* @version 1.7.0
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public record Controller(int id) implements Nameable {
|
public record Controller(int id) {
|
||||||
private static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
private static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,8 +79,7 @@ public record Controller(int id) implements Nameable {
|
|||||||
*
|
*
|
||||||
* @return the controller's name
|
* @return the controller's name
|
||||||
*/
|
*/
|
||||||
@Override
|
public @NotNull String getName() {
|
||||||
public String getName() {
|
|
||||||
var 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.id()) : name;
|
return name == null ? String.valueOf(this.id()) : name;
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ public record Controller(int id) implements Nameable {
|
|||||||
|
|
||||||
public static Controller byId(int id) {
|
public static Controller byId(int id) {
|
||||||
if (id > GLFW.GLFW_JOYSTICK_LAST) {
|
if (id > GLFW.GLFW_JOYSTICK_LAST) {
|
||||||
MidnightControlsClient.get().log("Controller '" + id + "' doesn't exist.");
|
MidnightControls.log("Controller '" + id + "' doesn't exist.");
|
||||||
id = GLFW.GLFW_JOYSTICK_LAST;
|
id = GLFW.GLFW_JOYSTICK_LAST;
|
||||||
}
|
}
|
||||||
Controller controller;
|
Controller controller;
|
||||||
@@ -121,11 +121,10 @@ public record Controller(int id) implements Nameable {
|
|||||||
* 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
|
|
||||||
* @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) throws IOException {
|
||||||
ByteBuffer buffer = null;
|
ByteBuffer buffer = null;
|
||||||
|
|
||||||
var path = Paths.get(resource);
|
var path = Paths.get(resource);
|
||||||
@@ -145,27 +144,22 @@ public record Controller(int id) implements Nameable {
|
|||||||
* Updates the controller mappings.
|
* Updates the controller mappings.
|
||||||
*/
|
*/
|
||||||
public static void updateMappings() {
|
public static void updateMappings() {
|
||||||
|
CompletableFuture.supplyAsync(Controller::updateMappingsSync);
|
||||||
|
}
|
||||||
|
private static boolean updateMappingsSync() {
|
||||||
try {
|
try {
|
||||||
MidnightControlsClient.get().log("Updating controller mappings...");
|
MidnightControls.log("Updating controller mappings...");
|
||||||
File databaseFile = new File("config/gamecontrollerdatabase.txt");
|
Optional<File> databaseFile = getDatabaseFile();
|
||||||
try {
|
if (databaseFile.isPresent()) {
|
||||||
BufferedInputStream in = new BufferedInputStream(new URL("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").openStream());
|
var database = ioResourceToBuffer(databaseFile.get().getPath());
|
||||||
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(databaseFile));
|
if (database != null) GLFW.glfwUpdateGamepadMappings(database);
|
||||||
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())
|
if (!MidnightControlsClient.MAPPINGS_FILE.exists())
|
||||||
return;
|
return false;
|
||||||
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024);
|
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath());
|
||||||
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
|
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.fillInStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
try (var memoryStack = MemoryStack.stackPush()) {
|
try (var memoryStack = MemoryStack.stackPush()) {
|
||||||
@@ -176,10 +170,10 @@ public record Controller(int id) implements Nameable {
|
|||||||
var string = l == 0L ? "" : MemoryUtil.memUTF8(l);
|
var string = l == 0L ? "" : MemoryUtil.memUTF8(l);
|
||||||
var 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.PERIODIC_NOTIFICATION,
|
||||||
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string)));
|
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string)));
|
||||||
MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
|
|
||||||
}
|
}
|
||||||
|
MidnightControls.log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
/* Ignored :concern: */
|
/* Ignored :concern: */
|
||||||
@@ -192,12 +186,28 @@ public record Controller(int id) implements Nameable {
|
|||||||
if (!controller.isConnected())
|
if (!controller.isConnected())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MidnightControls.get().log(String.format("Controller #%d name: \"%s\"\n GUID: %s\n Gamepad: %s",
|
MidnightControls.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(),
|
||||||
controller.isGamepad()));
|
controller.isGamepad()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Optional<File> getDatabaseFile() {
|
||||||
|
File databaseFile = new File("config/gamecontrollerdatabase.txt");
|
||||||
|
try {
|
||||||
|
BufferedInputStream in = new BufferedInputStream(URI.create("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").toURL().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 e) {return Optional.empty();}
|
||||||
|
return Optional.of(databaseFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
/*
|
||||||
|
* 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.controller;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.InventoryTabsCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.*;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.InventoryUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.ToggleSneakSprintUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.platform.ItemGroupUtil;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.TitleScreen;
|
||||||
|
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.*;
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||||
|
import net.minecraft.client.gui.widget.TabNavigationWidget;
|
||||||
|
import net.minecraft.client.util.ScreenshotRecorder;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.screen.slot.SlotActionType;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents some input handlers.
|
||||||
|
*
|
||||||
|
* @author LambdAurora
|
||||||
|
* @version 1.7.0
|
||||||
|
* @since 1.1.0
|
||||||
|
*/
|
||||||
|
public class InputHandlers {
|
||||||
|
private InputHandlers() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PressAction handleHotbar(boolean next) {
|
||||||
|
return (client, button, value, action) -> {
|
||||||
|
if (action == ButtonState.RELEASE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// When in-game
|
||||||
|
if (client.currentScreen == null && client.player != null) {
|
||||||
|
if (!client.player.isSpectator()) {
|
||||||
|
var inv = client.player.getInventory();
|
||||||
|
if (next)
|
||||||
|
inv.setSelectedSlot(inv.getSelectedSlot() < 8 ? inv.getSelectedSlot() + 1 : inv.getSelectedSlot() - 8);
|
||||||
|
else
|
||||||
|
inv.setSelectedSlot(inv.getSelectedSlot() > 0 ? inv.getSelectedSlot() - 1 : inv.getSelectedSlot() + 8);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (client.inGameHud.getSpectatorHud().isOpen()) {
|
||||||
|
client.inGameHud.getSpectatorHud().cycleSlot(next ? -1 : 1);
|
||||||
|
} else {
|
||||||
|
float g = MathHelper.clamp(client.player.getAbilities().getFlySpeed() + (next ? 1 : -1) * 0.005F, 0.0F, 0.2F);
|
||||||
|
client.player.getAbilities().setFlySpeed(g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (client.currentScreen instanceof RingScreen) {
|
||||||
|
MidnightControlsClient.ring.cyclePage(next);
|
||||||
|
} else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) {
|
||||||
|
inventory.midnightcontrols$setSelectedTab(ItemGroupUtil.cycleTab(next, client));
|
||||||
|
return true;
|
||||||
|
} else if (client.currentScreen instanceof RecipeBookScreen<?> recipeBookScreen) {
|
||||||
|
RecipeBookWidget<?> recipeBook = ((RecipeBookScreenAccessor) recipeBookScreen).getRecipeBook();
|
||||||
|
|
||||||
|
var recipeBookAccessor = (RecipeBookWidgetAccessor) recipeBook;
|
||||||
|
var tabs = recipeBookAccessor.getTabButtons();
|
||||||
|
var currentTab = recipeBookAccessor.getCurrentTab();
|
||||||
|
if (currentTab == null || !recipeBook.isOpen()) {
|
||||||
|
return MidnightControlsCompat.handleTabs(client.currentScreen, next);
|
||||||
|
}
|
||||||
|
int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1);
|
||||||
|
if (nextTab < 0)
|
||||||
|
nextTab = tabs.size() - 1;
|
||||||
|
else if (nextTab >= tabs.size())
|
||||||
|
nextTab = 0;
|
||||||
|
currentTab.setToggled(false);
|
||||||
|
recipeBookAccessor.setCurrentTab(currentTab = tabs.get(nextTab));
|
||||||
|
currentTab.setToggled(true);
|
||||||
|
recipeBookScreen.refreshRecipeBook();
|
||||||
|
return true;
|
||||||
|
} else if (client.currentScreen instanceof AdvancementsScreenAccessor screen) {
|
||||||
|
var tabs = screen.getTabs().values().stream().distinct().toList();
|
||||||
|
var tab = screen.getSelectedTab();
|
||||||
|
if (tab == null)
|
||||||
|
return false;
|
||||||
|
for (int i = 0; i < tabs.size(); i++) {
|
||||||
|
if (tabs.get(i).equals(tab)) {
|
||||||
|
int nextTab = i + (next ? 1 : -1);
|
||||||
|
if (nextTab < 0)
|
||||||
|
nextTab = tabs.size() - 1;
|
||||||
|
else if (nextTab >= tabs.size())
|
||||||
|
nextTab = 0;
|
||||||
|
screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot().getAdvancementEntry(), true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (client.currentScreen != null && client.currentScreen.children().stream().anyMatch(e -> e instanceof TabNavigationWidget)) {
|
||||||
|
return Lists.newCopyOnWriteArrayList(client.currentScreen.children()).stream().anyMatch(e -> {
|
||||||
|
if (e instanceof TabNavigationWidget tabs) {
|
||||||
|
TabNavigationWidgetAccessor accessor = (TabNavigationWidgetAccessor) tabs;
|
||||||
|
int tabIndex = accessor.getTabs().indexOf(accessor.getTabManager().getCurrentTab());
|
||||||
|
if (next ? tabIndex+1 < accessor.getTabs().size() : tabIndex > 0) {
|
||||||
|
if (next) tabs.selectTab(tabIndex + 1, true);
|
||||||
|
else tabs.selectTab(tabIndex - 1, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} else return MidnightControlsCompat.handleTabs(client.currentScreen, next);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PressAction handlePage(boolean next) {
|
||||||
|
return (client, button, value, action) -> {
|
||||||
|
if (action == ButtonState.RELEASE)
|
||||||
|
return false;
|
||||||
|
if (client.currentScreen instanceof CreativeInventoryScreen creativeScreen) {
|
||||||
|
return ItemGroupUtil.cyclePage(next, creativeScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return MidnightControlsCompat.handlePages(client.currentScreen, next);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static PressAction handleExit() {
|
||||||
|
return (client, button, value, action) -> {
|
||||||
|
if (client.currentScreen != null && client.currentScreen.getClass() != TitleScreen.class) {
|
||||||
|
if (!MidnightControlsCompat.handleMenuBack(client, client.currentScreen))
|
||||||
|
if (!MidnightControlsClient.input.tryGoBack(client.currentScreen))
|
||||||
|
client.currentScreen.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
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.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 = accessor.midnightcontrols$getSlotAt(x, y);
|
||||||
|
|
||||||
|
int slotId;
|
||||||
|
if (slot == null) {
|
||||||
|
if (button.getName().equals("take_all")) {
|
||||||
|
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.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "take" -> {
|
||||||
|
clickData = GLFW_MOUSE_BUTTON_2;
|
||||||
|
}
|
||||||
|
case "quick_move" -> {
|
||||||
|
actionType = SlotActionType.QUICK_MOVE;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
if (action == ButtonState.PRESS) {
|
||||||
|
// If in game, then pause the game.
|
||||||
|
if (client.currentScreen == null || client.currentScreen instanceof RingScreen)
|
||||||
|
client.openGameMenu(false);
|
||||||
|
else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it.
|
||||||
|
client.player.closeHandledScreen();
|
||||||
|
else // Else just close the current screen.
|
||||||
|
client.currentScreen.close();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the screenshot action.
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
* @param binding the binding which fired the action
|
||||||
|
* @param action the action done on the binding
|
||||||
|
* @return true if handled, else false
|
||||||
|
*/
|
||||||
|
public static boolean handleScreenshot(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) {
|
||||||
|
if (action == ButtonState.RELEASE)
|
||||||
|
ScreenshotRecorder.saveScreenshot(client.runDirectory, client.getFramebuffer(),
|
||||||
|
text -> client.execute(() -> client.inGameHud.getChatHud().addMessage(text)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||||
|
return ToggleSneakSprintUtil.toggleSneak(button);
|
||||||
|
}
|
||||||
|
public static boolean handleToggleSprint(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||||
|
return ToggleSneakSprintUtil.toggleSprint(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PressAction handleInventorySlotPad(int direction) {
|
||||||
|
return (client, binding, value, action) -> {
|
||||||
|
if (!(client.currentScreen instanceof HandledScreen<?> inventory && action != ButtonState.RELEASE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var accessor = (HandledScreenAccessor) inventory;
|
||||||
|
|
||||||
|
Optional<Slot> closestSlot = InventoryUtil.findClosestSlot(inventory, direction);
|
||||||
|
|
||||||
|
if (closestSlot.isPresent()) {
|
||||||
|
var slot = closestSlot.get();
|
||||||
|
int x = accessor.getX() + slot.x + 8;
|
||||||
|
int y = accessor.getY() + slot.y + 8;
|
||||||
|
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
|
||||||
|
y * (double) client.getWindow().getHeight() / (double) client.getWindow().getScaledHeight());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns always true to the filter.
|
||||||
|
*
|
||||||
|
* @param binding the affected binding
|
||||||
|
* @return true
|
||||||
|
*/
|
||||||
|
public static boolean always(@NotNull ButtonBinding binding) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the client is in game or not.
|
||||||
|
*
|
||||||
|
* @param binding the affected binding
|
||||||
|
* @return true if the client is in game, else false
|
||||||
|
*/
|
||||||
|
public static boolean inGame(@NotNull ButtonBinding binding) {
|
||||||
|
return (client.currentScreen == null && MidnightControlsClient.input.screenCloseCooldown <= 0) || client.currentScreen instanceof TouchscreenOverlay || client.currentScreen instanceof RingScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the client is in a non-interactive screen (which means require mouse input) or not.
|
||||||
|
*
|
||||||
|
* @param binding the affected binding
|
||||||
|
* @return true if the client is in a non-interactive screen, else false
|
||||||
|
*/
|
||||||
|
public static boolean inNonInteractiveScreens(@NotNull ButtonBinding binding) {
|
||||||
|
if (client.currentScreen == null)
|
||||||
|
return false;
|
||||||
|
return !MidnightInput.isScreenInteractive(client.currentScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the client is in an inventory or not.
|
||||||
|
*
|
||||||
|
* @param binding the affected binding
|
||||||
|
* @return true if the client is in an inventory, else false
|
||||||
|
*/
|
||||||
|
public static boolean inInventory(@NotNull ButtonBinding binding) {
|
||||||
|
return client.currentScreen instanceof HandledScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the client is in the advancements screen or not.
|
||||||
|
*
|
||||||
|
* @param binding the affected binding
|
||||||
|
* @return true if the client is in the advancements screen, else false
|
||||||
|
*/
|
||||||
|
public static boolean inAdvancements(@NotNull ButtonBinding binding) {
|
||||||
|
return client.currentScreen instanceof AdvancementsScreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,26 +10,28 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
|
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
|
||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.option.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import org.aperlambda.lambdacommon.Identifier;
|
|
||||||
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;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an input manager for controllers.
|
* Represents an input manager for controllers.
|
||||||
*
|
*
|
||||||
@@ -51,17 +53,17 @@ public class InputManager {
|
|||||||
protected InputManager() {
|
protected InputManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick(@NotNull MinecraftClient client) {
|
public void tick() {
|
||||||
if (MidnightControlsConfig.autoSwitchMode && !MidnightControlsConfig.isEditing && MidnightControlsConfig.controlsMode != ControlsMode.TOUCHSCREEN)
|
if (MidnightControlsConfig.autoSwitchMode && !MidnightControlsConfig.isEditing && MidnightControlsConfig.controlsMode != ControlsMode.TOUCHSCREEN)
|
||||||
if (MidnightControlsConfig.getController().isConnected() && MidnightControlsConfig.getController().isGamepad())
|
if (MidnightControlsConfig.getController().isConnected() && MidnightControlsConfig.getController().isGamepad())
|
||||||
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||||
else MidnightControlsConfig.controlsMode = ControlsMode.DEFAULT;
|
else MidnightControlsConfig.controlsMode = ControlsMode.DEFAULT;
|
||||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||||
this.controllerTick(client);
|
this.controllerTick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void controllerTick(@NotNull MinecraftClient client) {
|
public void controllerTick() {
|
||||||
this.prevTargetMouseX = this.targetMouseX;
|
this.prevTargetMouseX = this.targetMouseX;
|
||||||
this.prevTargetMouseY = this.targetMouseY;
|
this.prevTargetMouseY = this.targetMouseY;
|
||||||
}
|
}
|
||||||
@@ -74,8 +76,8 @@ public class InputManager {
|
|||||||
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.getRenderTickCounter().getTickProgress(true) + 0.5;
|
||||||
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getTickDelta() + 0.5;
|
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getRenderTickCounter().getTickProgress(true) + 0.5;
|
||||||
if (!MidnightControlsConfig.virtualMouse)
|
if (!MidnightControlsConfig.virtualMouse)
|
||||||
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
||||||
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
||||||
@@ -127,7 +129,7 @@ public class InputManager {
|
|||||||
* @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.getPath());
|
||||||
}
|
}
|
||||||
private static ButtonBinding tempBinding;
|
private static ButtonBinding tempBinding;
|
||||||
/**
|
/**
|
||||||
@@ -166,19 +168,21 @@ public class InputManager {
|
|||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
@Deprecated
|
||||||
return registerBinding(new ButtonBinding(id.getNamespace() + "." + id.getName(), defaultButton, actions, filter, hasCooldown));
|
public static @NotNull ButtonBinding registerBinding(@NotNull org.aperlambda.lambdacommon.Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull Predicate<ButtonBinding> filter, boolean hasCooldown) {
|
||||||
|
return registerBinding(Identifier.of(id.getNamespace(), id.getName()), defaultButton, actions, filter, hasCooldown);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, boolean hasCooldown) {
|
@Deprecated
|
||||||
|
public static @NotNull ButtonBinding registerBinding(@NotNull org.aperlambda.lambdacommon.Identifier id, int[] defaultButton, boolean hasCooldown) {
|
||||||
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
|
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull net.minecraft.util.Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull Predicate<ButtonBinding> filter, boolean hasCooldown) {
|
||||||
return registerBinding(new Identifier(id.getNamespace(), id.getPath()), defaultButton, actions, filter, hasCooldown);
|
return registerBinding(new ButtonBinding(id.getNamespace() + "." + id.getPath(), defaultButton, actions, filter, hasCooldown));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull net.minecraft.util.Identifier id, int[] defaultButton, boolean hasCooldown) {
|
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, boolean hasCooldown) {
|
||||||
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
|
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +208,13 @@ public class InputManager {
|
|||||||
CATEGORIES.add(category);
|
CATEGORIES.add(category);
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
|
public static ButtonCategory registerCategory(@NotNull org.aperlambda.lambdacommon.Identifier identifier, int priority) {
|
||||||
|
return registerCategory(Identifier.of(identifier.getNamespace(), identifier.getName()), priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ButtonCategory registerCategory(@NotNull org.aperlambda.lambdacommon.Identifier identifier) {
|
||||||
|
return registerCategory(Identifier.of(identifier.getNamespace(), identifier.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
public static ButtonCategory registerCategory(@NotNull Identifier identifier, int priority) {
|
public static ButtonCategory registerCategory(@NotNull Identifier identifier, int priority) {
|
||||||
return registerCategory(new ButtonCategory(identifier, priority));
|
return registerCategory(new ButtonCategory(identifier, priority));
|
||||||
@@ -214,7 +225,7 @@ 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) {
|
||||||
var category = registerCategory(new Identifier("minecraft", key), CATEGORIES.size());
|
var category = registerCategory(Identifier.of("minecraft", key), CATEGORIES.size());
|
||||||
keyAdder.accept(category);
|
keyAdder.accept(category);
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
@@ -331,27 +342,27 @@ public class InputManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateBindings(@NotNull MinecraftClient client) {
|
public static void updateBindings() {
|
||||||
var skipButtons = new IntArrayList();
|
var skipButtons = new IntArrayList();
|
||||||
record ButtonStateValue(ButtonState state, float value) {
|
record ButtonStateValue(ButtonState state, float value) {
|
||||||
}
|
}
|
||||||
var states = new Object2ObjectOpenHashMap<ButtonBinding, ButtonStateValue>();
|
var states = new Object2ObjectOpenHashMap<ButtonBinding, ButtonStateValue>();
|
||||||
for (var binding : BINDINGS) {
|
for (var binding : BINDINGS) {
|
||||||
var state = binding.isAvailable(client) ? getBindingState(binding) : ButtonState.NONE;
|
var state = binding.isAvailable() ? getBindingState(binding) : ButtonState.NONE;
|
||||||
if (skipButtons.intStream().anyMatch(btn -> containsButton(binding.getButton(), btn))) {
|
if (skipButtons.intStream().anyMatch(btn -> containsButton(binding.getButton(), btn))) {
|
||||||
if (binding.pressed)
|
if (binding.isPressed())
|
||||||
state = ButtonState.RELEASE;
|
state = ButtonState.RELEASE;
|
||||||
else
|
else
|
||||||
state = ButtonState.NONE;
|
state = ButtonState.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == ButtonState.RELEASE && !binding.pressed) {
|
if (state == ButtonState.RELEASE && !binding.isPressed()) {
|
||||||
state = ButtonState.NONE;
|
state = ButtonState.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.pressed = state.isPressed();
|
binding.setPressed(state.isPressed());
|
||||||
binding.update();
|
binding.update();
|
||||||
if (binding.pressed)
|
if (binding.isPressed())
|
||||||
Arrays.stream(binding.getButton()).forEach(skipButtons::add);
|
Arrays.stream(binding.getButton()).forEach(skipButtons::add);
|
||||||
|
|
||||||
float value = getBindingValue(binding, state);
|
float value = getBindingValue(binding, state);
|
||||||
@@ -393,21 +404,7 @@ public class InputManager {
|
|||||||
* @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) {
|
|
||||||
return makeKeyBinding(new Identifier(id.getNamespace(), id.getPath()), type, code, category);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new key binding instance.
|
|
||||||
*
|
|
||||||
* @param id the identifier of the key binding
|
|
||||||
* @param type the type
|
|
||||||
* @param code the code
|
|
||||||
* @param category the category of the key binding
|
|
||||||
* @return the key binding
|
|
||||||
* @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) {
|
||||||
return new KeyBinding(String.format("key.%s.%s", id.getNamespace(), id.getName()), type, code, category);
|
return new KeyBinding(String.format("key.%s.%s", id.getNamespace(), id.getPath()), type, code, category);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,21 +9,16 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.InputAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
|
||||||
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.entity.attribute.EntityAttributes;
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.util.PlayerInput;
|
||||||
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 net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec2f;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,6 +38,7 @@ public final class MovementHandler implements PressAction {
|
|||||||
private float slowdownFactor = 1.f;
|
private float slowdownFactor = 1.f;
|
||||||
private float movementForward = 0.f;
|
private float movementForward = 0.f;
|
||||||
private float movementSideways = 0.f;
|
private float movementSideways = 0.f;
|
||||||
|
private final MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil();
|
||||||
|
|
||||||
private MovementHandler() {
|
private MovementHandler() {
|
||||||
}
|
}
|
||||||
@@ -53,21 +49,14 @@ public final class MovementHandler implements PressAction {
|
|||||||
* @param player The client player.
|
* @param player The client player.
|
||||||
*/
|
*/
|
||||||
public void applyMovement(@NotNull ClientPlayerEntity player) {
|
public void applyMovement(@NotNull ClientPlayerEntity player) {
|
||||||
double movementR, movementTheta;
|
|
||||||
|
|
||||||
if (!this.shouldOverrideMovement)
|
if (!this.shouldOverrideMovement)
|
||||||
return;
|
return;
|
||||||
player.input.pressingForward = this.pressingForward;
|
player.input.playerInput = new PlayerInput(this.pressingForward, this.pressingBack, this.pressingLeft, this.pressingRight,
|
||||||
player.input.pressingBack = this.pressingBack;
|
player.input.playerInput.jump(), player.input.playerInput.sneak(), player.input.playerInput.sprint());
|
||||||
player.input.pressingLeft = this.pressingLeft;
|
|
||||||
player.input.pressingRight = this.pressingRight;
|
|
||||||
|
|
||||||
// Do an implicit square here
|
polarUtil.calculate(this.movementSideways, this.movementForward, this.slowdownFactor);
|
||||||
movementR = this.slowdownFactor * (Math.pow(this.movementSideways, 2) + Math.pow(this.movementForward, 2));
|
Vec2f inputVector = new Vec2f(polarUtil.polarX, polarUtil.polarY);
|
||||||
movementR = MathHelper.clamp(movementR, 0.f, 1.f);
|
((InputAccessor)player.input).setMovementVector(inputVector);
|
||||||
movementTheta = Math.atan2(this.movementForward, this.movementSideways);
|
|
||||||
player.input.movementForward = (float) (movementR * Math.sin(movementTheta));
|
|
||||||
player.input.movementSideways = (float) (movementR * Math.cos(movementTheta));
|
|
||||||
|
|
||||||
this.shouldOverrideMovement = false;
|
this.shouldOverrideMovement = false;
|
||||||
}
|
}
|
||||||
@@ -93,7 +82,7 @@ public final class MovementHandler implements PressAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.slowdownFactor = client.player.shouldSlowDown() ? (MathHelper.clamp(
|
this.slowdownFactor = client.player.shouldSlowDown() ? (MathHelper.clamp(
|
||||||
0.3F + EnchantmentHelper.getSwiftSneakSpeedBoost(client.player),
|
0.3F + (float) client.player.getAttributeValue(EntityAttributes.SNEAKING_SPEED),
|
||||||
0.0F,
|
0.0F,
|
||||||
1.0F
|
1.0F
|
||||||
)) : 1.f;
|
)) : 1.f;
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.option.StickyKeyBinding;
|
import net.minecraft.client.option.StickyKeyBinding;
|
||||||
@@ -29,9 +29,9 @@ public interface PressAction {
|
|||||||
return false;
|
return false;
|
||||||
button.asKeyBinding().ifPresent(binding -> {
|
button.asKeyBinding().ifPresent(binding -> {
|
||||||
if (binding instanceof StickyKeyBinding)
|
if (binding instanceof StickyKeyBinding)
|
||||||
binding.setPressed(button.pressed);
|
binding.setPressed(button.isPressed());
|
||||||
else
|
else
|
||||||
((KeyBindingAccessor) binding).midnightcontrols$handlePressState(button.isButtonDown());
|
((KeyBindingAccessor) binding).midnightcontrols$handlePressState(button.isPressed());
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client;
|
package eu.midnightdust.midnightcontrols.client.enums;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a button state.
|
* Represents a button state.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.enums;
|
||||||
|
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public enum CameraMode {
|
||||||
|
FLAT, ADAPTIVE;
|
||||||
|
public Text getTranslatedText() {
|
||||||
|
return Text.translatable("midnightcontrols.midnightconfig.enum."+this.getClass().getSimpleName()+"."+this.name());
|
||||||
|
}
|
||||||
|
public @NotNull CameraMode next() {
|
||||||
|
var v = values();
|
||||||
|
if (v.length == this.ordinal() + 1)
|
||||||
|
return v[0];
|
||||||
|
return v[this.ordinal() + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,10 +7,9 @@
|
|||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client;
|
package eu.midnightdust.midnightcontrols.client.enums;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -23,7 +22,7 @@ import java.util.Optional;
|
|||||||
* @version 1.4.3
|
* @version 1.4.3
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum ControllerType implements Nameable {
|
public enum ControllerType {
|
||||||
DEFAULT(0),
|
DEFAULT(0),
|
||||||
DUALSHOCK(1),
|
DUALSHOCK(1),
|
||||||
DUALSENSE(2),
|
DUALSENSE(2),
|
||||||
@@ -78,7 +77,6 @@ public enum ControllerType implements Nameable {
|
|||||||
return this.text;
|
return this.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.name().toLowerCase();
|
return this.name().toLowerCase();
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client;
|
package eu.midnightdust.midnightcontrols.client.enums;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||||
@@ -23,7 +23,7 @@ import java.util.Optional;
|
|||||||
* @version 1.4.0
|
* @version 1.4.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum HudSide implements Nameable {
|
public enum HudSide {
|
||||||
LEFT,
|
LEFT,
|
||||||
RIGHT;
|
RIGHT;
|
||||||
|
|
||||||
@@ -63,9 +63,8 @@ public enum HudSide implements Nameable {
|
|||||||
return this.text;
|
return this.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.name().toLowerCase();
|
return this.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,6 +73,7 @@ public enum HudSide implements Nameable {
|
|||||||
* @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
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
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,17 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.enums;
|
||||||
|
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public enum TouchMode {
|
||||||
|
CROSSHAIR, FINGER_POS;
|
||||||
|
public Text getTranslatedText() {
|
||||||
|
return Text.translatable("midnightcontrols.midnightconfig.enum."+this.getClass().getSimpleName()+"."+this.name());
|
||||||
|
}
|
||||||
|
public @NotNull TouchMode next() {
|
||||||
|
var v = values();
|
||||||
|
if (v.length == this.ordinal() + 1)
|
||||||
|
return v[0];
|
||||||
|
return v[this.ordinal() + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,10 +7,9 @@
|
|||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client;
|
package eu.midnightdust.midnightcontrols.client.enums;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -22,7 +21,7 @@ import java.util.Optional;
|
|||||||
* @version 1.7.0
|
* @version 1.7.0
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public enum VirtualMouseSkin implements Nameable {
|
public enum VirtualMouseSkin {
|
||||||
DEFAULT_LIGHT("default_light"),
|
DEFAULT_LIGHT("default_light"),
|
||||||
DEFAULT_DARK("default_dark"),
|
DEFAULT_DARK("default_dark"),
|
||||||
SECOND_LIGHT("second_light"),
|
SECOND_LIGHT("second_light"),
|
||||||
@@ -66,7 +65,6 @@ public enum VirtualMouseSkin implements Nameable {
|
|||||||
return this.text;
|
return this.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
@@ -77,7 +75,16 @@ public enum VirtualMouseSkin implements Nameable {
|
|||||||
* @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
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
public String getSpritePath() {
|
||||||
|
return switch (this) {
|
||||||
|
case DEFAULT_LIGHT -> "cursor/light/default";
|
||||||
|
case DEFAULT_DARK -> "cursor/dark/default";
|
||||||
|
case SECOND_LIGHT -> "cursor/light/secondary";
|
||||||
|
case SECOND_DARK -> "cursor/dark/secondary";
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,11 +10,15 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import dev.lambdaurora.spruceui.Position;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import dev.lambdaurora.spruceui.option.SpruceOption;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
import dev.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
|
import org.thinkingstudio.obsidianui.option.SpruceOption;
|
||||||
|
import org.thinkingstudio.obsidianui.option.SpruceSimpleActionOption;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.text.SpruceTextAreaWidget;
|
||||||
import net.minecraft.client.toast.SystemToast;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
@@ -30,17 +34,18 @@ import java.nio.file.Files;
|
|||||||
* @since 1.4.3
|
* @since 1.4.3
|
||||||
*/
|
*/
|
||||||
public class MappingsStringInputWidget extends SpruceContainerWidget {
|
public class MappingsStringInputWidget extends SpruceContainerWidget {
|
||||||
|
private final SpruceOption copyGuidOption;
|
||||||
private final SpruceOption reloadMappingsOption;
|
private final SpruceOption reloadMappingsOption;
|
||||||
private String mappings;
|
private String mappings;
|
||||||
private SpruceTextAreaWidget textArea;
|
private SpruceTextAreaWidget textArea;
|
||||||
|
|
||||||
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("midnightcontrols.menu.title.mappings.string"));
|
|
||||||
|
|
||||||
this.reloadMappingsOption = ReloadControllerMappingsOption.newOption(btn -> {
|
this.reloadMappingsOption = ReloadControllerMappingsOption.newOption(btn -> {
|
||||||
this.writeMappings();
|
this.writeMappings();
|
||||||
});
|
});
|
||||||
|
this.copyGuidOption = SpruceSimpleActionOption.of("midnightcontrols.menu.copy_controller_guid", button -> client.keyboard.setClipboard(MidnightControlsConfig.getController().getGuid()));
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
@@ -63,9 +68,9 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
|||||||
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.PERIODIC_NOTIFICATION,
|
||||||
Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty()));
|
Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty()));
|
||||||
e.printStackTrace();
|
e.fillInStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,10 +100,14 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
|||||||
this.textArea.setDisplayedLines(this.textArea.getInnerHeight() / this.client.textRenderer.fontHeight);
|
this.textArea.setDisplayedLines(this.textArea.getInnerHeight() / this.client.textRenderer.fontHeight);
|
||||||
this.addChild(this.textArea);
|
this.addChild(this.textArea);
|
||||||
|
|
||||||
this.addChild(this.reloadMappingsOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 310));
|
this.addChild(this.reloadMappingsOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 257));
|
||||||
|
this.addChild(this.copyGuidOption.createWidget(Position.of(this.width / 2 + 105, this.height - 29), 65));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public void renderTitle(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
@Override
|
||||||
drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 8, 16777215);
|
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
}*/
|
super.renderWidget(context, mouseX, mouseY, delta);
|
||||||
|
context.drawCenteredTextWithShadow(this.client.textRenderer, Text.translatable("midnightcontrols.menu.multiple_mapping_tip"), this.textArea.getX() + this.textArea.getWidth() / 2, this.textArea.getY() + this.textArea.getHeight() - 12, 0x888888);
|
||||||
|
context.drawCenteredTextWithShadow(this.client.textRenderer, Text.translatable("midnightcontrols.menu.current_controller_guid", MidnightControlsConfig.getController().getGuid()), this.textArea.getX() + this.textArea.getWidth() / 2, this.height - 21, 0xFFFFFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,24 +10,26 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
|
||||||
import eu.midnightdust.midnightcontrols.client.HudSide;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import dev.lambdaurora.spruceui.hud.Hud;
|
import net.minecraft.client.render.RenderTickCounter;
|
||||||
|
import org.thinkingstudio.obsidianui.hud.Hud;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
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.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import net.minecraft.util.hit.HitResult;
|
import net.minecraft.util.hit.HitResult;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the midnightcontrols HUD.
|
* Represents the midnightcontrols HUD.
|
||||||
*
|
*
|
||||||
@@ -36,8 +38,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public class MidnightControlsHud extends Hud {
|
public class MidnightControlsHud extends Hud {
|
||||||
private final MidnightControlsClient mod;
|
private MinecraftClient client = MinecraftClient.getInstance();
|
||||||
private MinecraftClient client;
|
|
||||||
private int attackWidth = 0;
|
private int attackWidth = 0;
|
||||||
private int attackButtonWidth = 0;
|
private int attackButtonWidth = 0;
|
||||||
private int dropItemWidth = 0;
|
private int dropItemWidth = 0;
|
||||||
@@ -49,21 +50,19 @@ public class MidnightControlsHud extends Hud {
|
|||||||
private boolean showSwapHandsAction = false;
|
private boolean showSwapHandsAction = false;
|
||||||
private int useWidth = 0;
|
private int useWidth = 0;
|
||||||
private int useButtonWidth = 0;
|
private int useButtonWidth = 0;
|
||||||
private BlockHitResult placeHitResult;
|
|
||||||
private String attackAction = "";
|
private String attackAction = "";
|
||||||
private String placeAction = "";
|
private String placeAction = "";
|
||||||
private int ticksDisplayedCrosshair = 0;
|
private int ticksDisplayedCrosshair = 0;
|
||||||
private static boolean isCrammed = false;
|
private static boolean isCrammed = false;
|
||||||
|
|
||||||
public MidnightControlsHud(@NotNull MidnightControlsClient mod) {
|
public MidnightControlsHud() {
|
||||||
super(new Identifier(MidnightControlsConstants.NAMESPACE, "hud/button_indicator"));
|
super(id("hud/button_indicator"));
|
||||||
this.mod = mod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(@NotNull MinecraftClient client, int screenWidth, int screenHeight) {
|
public void init(@NotNull MinecraftClient client, int screenWidth, int screenHeight) {
|
||||||
|
this.client = MinecraftClient.getInstance();
|
||||||
super.init(client, screenWidth, screenHeight);
|
super.init(client, screenWidth, screenHeight);
|
||||||
this.client = client;
|
|
||||||
this.inventoryWidth = this.width(ButtonBinding.INVENTORY);
|
this.inventoryWidth = this.width(ButtonBinding.INVENTORY);
|
||||||
this.inventoryButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY);
|
this.inventoryButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY);
|
||||||
this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS);
|
this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS);
|
||||||
@@ -79,38 +78,39 @@ public class MidnightControlsHud extends Hud {
|
|||||||
* Renders the MidnightControls HUD.
|
* Renders the MidnightControls HUD.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void render(MatrixStack matrices, float tickDelta) {
|
public void render(DrawContext context, RenderTickCounter tickCounter) {
|
||||||
if (this.client == null) return;
|
if (this.client == null) return;
|
||||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && this.client.currentScreen == null) {
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && this.client.currentScreen == null) {
|
||||||
isCrammed = client.getWindow().getScaledWidth() < 520;
|
isCrammed = client.getWindow().getScaledWidth() < 520;
|
||||||
int y = bottom(2);
|
int y = bottom(2);
|
||||||
|
MatrixStack matrices = context.getMatrices();
|
||||||
matrices.push();
|
matrices.push();
|
||||||
this.renderFirstIcons(matrices, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
this.renderFirstIcons(context, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||||
this.renderSecondIcons(matrices, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
this.renderSecondIcons(context, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||||
this.renderFirstSection(matrices, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
this.renderFirstSection(context, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||||
this.renderSecondSection(matrices, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
this.renderSecondSection(context, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mod.reacharound.isLastReacharoundVertical()) {
|
if (MidnightControlsClient.reacharound.isLastReacharoundVertical()) {
|
||||||
// Render crosshair indicator.
|
// Render crosshair indicator.
|
||||||
var window = this.client.getWindow();
|
var window = this.client.getWindow();
|
||||||
var text = "[ ]";
|
var text = "[ ]";
|
||||||
|
|
||||||
float scale = Math.min(5, this.ticksDisplayedCrosshair + tickDelta) / 5F;
|
float scale = Math.min(5, this.ticksDisplayedCrosshair + tickCounter.getTickProgress(true)) / 5F;
|
||||||
scale *= scale;
|
scale *= scale;
|
||||||
int opacity = ((int) (255 * scale)) << 24;
|
int opacity = ((int) (255 * scale)) << 24;
|
||||||
|
|
||||||
this.client.textRenderer.draw(matrices, text, window.getScaledWidth() / 2.f - this.client.textRenderer.getWidth(text) / 2.f,
|
context.drawText(client.textRenderer, text, (int) (window.getScaledWidth() / 2.f - this.client.textRenderer.getWidth(text) / 2.f),
|
||||||
window.getScaledHeight() / 2.f - 4, 0xCCCCCC | opacity);
|
(int) (window.getScaledHeight() / 2.f - 4), 0xCCCCCC | opacity, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderFirstIcons(MatrixStack matrices, int x, int y) {
|
public void renderFirstIcons(DrawContext context, int x, int y) {
|
||||||
int offset = 2 + this.inventoryWidth + this.inventoryButtonWidth + 4;
|
int offset = 2 + this.inventoryWidth + this.inventoryButtonWidth + 4;
|
||||||
int currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.inventoryButtonWidth;
|
int currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.inventoryButtonWidth;
|
||||||
if (!ButtonBinding.INVENTORY.isNotBound()) this.drawButton(matrices, currentX, y, ButtonBinding.INVENTORY, true);
|
if (!ButtonBinding.INVENTORY.isNotBound()) this.drawButton(context, currentX, y, ButtonBinding.INVENTORY, true);
|
||||||
if (!ButtonBinding.SWAP_HANDS.isNotBound() && !isCrammed && showSwapHandsAction) this.drawButton(matrices, currentX += (MidnightControlsConfig.hudSide == HudSide.LEFT ? offset : -offset), y, ButtonBinding.SWAP_HANDS, true);
|
if (!ButtonBinding.SWAP_HANDS.isNotBound() && !isCrammed && showSwapHandsAction) this.drawButton(context, 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.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
||||||
currentX += -offset;
|
currentX += -offset;
|
||||||
@@ -118,23 +118,24 @@ public class MidnightControlsHud extends Hud {
|
|||||||
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.dropItemButtonWidth;
|
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.dropItemButtonWidth;
|
||||||
y -= 20;
|
y -= 20;
|
||||||
}
|
}
|
||||||
if (!ButtonBinding.DROP_ITEM.isNotBound()) this.drawButton(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
if (!ButtonBinding.DROP_ITEM.isNotBound() && client.player != null)
|
||||||
|
this.drawButton(context, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderSecondIcons(MatrixStack matrices, int x, int y) {
|
public void renderSecondIcons(DrawContext context, int x, int y) {
|
||||||
int offset;
|
int offset;
|
||||||
int currentX = x;
|
int currentX = x;
|
||||||
if (isCrammed && showSwapHandsAction && !this.client.options.getShowSubtitles().getValue() && !ButtonBinding.SWAP_HANDS.isNotBound()) {
|
if (isCrammed && showSwapHandsAction && !this.client.options.getShowSubtitles().getValue() && !ButtonBinding.SWAP_HANDS.isNotBound()) {
|
||||||
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
||||||
currentX -= this.useButtonWidth;
|
currentX -= this.useButtonWidth;
|
||||||
this.drawButton(matrices, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
this.drawButton(context, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
||||||
currentX = x;
|
currentX = x;
|
||||||
y -= 20;
|
y -= 20;
|
||||||
}
|
}
|
||||||
if (!this.placeAction.isEmpty() && (!ButtonBinding.USE.isNotBound()) ) {
|
if (!this.placeAction.isEmpty() && (!ButtonBinding.USE.isNotBound()) ) {
|
||||||
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
||||||
currentX -= this.useButtonWidth;
|
currentX -= this.useButtonWidth;
|
||||||
this.drawButton(matrices, currentX, y, ButtonBinding.USE, true);
|
this.drawButton(context, currentX, y, ButtonBinding.USE, true);
|
||||||
offset = 2 + this.useWidth + 4;
|
offset = 2 + this.useWidth + 4;
|
||||||
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||||
currentX -= offset;
|
currentX -= offset;
|
||||||
@@ -147,31 +148,31 @@ public class MidnightControlsHud extends Hud {
|
|||||||
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
||||||
currentX -= this.attackButtonWidth;
|
currentX -= this.attackButtonWidth;
|
||||||
|
|
||||||
if (!ButtonBinding.ATTACK.isNotBound()) this.drawButton(matrices, currentX, y, ButtonBinding.ATTACK, this.attackWidth != 0);
|
if (!ButtonBinding.ATTACK.isNotBound()) this.drawButton(context, currentX, y, ButtonBinding.ATTACK, this.attackWidth != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderFirstSection(MatrixStack matrices, int x, int y) {
|
public void renderFirstSection(DrawContext context, int x, int y) {
|
||||||
int currentX = MidnightControlsConfig.hudSide == 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;
|
||||||
if (!ButtonBinding.INVENTORY.isNotBound()) this.drawTip(matrices, currentX, y, ButtonBinding.INVENTORY, true);
|
if (!ButtonBinding.INVENTORY.isNotBound()) this.drawTip(context, currentX, y, ButtonBinding.INVENTORY, true);
|
||||||
currentX += MidnightControlsConfig.hudSide == 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;
|
||||||
if (!ButtonBinding.SWAP_HANDS.isNotBound() && !isCrammed && showSwapHandsAction) this.drawTip(matrices, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
if (!ButtonBinding.SWAP_HANDS.isNotBound() && !isCrammed && showSwapHandsAction) this.drawTip(context, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
||||||
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
||||||
currentX += -this.dropItemWidth - 2 - this.dropItemButtonWidth - 4;
|
currentX += -this.dropItemWidth - 2 - this.dropItemButtonWidth - 4;
|
||||||
} else {
|
} else {
|
||||||
y -= 20;
|
y -= 20;
|
||||||
currentX = MidnightControlsConfig.hudSide == 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;
|
||||||
}
|
}
|
||||||
if (!ButtonBinding.DROP_ITEM.isNotBound()) this.drawTip(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
if (!ButtonBinding.DROP_ITEM.isNotBound() && client.player != null) this.drawTip(context, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderSecondSection(MatrixStack matrices, int x, int y) {
|
public void renderSecondSection(DrawContext context, int x, int y) {
|
||||||
int currentX = x;
|
int currentX = x;
|
||||||
|
|
||||||
if (isCrammed && showSwapHandsAction && !this.client.options.getShowSubtitles().getValue() && !ButtonBinding.SWAP_HANDS.isNotBound()) {
|
if (isCrammed && showSwapHandsAction && !this.client.options.getShowSubtitles().getValue() && !ButtonBinding.SWAP_HANDS.isNotBound()) {
|
||||||
currentX += MidnightControlsConfig.hudSide == HudSide.RIGHT ? this.swapHandsButtonWidth + 2 : -this.swapHandsButtonWidth - 2 - this.swapHandsWidth;
|
currentX += MidnightControlsConfig.hudSide == HudSide.RIGHT ? this.swapHandsButtonWidth + 2 : -this.swapHandsButtonWidth - 2 - this.swapHandsWidth;
|
||||||
|
|
||||||
this.drawTip(matrices, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
this.drawTip(context, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
||||||
|
|
||||||
currentX = x;
|
currentX = x;
|
||||||
y -= 20;
|
y -= 20;
|
||||||
@@ -179,7 +180,7 @@ public class MidnightControlsHud extends Hud {
|
|||||||
if (!this.placeAction.isEmpty()) {
|
if (!this.placeAction.isEmpty()) {
|
||||||
currentX += MidnightControlsConfig.hudSide == 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(context, currentX, y, this.placeAction, true);
|
||||||
|
|
||||||
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||||
currentX -= 4;
|
currentX -= 4;
|
||||||
@@ -191,11 +192,12 @@ public class MidnightControlsHud extends Hud {
|
|||||||
|
|
||||||
currentX += MidnightControlsConfig.hudSide == HudSide.RIGHT ? this.attackButtonWidth + 2 : -this.attackButtonWidth - 2 - this.attackWidth;
|
currentX += MidnightControlsConfig.hudSide == HudSide.RIGHT ? this.attackButtonWidth + 2 : -this.attackButtonWidth - 2 - this.attackWidth;
|
||||||
|
|
||||||
if (!ButtonBinding.ATTACK.isNotBound()) this.drawTip(matrices, currentX, y, this.attackAction, this.attackWidth != 0);
|
if (!ButtonBinding.ATTACK.isNotBound()) this.drawTip(context, currentX, y, this.attackAction, this.attackWidth != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (this.client == null) return;
|
||||||
super.tick();
|
super.tick();
|
||||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||||
if (this.client.crosshairTarget == null)
|
if (this.client.crosshairTarget == null)
|
||||||
@@ -204,28 +206,29 @@ public class MidnightControlsHud extends Hud {
|
|||||||
String placeAction;
|
String placeAction;
|
||||||
|
|
||||||
// Update "Use" tip status.
|
// Update "Use" tip status.
|
||||||
|
BlockHitResult placeHitResult;
|
||||||
if (this.client.crosshairTarget.getType() == HitResult.Type.MISS) {
|
if (this.client.crosshairTarget.getType() == HitResult.Type.MISS) {
|
||||||
this.placeHitResult = this.mod.reacharound.getLastReacharoundResult();
|
placeHitResult = MidnightControlsClient.reacharound.getLastReacharoundResult();
|
||||||
this.attackAction = "";
|
this.attackAction = "";
|
||||||
this.attackWidth = 0;
|
this.attackWidth = 0;
|
||||||
} else {
|
} else {
|
||||||
if (this.client.crosshairTarget.getType() == HitResult.Type.BLOCK)
|
if (this.client.crosshairTarget.getType() == HitResult.Type.BLOCK)
|
||||||
this.placeHitResult = (BlockHitResult) this.client.crosshairTarget;
|
placeHitResult = (BlockHitResult) this.client.crosshairTarget;
|
||||||
else
|
else
|
||||||
this.placeHitResult = null;
|
placeHitResult = null;
|
||||||
|
|
||||||
this.attackAction = this.client.crosshairTarget.getType() == HitResult.Type.BLOCK ? "midnightcontrols.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.mod.reacharound.isLastReacharoundVertical()) {
|
if (MidnightControlsClient.reacharound.isLastReacharoundVertical()) {
|
||||||
if (this.ticksDisplayedCrosshair < 5)
|
if (this.ticksDisplayedCrosshair < 5)
|
||||||
this.ticksDisplayedCrosshair++;
|
this.ticksDisplayedCrosshair++;
|
||||||
} else {
|
} else {
|
||||||
this.ticksDisplayedCrosshair = 0;
|
this.ticksDisplayedCrosshair = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var customAttackAction = MidnightControlsCompat.getAttackActionAt(this.client, this.placeHitResult);
|
var customAttackAction = MidnightControlsCompat.getAttackActionAt(this.client, placeHitResult);
|
||||||
if (customAttackAction != null) {
|
if (customAttackAction != null) {
|
||||||
this.attackAction = customAttackAction;
|
this.attackAction = customAttackAction;
|
||||||
this.attackWidth = this.width(customAttackAction);
|
this.attackWidth = this.width(customAttackAction);
|
||||||
@@ -240,14 +243,14 @@ public class MidnightControlsHud extends Hud {
|
|||||||
if (stack == null || stack.isEmpty()) {
|
if (stack == null || stack.isEmpty()) {
|
||||||
placeAction = "";
|
placeAction = "";
|
||||||
} else {
|
} else {
|
||||||
if (this.placeHitResult != null && stack.getItem() instanceof BlockItem) {
|
if (placeHitResult != null && stack.getItem() instanceof BlockItem) {
|
||||||
placeAction = "midnightcontrols.action.place";
|
placeAction = "midnightcontrols.action.place";
|
||||||
} else {
|
} else {
|
||||||
placeAction = ButtonBinding.USE.getTranslationKey();
|
placeAction = ButtonBinding.USE.getTranslationKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var customUseAction = MidnightControlsCompat.getUseActionAt(this.client, this.placeHitResult);
|
var customUseAction = MidnightControlsCompat.getUseActionAt(this.client, placeHitResult);
|
||||||
if (customUseAction != null)
|
if (customUseAction != null)
|
||||||
placeAction = customUseAction;
|
placeAction = customUseAction;
|
||||||
|
|
||||||
@@ -281,20 +284,20 @@ public class MidnightControlsHud extends Hud {
|
|||||||
return this.client.textRenderer.getWidth(I18n.translate(text));
|
return this.client.textRenderer.getWidth(I18n.translate(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display) {
|
private void drawButton(DrawContext context, int x, int y, @NotNull ButtonBinding button, boolean display) {
|
||||||
if (display)
|
if (display)
|
||||||
MidnightControlsRenderer.drawButton(matrices, x, y, button, this.client);
|
MidnightControlsRenderer.drawButton(context, x, y, button, this.client);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawTip(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display) {
|
private void drawTip(DrawContext context, int x, int y, @NotNull ButtonBinding button, boolean display) {
|
||||||
this.drawTip(matrices, x, y, button.getTranslationKey(), display);
|
this.drawTip(context, x, y, button.getTranslationKey(), display);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawTip(MatrixStack matrices, int x, int y, @NotNull String action, boolean display) {
|
private void drawTip(DrawContext context, int x, int y, @NotNull String action, boolean display) {
|
||||||
if (!display)
|
if (!display)
|
||||||
return;
|
return;
|
||||||
var translatedAction = I18n.translate(action);
|
var translatedAction = I18n.translate(action);
|
||||||
int textY = (MidnightControlsRenderer.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);
|
context.drawText(this.client.textRenderer, translatedAction, x, (y + textY), 14737632, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,23 +10,33 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import eu.midnightdust.midnightcontrols.client.ControllerType;
|
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.DrawContextAccessor;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
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.DrawContext;
|
||||||
|
import net.minecraft.client.render.*;
|
||||||
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.texture.Sprite;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.ColorHelper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the midnightcontrols renderer.
|
* Represents the midnightcontrols renderer.
|
||||||
*
|
*
|
||||||
@@ -77,17 +87,17 @@ public class MidnightControlsRenderer {
|
|||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ButtonSize drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client) {
|
public static ButtonSize drawButton(DrawContext context, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client) {
|
||||||
return drawButton(matrices, x, y, button.getButton(), client);
|
return drawButton(context, x, y, button.getButton(), client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ButtonSize drawButton(MatrixStack matrices, int x, int y, int[] buttons, @NotNull MinecraftClient client) {
|
public static ButtonSize drawButton(DrawContext context, 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;
|
||||||
for (int i = 0; i < buttons.length; i++) {
|
for (int i = 0; i < buttons.length; i++) {
|
||||||
int btn = buttons[i];
|
int btn = buttons[i];
|
||||||
int size = drawButton(matrices, currentX, y, btn, client);
|
int size = drawButton(context, currentX, y, btn, client);
|
||||||
if (size > height)
|
if (size > height)
|
||||||
height = size;
|
height = size;
|
||||||
length += size;
|
length += size;
|
||||||
@@ -99,7 +109,7 @@ public class MidnightControlsRenderer {
|
|||||||
return new ButtonSize(length, height);
|
return new ButtonSize(length, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int drawButton(MatrixStack matrices, int x, int y, int button, @NotNull MinecraftClient client) {
|
public static int drawButton(DrawContext context, int x, int y, int button, @NotNull MinecraftClient client) {
|
||||||
boolean second = false;
|
boolean second = false;
|
||||||
if (button == -1)
|
if (button == -1)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -159,33 +169,30 @@ public class MidnightControlsRenderer {
|
|||||||
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100, GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200 -> buttonOffset = 10 * 15;
|
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100, GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200 -> buttonOffset = 10 * 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderSystem.setShaderTexture(0, axis ? MidnightControlsClient.CONTROLLER_AXIS : button >= 15 && button <= 19 ? MidnightControlsClient.CONTROLLER_EXPANDED :MidnightControlsClient.CONTROLLER_BUTTONS);
|
|
||||||
RenderSystem.disableDepthTest();
|
|
||||||
|
|
||||||
int assetSize = axis || (button >= 15 && button <= 18) ? AXIS_SIZE : BUTTON_SIZE;
|
int assetSize = axis || (button >= 15 && button <= 18) ? AXIS_SIZE : BUTTON_SIZE;
|
||||||
|
|
||||||
RenderSystem.setShaderColor(1.f, second ? 0.f : 1.f, 1.f, 1.f);
|
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),
|
context.drawTexture(RenderLayer::getGuiTextured, axis ? MidnightControlsClient.CONTROLLER_AXIS : button >= 15 && button <= 19 ? MidnightControlsClient.CONTROLLER_EXPANDED :MidnightControlsClient.CONTROLLER_BUTTONS
|
||||||
|
, x + (ICON_SIZE / 2 - assetSize / 2), y + (ICON_SIZE / 2 - assetSize / 2),
|
||||||
(float) buttonOffset, (float) (controllerType * assetSize),
|
(float) buttonOffset, (float) (controllerType * assetSize),
|
||||||
assetSize, assetSize,
|
assetSize, assetSize,
|
||||||
256, 256);
|
256, 256);
|
||||||
RenderSystem.enableDepthTest();
|
|
||||||
|
|
||||||
return ICON_SIZE;
|
return ICON_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int drawButtonTip(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display, @NotNull MinecraftClient client) {
|
public static int drawButtonTip(DrawContext context, int x, int y, @NotNull ButtonBinding button, boolean display, @NotNull MinecraftClient client) {
|
||||||
return drawButtonTip(matrices, x, y, button.getButton(), button.getTranslationKey(), display, client);
|
return drawButtonTip(context, x, y, button.getButton(), button.getTranslationKey(), display, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int drawButtonTip(MatrixStack matrices, int x, int y, int[] button, @NotNull String action, boolean display, @NotNull MinecraftClient client) {
|
public static int drawButtonTip(DrawContext context, 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).length();
|
int buttonWidth = drawButton(context, x, y, button, client).length();
|
||||||
|
|
||||||
var translatedAction = I18n.translate(action);
|
var translatedAction = I18n.translate(action);
|
||||||
int textY = (MidnightControlsRenderer.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 context.drawTextWithShadow(client.textRenderer, translatedAction, (x + buttonWidth + 2), (y + textY), 14737632);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -10;
|
return -10;
|
||||||
@@ -194,14 +201,28 @@ public class MidnightControlsRenderer {
|
|||||||
private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer) {
|
private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer) {
|
||||||
return 15 + 5 + textRenderer.getWidth(action);
|
return 15 + 5 + textRenderer.getWidth(action);
|
||||||
}
|
}
|
||||||
|
public static void renderWaylandCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
|
||||||
|
if (MidnightControlsConfig.virtualMouse || client.currentScreen == null || MidnightControlsConfig.controlsMode != ControlsMode.CONTROLLER) return;
|
||||||
|
|
||||||
public static void renderVirtualCursor(@NotNull MatrixStack matrices, @NotNull MinecraftClient client) {
|
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
|
||||||
|
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Identifier spritePath = MidnightControlsClient.WAYLAND_CURSOR_TEXTURE_LIGHT;
|
||||||
|
if (MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.DEFAULT_DARK || MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.SECOND_DARK)
|
||||||
|
spritePath = MidnightControlsClient.WAYLAND_CURSOR_TEXTURE_DARK;
|
||||||
|
Sprite sprite = client.getGuiAtlasManager().getSprite(spritePath);
|
||||||
|
drawUnalignedTexturedQuad(RenderLayer::getGuiTextured, sprite.getAtlasId(), context, mouseX, mouseX + 8, mouseY, mouseY + 8, 999, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
|
||||||
|
} catch (IllegalStateException ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void renderVirtualCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
|
||||||
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|
||||||
|| MidnightInput.isScreenInteractive(client.currentScreen)))
|
|| MidnightInput.isScreenInteractive(client.currentScreen)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int mouseX = (int) (client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
|
||||||
int mouseY = (int) (client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
|
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
|
||||||
|
|
||||||
boolean hoverSlot = false;
|
boolean hoverSlot = false;
|
||||||
|
|
||||||
@@ -218,8 +239,8 @@ public class MidnightControlsRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hoverSlot) {
|
if (!hoverSlot && client.currentScreen != null) {
|
||||||
var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, mouseX, mouseY);
|
var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, (int) mouseX, (int) mouseY);
|
||||||
|
|
||||||
if (slot != null) {
|
if (slot != null) {
|
||||||
mouseX = slot.x();
|
mouseX = slot.x();
|
||||||
@@ -233,27 +254,22 @@ public class MidnightControlsRenderer {
|
|||||||
mouseY -= 8;
|
mouseY -= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawCursor(matrices, mouseX, mouseY, hoverSlot, client);
|
try {
|
||||||
|
Sprite sprite = client.getGuiAtlasManager().getSprite(id(MidnightControlsConfig.virtualMouseSkin.getSpritePath() + (hoverSlot ? "_slot" : "")));
|
||||||
|
drawUnalignedTexturedQuad(RenderLayer::getGuiTextured, sprite.getAtlasId(), context, mouseX, mouseX + 16, mouseY, mouseY + 16, 999, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
|
||||||
|
} catch (IllegalStateException ignored) {}
|
||||||
}
|
}
|
||||||
|
private static void drawUnalignedTexturedQuad(Function<Identifier, RenderLayer> renderLayers, Identifier texture, DrawContext context, float x1, float x2, float y1, float y2, float z, float u1, float u2, float v1, float v2) {
|
||||||
/**
|
RenderLayer renderLayer = renderLayers.apply(texture);
|
||||||
* Draws the virtual cursor.
|
//RenderSystem.setShaderTexture(0, texture);
|
||||||
*
|
Matrix4f matrix4f = context.getMatrices().peek().getPositionMatrix();
|
||||||
* @param matrices the matrix stack
|
//BufferBuilder bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE);
|
||||||
* @param x x coordinate
|
VertexConsumer vertexConsumer = ((DrawContextAccessor)context).getVertexConsumers().getBuffer(renderLayer);
|
||||||
* @param y y coordinate
|
vertexConsumer.vertex(matrix4f, x1, y1, z).texture(u1, v1).color(ColorHelper.getWhite(1.0f));
|
||||||
* @param hoverSlot true if hovering a slot, else false
|
vertexConsumer.vertex(matrix4f, x1, y2, z).texture(u1, v2).color(ColorHelper.getWhite(1.0f));
|
||||||
* @param client the client instance
|
vertexConsumer.vertex(matrix4f, x2, y2, z).texture(u2, v2).color(ColorHelper.getWhite(1.0f));
|
||||||
*/
|
vertexConsumer.vertex(matrix4f, x2, y1, z).texture(u2, v1).color(ColorHelper.getWhite(1.0f));
|
||||||
public static void drawCursor(@NotNull MatrixStack matrices, int x, int y, boolean hoverSlot, @NotNull MinecraftClient client) {
|
context.draw();
|
||||||
RenderSystem.disableDepthTest();
|
|
||||||
|
|
||||||
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ButtonSize(int length, int height) {
|
public record ButtonSize(int length, int height) {
|
||||||
@@ -9,26 +9,32 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.opengl.GlStateManager;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import dev.lambdaurora.spruceui.background.Background;
|
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||||
import dev.lambdaurora.spruceui.widget.SpruceWidget;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.KeyboardLayoutManager;
|
||||||
|
import org.thinkingstudio.obsidianui.background.Background;
|
||||||
|
import org.thinkingstudio.obsidianui.mixin.DrawContextAccessor;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.SpruceWidget;
|
||||||
import eu.midnightdust.lib.util.MidnightColorUtil;
|
import eu.midnightdust.lib.util.MidnightColorUtil;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
||||||
import dev.lambdaurora.spruceui.Position;
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
import org.thinkingstudio.obsidianui.SpruceTexts;
|
||||||
import dev.lambdaurora.spruceui.option.*;
|
import org.thinkingstudio.obsidianui.option.*;
|
||||||
import dev.lambdaurora.spruceui.screen.SpruceScreen;
|
import org.thinkingstudio.obsidianui.screen.SpruceScreen;
|
||||||
import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget;
|
import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget;
|
||||||
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
import org.thinkingstudio.obsidianui.widget.SpruceLabelWidget;
|
||||||
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
||||||
import dev.lambdaurora.spruceui.widget.container.SpruceOptionListWidget;
|
import org.thinkingstudio.obsidianui.widget.container.SpruceOptionListWidget;
|
||||||
import dev.lambdaurora.spruceui.widget.container.tabbed.SpruceTabbedWidget;
|
import org.thinkingstudio.obsidianui.widget.container.tabbed.SpruceTabbedWidget;
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
import net.minecraft.client.render.*;
|
import net.minecraft.client.render.*;
|
||||||
@@ -38,7 +44,7 @@ import net.minecraft.text.MutableText;
|
|||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
import net.minecraft.util.Util;
|
import net.minecraft.util.Util;
|
||||||
import net.minecraft.util.math.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -49,7 +55,6 @@ import java.awt.*;
|
|||||||
public class MidnightControlsSettingsScreen extends SpruceScreen {
|
public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||||
private static final Text SDL2_GAMEPAD_TOOL = Text.literal("SDL2 Gamepad Tool").formatted(Formatting.GREEN);
|
private static final Text SDL2_GAMEPAD_TOOL = Text.literal("SDL2 Gamepad Tool").formatted(Formatting.GREEN);
|
||||||
public static final String GAMEPAD_TOOL_URL = "https://generalarcade.com/gamepadtool/";
|
public static final String GAMEPAD_TOOL_URL = "https://generalarcade.com/gamepadtool/";
|
||||||
final MidnightControlsClient mod = MidnightControlsClient.get();
|
|
||||||
private final Screen parent;
|
private final Screen parent;
|
||||||
// General options
|
// General options
|
||||||
private final SpruceOption inputModeOption;
|
private final SpruceOption inputModeOption;
|
||||||
@@ -57,8 +62,14 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
private final SpruceOption rotationSpeedOption;
|
private final SpruceOption rotationSpeedOption;
|
||||||
private final SpruceOption yAxisRotationSpeedOption;
|
private final SpruceOption yAxisRotationSpeedOption;
|
||||||
private final SpruceOption mouseSpeedOption;
|
private final SpruceOption mouseSpeedOption;
|
||||||
|
private final SpruceOption joystickAsMouseOption;
|
||||||
|
private final SpruceOption eyeTrackingAsMouseOption;
|
||||||
|
private final SpruceOption eyeTrackingDeadzone;
|
||||||
private final SpruceOption virtualMouseOption;
|
private final SpruceOption virtualMouseOption;
|
||||||
|
private final SpruceOption virtualKeyboardOption;
|
||||||
|
private final SpruceOption hideCursorOption;
|
||||||
private final SpruceOption resetOption;
|
private final SpruceOption resetOption;
|
||||||
|
private final SpruceOption advancedConfigOption;
|
||||||
// Gameplay options
|
// Gameplay options
|
||||||
private final SpruceOption analogMovementOption;
|
private final SpruceOption analogMovementOption;
|
||||||
private final SpruceOption doubleTapToSprintOption;
|
private final SpruceOption doubleTapToSprintOption;
|
||||||
@@ -75,6 +86,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
private final SpruceOption virtualMouseSkinOption;
|
private final SpruceOption virtualMouseSkinOption;
|
||||||
private final SpruceOption hudEnableOption;
|
private final SpruceOption hudEnableOption;
|
||||||
private final SpruceOption hudSideOption;
|
private final SpruceOption hudSideOption;
|
||||||
|
private final SpruceOption moveChatOption;
|
||||||
// Controller options
|
// Controller options
|
||||||
private final SpruceOption controllerOption =
|
private final SpruceOption controllerOption =
|
||||||
new SpruceCyclingOption("midnightcontrols.menu.controller",
|
new SpruceCyclingOption("midnightcontrols.menu.controller",
|
||||||
@@ -85,6 +97,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
id = GLFW.GLFW_JOYSTICK_1;
|
id = GLFW.GLFW_JOYSTICK_1;
|
||||||
id = searchNextAvailableController(id, false);
|
id = searchNextAvailableController(id, false);
|
||||||
MidnightControlsConfig.setController(Controller.byId(id));
|
MidnightControlsConfig.setController(Controller.byId(id));
|
||||||
|
if (MidnightControlsConfig.debug) System.out.println(Controller.byId(id).getName() + "'s Controller GUID: " + Controller.byId(id).getGuid());
|
||||||
},
|
},
|
||||||
option -> {
|
option -> {
|
||||||
var controller = MidnightControlsConfig.getController();
|
var controller = MidnightControlsConfig.getController();
|
||||||
@@ -114,10 +127,11 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
else
|
else
|
||||||
return option.getDisplayText(Text.literal(controllerName));
|
return option.getDisplayText(Text.literal(controllerName));
|
||||||
}).orElse(option.getDisplayText(SpruceTexts.OPTIONS_OFF.copyContentOnly().formatted(Formatting.RED))),
|
}).orElse(option.getDisplayText(SpruceTexts.OPTIONS_OFF.copyContentOnly().formatted(Formatting.RED))),
|
||||||
Text.translatable("midnightcontrols.tooltip.controller2"));
|
Text.translatable("midnightcontrols.menu.controller2.tooltip"));
|
||||||
private final SpruceOption unfocusedInputOption;
|
private final SpruceOption unfocusedInputOption;
|
||||||
private final SpruceOption invertsRightXAxis;
|
private final SpruceOption invertsRightXAxis;
|
||||||
private final SpruceOption invertsRightYAxis;
|
private final SpruceOption invertsRightYAxis;
|
||||||
|
private final SpruceOption cameraModeOption;
|
||||||
private final SpruceOption toggleControllerProfileOption;
|
private final SpruceOption toggleControllerProfileOption;
|
||||||
private final SpruceOption rightDeadZoneOption;
|
private final SpruceOption rightDeadZoneOption;
|
||||||
private final SpruceOption leftDeadZoneOption;
|
private final SpruceOption leftDeadZoneOption;
|
||||||
@@ -127,15 +141,31 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
maxAnalogValueOption("midnightcontrols.menu.max_right_x_value", GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X),
|
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)
|
maxAnalogValueOption("midnightcontrols.menu.max_right_y_value", GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y)
|
||||||
};
|
};
|
||||||
|
// Controller options
|
||||||
|
public final static SpruceOption virtualKeyboardLayoutOption =
|
||||||
|
new SpruceCyclingOption("midnightcontrols.menu.virtual_keyboard_layout",
|
||||||
|
amount -> {
|
||||||
|
MidnightControlsConfig.keyboardLayout = KeyboardLayoutManager.getNext(KeyboardLayoutManager.getById(MidnightControlsConfig.keyboardLayout)).getId();
|
||||||
|
},
|
||||||
|
option -> {
|
||||||
|
return option.getDisplayText(Text.translatable(KeyboardLayoutManager.getById(MidnightControlsConfig.keyboardLayout).getTranslationKey()));
|
||||||
|
}, null);
|
||||||
|
|
||||||
private static SpruceOption maxAnalogValueOption(String key, int axis) {
|
private static SpruceOption maxAnalogValueOption(String key, int axis) {
|
||||||
return new SpruceDoubleOption(key, .25f, 1.f, 0.05f,
|
return new SpruceDoubleOption(key, .25f, 1.f, 0.05f,
|
||||||
() -> MidnightControlsConfig.getAxisMaxValue(axis),
|
() -> MidnightControlsConfig.getAxisMaxValue(axis),
|
||||||
newValue -> MidnightControlsConfig.setAxisMaxValue(axis, newValue),
|
newValue -> MidnightControlsConfig.setAxisMaxValue(axis, newValue),
|
||||||
option -> option.getDisplayText(Text.literal(String.format("%.2f", option.get()))),
|
option -> option.getDisplayText(Text.literal(String.format("%.2f", option.get()))),
|
||||||
Text.translatable(key.replace("menu", "tooltip"))
|
Text.translatable(key.concat(".tooltip"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Touch options
|
||||||
|
private final SpruceOption touchWithControllerOption;
|
||||||
|
private final SpruceOption touchSpeedOption;
|
||||||
|
private final SpruceOption touchBreakDelayOption;
|
||||||
|
private final SpruceOption invertTouchOption;
|
||||||
|
private final SpruceOption touchTransparencyOption;
|
||||||
|
private final SpruceOption touchModeOption;
|
||||||
|
|
||||||
private final MutableText controllerMappingsUrlText = Text.literal("(")
|
private final MutableText controllerMappingsUrlText = Text.literal("(")
|
||||||
.append(Text.literal(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
|
.append(Text.literal(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
|
||||||
@@ -144,7 +174,9 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
private static int searchNextAvailableController(int newId, boolean allowNone) {
|
private static int searchNextAvailableController(int newId, boolean allowNone) {
|
||||||
if ((allowNone && newId == -1) || newId == 0) return newId;
|
if ((allowNone && newId == -1) || newId == 0) return newId;
|
||||||
|
|
||||||
boolean connected = Controller.byId(newId).isConnected();
|
Controller candidate = Controller.byId(newId);
|
||||||
|
boolean connected = candidate.isConnected();
|
||||||
|
if (MidnightControlsConfig.excludedControllers.stream().anyMatch(exclusion -> candidate.getName().matches(exclusion))) connected = false;
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
newId++;
|
newId++;
|
||||||
}
|
}
|
||||||
@@ -167,36 +199,46 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
MidnightControlsConfig.save();
|
MidnightControlsConfig.save();
|
||||||
|
|
||||||
if (this.client != null && this.client.player != null) {
|
if (this.client != null && this.client.player != null) {
|
||||||
ClientPlayNetworking.getSender().sendPacket(MidnightControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next));
|
NetworkUtil.sendPayloadC2S(new ControlsModePayload(next.getName()));
|
||||||
}
|
}
|
||||||
}, option -> option.getDisplayText(Text.translatable(MidnightControlsConfig.controlsMode.getTranslationKey())),
|
}, option -> option.getDisplayText(Text.translatable(MidnightControlsConfig.controlsMode.getTranslationKey())),
|
||||||
Text.translatable("midnightcontrols.tooltip.controls_mode"));
|
Text.translatable("midnightcontrols.menu.controls_mode.tooltip"));
|
||||||
this.autoSwitchModeOption = new SpruceToggleBooleanOption("midnightcontrols.menu.auto_switch_mode", () -> MidnightControlsConfig.autoSwitchMode,
|
this.autoSwitchModeOption = new SpruceToggleBooleanOption("midnightcontrols.menu.auto_switch_mode", () -> MidnightControlsConfig.autoSwitchMode,
|
||||||
value -> MidnightControlsConfig.autoSwitchMode = value, Text.translatable("midnightcontrols.tooltip.auto_switch_mode"));
|
value -> MidnightControlsConfig.autoSwitchMode = value, Text.translatable("midnightcontrols.menu.auto_switch_mode.tooltip"));
|
||||||
this.rotationSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.rotation_speed", 0.0, 100.0, .5f,
|
this.rotationSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.rotation_speed", 0.0, 100.0, .5f,
|
||||||
() -> MidnightControlsConfig.rotationSpeed,
|
() -> MidnightControlsConfig.rotationSpeed,
|
||||||
value -> MidnightControlsConfig.rotationSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
value -> MidnightControlsConfig.rotationSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||||
Text.translatable("midnightcontrols.tooltip.rotation_speed"));
|
Text.translatable("midnightcontrols.menu.rotation_speed.tooltip"));
|
||||||
this.yAxisRotationSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.y_axis_rotation_speed", 0.0, 100.0, .5f,
|
this.yAxisRotationSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.y_axis_rotation_speed", 0.0, 100.0, .5f,
|
||||||
() -> MidnightControlsConfig.yAxisRotationSpeed,
|
() -> MidnightControlsConfig.yAxisRotationSpeed,
|
||||||
value -> MidnightControlsConfig.yAxisRotationSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
value -> MidnightControlsConfig.yAxisRotationSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||||
Text.translatable("midnightcontrols.tooltip.y_axis_rotation_speed"));
|
Text.translatable("midnightcontrols.menu.y_axis_rotation_speed.tooltip"));
|
||||||
this.mouseSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.mouse_speed", 0.0, 150.0, .5f,
|
this.mouseSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.mouse_speed", 0.0, 150.0, .5f,
|
||||||
() -> MidnightControlsConfig.mouseSpeed,
|
() -> MidnightControlsConfig.mouseSpeed,
|
||||||
value -> MidnightControlsConfig.mouseSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
value -> MidnightControlsConfig.mouseSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||||
Text.translatable("midnightcontrols.tooltip.mouse_speed"));
|
Text.translatable("midnightcontrols.menu.mouse_speed.tooltip"));
|
||||||
|
this.joystickAsMouseOption = new SpruceToggleBooleanOption("midnightcontrols.menu.joystick_as_mouse",
|
||||||
|
() -> MidnightControlsConfig.joystickAsMouse, value -> MidnightControlsConfig.joystickAsMouse = value,
|
||||||
|
Text.translatable("midnightcontrols.menu.joystick_as_mouse.tooltip"));
|
||||||
|
this.eyeTrackingAsMouseOption = new SpruceToggleBooleanOption("midnightcontrols.menu.eye_tracker_as_mouse",
|
||||||
|
() -> MidnightControlsConfig.eyeTrackerAsMouse, value -> MidnightControlsConfig.eyeTrackerAsMouse = value,
|
||||||
|
Text.translatable("midnightcontrols.menu.eye_tracker_as_mouse.tooltip"));
|
||||||
|
this.eyeTrackingDeadzone = new SpruceDoubleInputOption("midnightcontrols.menu.eye_tracker_deadzone",
|
||||||
|
() -> MidnightControlsConfig.eyeTrackerDeadzone, value -> MidnightControlsConfig.eyeTrackerDeadzone = value,
|
||||||
|
Text.translatable("midnightcontrols.menu.eye_tracker_deadzone.tooltip"));
|
||||||
this.resetOption = SpruceSimpleActionOption.reset(btn -> {
|
this.resetOption = SpruceSimpleActionOption.reset(btn -> {
|
||||||
MidnightControlsConfig.reset();
|
MidnightControlsConfig.reset();
|
||||||
var client = MinecraftClient.getInstance();
|
var client = MinecraftClient.getInstance();
|
||||||
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||||
});
|
});
|
||||||
|
this.advancedConfigOption = SpruceSimpleActionOption.of("midnightcontrols.midnightconfig.title", button -> client.setScreen(MidnightControlsConfig.getScreen(this, MidnightControlsConstants.NAMESPACE)));
|
||||||
// Gameplay options
|
// Gameplay options
|
||||||
this.analogMovementOption = new SpruceToggleBooleanOption("midnightcontrols.menu.analog_movement",
|
this.analogMovementOption = new SpruceToggleBooleanOption("midnightcontrols.menu.analog_movement",
|
||||||
() -> MidnightControlsConfig.analogMovement, value -> MidnightControlsConfig.analogMovement = value,
|
() -> MidnightControlsConfig.analogMovement, value -> MidnightControlsConfig.analogMovement = value,
|
||||||
Text.translatable("midnightcontrols.tooltip.analog_movement"));
|
Text.translatable("midnightcontrols.menu.analog_movement.tooltip"));
|
||||||
this.doubleTapToSprintOption = new SpruceToggleBooleanOption("midnightcontrols.menu.double_tap_to_sprint",
|
this.doubleTapToSprintOption = new SpruceToggleBooleanOption("midnightcontrols.menu.double_tap_to_sprint",
|
||||||
() -> MidnightControlsConfig.doubleTapToSprint, value -> MidnightControlsConfig.doubleTapToSprint = value,
|
() -> MidnightControlsConfig.doubleTapToSprint, value -> MidnightControlsConfig.doubleTapToSprint = value,
|
||||||
Text.translatable("midnightcontrols.tooltip.double_tap_to_sprint"));
|
Text.translatable("midnightcontrols.menu.double_tap_to_sprint.tooltip"));
|
||||||
this.autoJumpOption = new SpruceToggleBooleanOption("options.autoJump",
|
this.autoJumpOption = new SpruceToggleBooleanOption("options.autoJump",
|
||||||
() -> this.client.options.getAutoJump().getValue(),
|
() -> this.client.options.getAutoJump().getValue(),
|
||||||
newValue -> this.client.options.getAutoJump().setValue(newValue),
|
newValue -> this.client.options.getAutoJump().setValue(newValue),
|
||||||
@@ -208,30 +250,32 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
() -> MidnightControlsConfig.controllerToggleSprint, value -> MidnightControlsConfig.controllerToggleSprint = value,
|
() -> MidnightControlsConfig.controllerToggleSprint, value -> MidnightControlsConfig.controllerToggleSprint = value,
|
||||||
null);
|
null);
|
||||||
this.fastBlockPlacingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fast_block_placing", () -> MidnightControlsConfig.fastBlockPlacing,
|
this.fastBlockPlacingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fast_block_placing", () -> MidnightControlsConfig.fastBlockPlacing,
|
||||||
value -> MidnightControlsConfig.fastBlockPlacing = value, Text.translatable("midnightcontrols.tooltip.fast_block_placing"));
|
value -> MidnightControlsConfig.fastBlockPlacing = value, Text.translatable("midnightcontrols.menu.fast_block_placing.tooltip"));
|
||||||
this.frontBlockPlacingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.reacharound.horizontal", () -> MidnightControlsConfig.horizontalReacharound,
|
this.frontBlockPlacingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.reacharound.horizontal", () -> MidnightControlsConfig.horizontalReacharound,
|
||||||
value -> MidnightControlsConfig.horizontalReacharound = value, Text.translatable("midnightcontrols.tooltip.reacharound.horizontal"));
|
value -> MidnightControlsConfig.horizontalReacharound = value, Text.translatable("midnightcontrols.menu.reacharound.horizontal.tooltip"));
|
||||||
this.verticalReacharoundOption = new SpruceToggleBooleanOption("midnightcontrols.menu.reacharound.vertical", () -> MidnightControlsConfig.verticalReacharound,
|
this.verticalReacharoundOption = new SpruceToggleBooleanOption("midnightcontrols.menu.reacharound.vertical", () -> MidnightControlsConfig.verticalReacharound,
|
||||||
value -> MidnightControlsConfig.verticalReacharound = value, Text.translatable("midnightcontrols.tooltip.reacharound.vertical"));
|
value -> MidnightControlsConfig.verticalReacharound = value, Text.translatable("midnightcontrols.menu.reacharound.vertical.tooltip"));
|
||||||
this.flyDriftingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fly_drifting", () -> MidnightControlsConfig.flyDrifting,
|
this.flyDriftingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fly_drifting", () -> MidnightControlsConfig.flyDrifting,
|
||||||
value -> MidnightControlsConfig.flyDrifting = value, Text.translatable("midnightcontrols.tooltip.fly_drifting"));
|
value -> MidnightControlsConfig.flyDrifting = value, Text.translatable("midnightcontrols.menu.fly_drifting.tooltip"));
|
||||||
this.flyVerticalDriftingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fly_drifting_vertical", () -> MidnightControlsConfig.verticalFlyDrifting,
|
this.flyVerticalDriftingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fly_drifting_vertical", () -> MidnightControlsConfig.verticalFlyDrifting,
|
||||||
value -> MidnightControlsConfig.verticalFlyDrifting = value, Text.translatable("midnightcontrols.tooltip.fly_drifting_vertical"));
|
value -> MidnightControlsConfig.verticalFlyDrifting = value, Text.translatable("midnightcontrols.menu.fly_drifting_vertical.tooltip"));
|
||||||
// Appearance options
|
// Appearance options
|
||||||
this.controllerTypeOption = new SpruceCyclingOption("midnightcontrols.menu.controller_type",
|
this.controllerTypeOption = new SpruceCyclingOption("midnightcontrols.menu.controller_type",
|
||||||
amount -> MidnightControlsConfig.controllerType = MidnightControlsConfig.controllerType.next(),
|
amount -> MidnightControlsConfig.controllerType = MidnightControlsConfig.controllerType.next(),
|
||||||
option -> option.getDisplayText(MidnightControlsConfig.controllerType.getTranslatedText()),
|
option -> option.getDisplayText(MidnightControlsConfig.controllerType.getTranslatedText()),
|
||||||
Text.translatable("midnightcontrols.tooltip.controller_type"));
|
Text.translatable("midnightcontrols.menu.controller_type.tooltip"));
|
||||||
this.virtualMouseSkinOption = new SpruceCyclingOption("midnightcontrols.menu.virtual_mouse.skin",
|
this.virtualMouseSkinOption = new SpruceCyclingOption("midnightcontrols.menu.virtual_mouse.skin",
|
||||||
amount -> MidnightControlsConfig.virtualMouseSkin = MidnightControlsConfig.virtualMouseSkin.next(),
|
amount -> MidnightControlsConfig.virtualMouseSkin = MidnightControlsConfig.virtualMouseSkin.next(),
|
||||||
option -> option.getDisplayText(MidnightControlsConfig.virtualMouseSkin.getTranslatedText()),
|
option -> option.getDisplayText(MidnightControlsConfig.virtualMouseSkin.getTranslatedText()),
|
||||||
null);
|
null);
|
||||||
this.hudEnableOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hud_enable", () -> MidnightControlsConfig.hudEnable,
|
this.hudEnableOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hud_enable", () -> MidnightControlsConfig.hudEnable,
|
||||||
this.mod::setHudEnabled, Text.translatable("midnightcontrols.tooltip.hud_enable"));
|
MidnightControlsClient::setHudEnabled, Text.translatable("midnightcontrols.menu.hud_enable.tooltip"));
|
||||||
this.hudSideOption = new SpruceCyclingOption("midnightcontrols.menu.hud_side",
|
this.hudSideOption = new SpruceCyclingOption("midnightcontrols.menu.hud_side",
|
||||||
amount -> MidnightControlsConfig.hudSide = MidnightControlsConfig.hudSide.next(),
|
amount -> MidnightControlsConfig.hudSide = MidnightControlsConfig.hudSide.next(),
|
||||||
option -> option.getDisplayText(MidnightControlsConfig.hudSide.getTranslatedText()),
|
option -> option.getDisplayText(MidnightControlsConfig.hudSide.getTranslatedText()),
|
||||||
Text.translatable("midnightcontrols.tooltip.hud_side"));
|
Text.translatable("midnightcontrols.menu.hud_side.tooltip"));
|
||||||
|
this.moveChatOption = new SpruceToggleBooleanOption("midnightcontrols.menu.move_chat", () -> MidnightControlsConfig.moveChat,
|
||||||
|
value -> MidnightControlsConfig.moveChat = value, Text.translatable("midnightcontrols.menu.move_chat.tooltip"));
|
||||||
// Controller options
|
// Controller options
|
||||||
this.toggleControllerProfileOption = new SpruceToggleBooleanOption("midnightcontrols.menu.separate_controller_profile", () -> MidnightControlsConfig.controllerBindingProfiles.containsKey(MidnightControlsConfig.getController().getGuid()), value -> {
|
this.toggleControllerProfileOption = new SpruceToggleBooleanOption("midnightcontrols.menu.separate_controller_profile", () -> MidnightControlsConfig.controllerBindingProfiles.containsKey(MidnightControlsConfig.getController().getGuid()), value -> {
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -242,27 +286,56 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
MidnightControlsConfig.updateBindingsForController(MidnightControlsConfig.getController());
|
MidnightControlsConfig.updateBindingsForController(MidnightControlsConfig.getController());
|
||||||
}
|
}
|
||||||
|
|
||||||
}, Text.translatable(""));
|
}, Text.empty());
|
||||||
|
this.cameraModeOption = new SpruceCyclingOption("midnightcontrols.menu.camera_mode",
|
||||||
|
amount -> MidnightControlsConfig.cameraMode = MidnightControlsConfig.cameraMode.next(),
|
||||||
|
option -> option.getDisplayText(MidnightControlsConfig.cameraMode.getTranslatedText()),
|
||||||
|
Text.translatable("midnightcontrols.menu.camera_mode.tooltip"));
|
||||||
this.rightDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.right_dead_zone", 0.05, 1.0, .05f,
|
this.rightDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.right_dead_zone", 0.05, 1.0, .05f,
|
||||||
() -> MidnightControlsConfig.rightDeadZone,
|
() -> MidnightControlsConfig.rightDeadZone,
|
||||||
value -> MidnightControlsConfig.rightDeadZone = value, option -> {
|
value -> MidnightControlsConfig.rightDeadZone = value, option -> {
|
||||||
var value = String.valueOf(option.get());
|
var value = String.valueOf(option.get());
|
||||||
return option.getDisplayText(Text.literal(value.substring(0, Math.min(value.length(), 5))));
|
return option.getDisplayText(Text.literal(value.substring(0, Math.min(value.length(), 5))));
|
||||||
}, Text.translatable("midnightcontrols.tooltip.right_dead_zone"));
|
}, Text.translatable("midnightcontrols.menu.right_dead_zone.tooltip"));
|
||||||
this.leftDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.left_dead_zone", 0.05, 1.0, .05f,
|
this.leftDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.left_dead_zone", 0.05, 1.0, .05f,
|
||||||
() -> MidnightControlsConfig.leftDeadZone,
|
() -> MidnightControlsConfig.leftDeadZone,
|
||||||
value -> MidnightControlsConfig.leftDeadZone = value, option -> {
|
value -> MidnightControlsConfig.leftDeadZone = value, option -> {
|
||||||
var value = String.valueOf(option.get());
|
var value = String.valueOf(option.get());
|
||||||
return option.getDisplayText(Text.literal(value.substring(0, Math.min(value.length(), 5))));
|
return option.getDisplayText(Text.literal(value.substring(0, Math.min(value.length(), 5))));
|
||||||
}, Text.translatable("midnightcontrols.tooltip.left_dead_zone"));
|
}, Text.translatable("midnightcontrols.menu.left_dead_zone.tooltip"));
|
||||||
this.invertsRightXAxis = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_right_x_axis", () -> MidnightControlsConfig.invertRightXAxis,
|
this.invertsRightXAxis = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_right_x_axis", () -> MidnightControlsConfig.invertRightXAxis,
|
||||||
value -> MidnightControlsConfig.invertRightXAxis = value, null);
|
value -> MidnightControlsConfig.invertRightXAxis = value, null);
|
||||||
this.invertsRightYAxis = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_right_y_axis", () -> MidnightControlsConfig.invertRightYAxis,
|
this.invertsRightYAxis = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_right_y_axis", () -> MidnightControlsConfig.invertRightYAxis,
|
||||||
value -> MidnightControlsConfig.invertRightYAxis = value, null);
|
value -> MidnightControlsConfig.invertRightYAxis = value, null);
|
||||||
this.unfocusedInputOption = new SpruceToggleBooleanOption("midnightcontrols.menu.unfocused_input", () -> MidnightControlsConfig.unfocusedInput,
|
this.unfocusedInputOption = new SpruceToggleBooleanOption("midnightcontrols.menu.unfocused_input", () -> MidnightControlsConfig.unfocusedInput,
|
||||||
value -> MidnightControlsConfig.unfocusedInput = value, Text.translatable("midnightcontrols.tooltip.unfocused_input"));
|
value -> MidnightControlsConfig.unfocusedInput = value, Text.translatable("midnightcontrols.menu.unfocused_input.tooltip"));
|
||||||
this.virtualMouseOption = new SpruceToggleBooleanOption("midnightcontrols.menu.virtual_mouse", () -> MidnightControlsConfig.virtualMouse,
|
this.virtualMouseOption = new SpruceToggleBooleanOption("midnightcontrols.menu.virtual_mouse", () -> MidnightControlsConfig.virtualMouse,
|
||||||
value -> MidnightControlsConfig.virtualMouse = value, Text.translatable("midnightcontrols.tooltip.virtual_mouse"));
|
value -> MidnightControlsConfig.virtualMouse = value, Text.translatable("midnightcontrols.menu.virtual_mouse.tooltip"));
|
||||||
|
this.virtualKeyboardOption = new SpruceToggleBooleanOption("midnightcontrols.menu.virtual_keyboard", () -> MidnightControlsConfig.virtualMouse,
|
||||||
|
value -> MidnightControlsConfig.virtualKeyboard = value, Text.translatable("midnightcontrols.menu.virtual_keyboard.tooltip"));
|
||||||
|
this.hideCursorOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hide_cursor", () -> MidnightControlsConfig.hideNormalMouse,
|
||||||
|
value -> MidnightControlsConfig.hideNormalMouse = value, Text.translatable("midnightcontrols.menu.hide_cursor.tooltip"));
|
||||||
|
// Touch options
|
||||||
|
this.touchModeOption = new SpruceCyclingOption("midnightcontrols.menu.touch_mode",
|
||||||
|
amount -> MidnightControlsConfig.touchMode = MidnightControlsConfig.touchMode.next(),
|
||||||
|
option -> option.getDisplayText(MidnightControlsConfig.touchMode.getTranslatedText()),
|
||||||
|
Text.translatable("midnightcontrols.menu.touch_mode.tooltip"));
|
||||||
|
this.touchWithControllerOption = new SpruceToggleBooleanOption("midnightcontrols.menu.touch_with_controller", () -> MidnightControlsConfig.touchInControllerMode,
|
||||||
|
value -> MidnightControlsConfig.touchInControllerMode = value, Text.translatable("midnightcontrols.menu.touch_with_controller.tooltip"));
|
||||||
|
this.touchSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.touch_speed", 0.0, 150.0, .5f,
|
||||||
|
() -> MidnightControlsConfig.touchSpeed,
|
||||||
|
value -> MidnightControlsConfig.touchSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||||
|
Text.translatable("midnightcontrols.menu.touch_speed.tooltip"));
|
||||||
|
this.touchBreakDelayOption = new SpruceDoubleOption("midnightcontrols.menu.touch_break_delay", 50, 500, 1f,
|
||||||
|
() -> (double) MidnightControlsConfig.touchBreakDelay,
|
||||||
|
value -> MidnightControlsConfig.touchBreakDelay = value.intValue(), option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||||
|
Text.translatable("midnightcontrols.menu.touch_break_delay.tooltip"));
|
||||||
|
this.touchTransparencyOption = new SpruceDoubleOption("midnightcontrols.menu.touch_transparency", 0, 100, 1f,
|
||||||
|
() -> (double) MidnightControlsConfig.touchTransparency,
|
||||||
|
value -> MidnightControlsConfig.touchTransparency = value.intValue(), option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||||
|
Text.translatable("midnightcontrols.menu.touch_break_delay.tooltip"));
|
||||||
|
this.invertTouchOption = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_touch", () -> MidnightControlsConfig.invertTouch,
|
||||||
|
value -> MidnightControlsConfig.invertTouch = value, Text.translatable("midnightcontrols.menu.invert_touch.tooltip"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -290,8 +363,8 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
this.buildTabs();
|
this.buildTabs();
|
||||||
|
|
||||||
this.addDrawableChild(this.resetOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 150));
|
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,
|
this.addDrawableChild(ButtonWidget.builder(SpruceTexts.GUI_DONE, btn -> this.client.setScreen(this.parent))
|
||||||
btn -> this.client.setScreen(this.parent)));
|
.dimensions(this.width / 2 - 155 + 160, this.height - 29, 150, 20).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildTabs() {
|
public void buildTabs() {
|
||||||
@@ -316,6 +389,8 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
tabs.addSeparatorEntry(Text.translatable("midnightcontrols.menu.separator.controller"));
|
tabs.addSeparatorEntry(Text.translatable("midnightcontrols.menu.separator.controller"));
|
||||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.controller"), null,
|
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.controller"), null,
|
||||||
this::buildControllerTab);
|
this::buildControllerTab);
|
||||||
|
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.touch"), null,
|
||||||
|
this::buildTouchTab);
|
||||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.mappings.string"), null,
|
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.mappings.string"), null,
|
||||||
this::buildMappingsStringEditorTab);
|
this::buildMappingsStringEditorTab);
|
||||||
}
|
}
|
||||||
@@ -329,6 +404,12 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
list.addSingleOptionEntry(this.yAxisRotationSpeedOption);
|
list.addSingleOptionEntry(this.yAxisRotationSpeedOption);
|
||||||
list.addSingleOptionEntry(this.mouseSpeedOption);
|
list.addSingleOptionEntry(this.mouseSpeedOption);
|
||||||
list.addSingleOptionEntry(this.virtualMouseOption);
|
list.addSingleOptionEntry(this.virtualMouseOption);
|
||||||
|
list.addSingleOptionEntry(this.virtualKeyboardOption);
|
||||||
|
list.addSingleOptionEntry(this.virtualKeyboardLayoutOption);
|
||||||
|
list.addSingleOptionEntry(this.hideCursorOption);
|
||||||
|
list.addSingleOptionEntry(this.joystickAsMouseOption);
|
||||||
|
list.addSingleOptionEntry(this.eyeTrackingAsMouseOption);
|
||||||
|
list.addSingleOptionEntry(this.advancedConfigOption);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,6 +437,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
list.addSingleOptionEntry(new SpruceSeparatorOption("midnightcontrols.menu.title.hud", true, null));
|
list.addSingleOptionEntry(new SpruceSeparatorOption("midnightcontrols.menu.title.hud", true, null));
|
||||||
list.addSingleOptionEntry(this.hudEnableOption);
|
list.addSingleOptionEntry(this.hudEnableOption);
|
||||||
list.addSingleOptionEntry(this.hudSideOption);
|
list.addSingleOptionEntry(this.hudSideOption);
|
||||||
|
list.addSingleOptionEntry(this.moveChatOption);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,6 +476,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
list.addSingleOptionEntry(this.secondControllerOption);
|
list.addSingleOptionEntry(this.secondControllerOption);
|
||||||
list.addSingleOptionEntry(this.toggleControllerProfileOption);
|
list.addSingleOptionEntry(this.toggleControllerProfileOption);
|
||||||
list.addSingleOptionEntry(this.unfocusedInputOption);
|
list.addSingleOptionEntry(this.unfocusedInputOption);
|
||||||
|
list.addSingleOptionEntry(this.cameraModeOption);
|
||||||
list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
|
list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
|
||||||
list.addSingleOptionEntry(this.rightDeadZoneOption);
|
list.addSingleOptionEntry(this.rightDeadZoneOption);
|
||||||
list.addSingleOptionEntry(this.leftDeadZoneOption);
|
list.addSingleOptionEntry(this.leftDeadZoneOption);
|
||||||
@@ -405,48 +488,51 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
root.addChild(labels);
|
root.addChild(labels);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
public SpruceOptionListWidget buildTouchTab(int width, int height) {
|
||||||
|
var list = new SpruceOptionListWidget(Position.origin(), width, height);
|
||||||
|
list.setBackground(new MidnightControlsBackground(130));
|
||||||
|
list.addSingleOptionEntry(this.touchSpeedOption);
|
||||||
|
list.addSingleOptionEntry(this.touchWithControllerOption);
|
||||||
|
list.addSingleOptionEntry(this.invertTouchOption);
|
||||||
|
list.addSingleOptionEntry(new SpruceSeparatorOption("midnightcontrols.menu.title.hud", true, null));
|
||||||
|
list.addSingleOptionEntry(this.touchModeOption);
|
||||||
|
list.addSingleOptionEntry(this.touchBreakDelayOption);
|
||||||
|
list.addSingleOptionEntry(this.touchTransparencyOption);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public SpruceContainerWidget buildMappingsStringEditorTab(int width, int height) {
|
public SpruceContainerWidget buildMappingsStringEditorTab(int width, int height) {
|
||||||
return new MappingsStringInputWidget(Position.origin(), width, height);
|
return new MappingsStringInputWidget(Position.origin(), width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderTitle(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
public void renderTitle(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
drawCenteredText(matrices, this.textRenderer, I18n.translate("midnightcontrols.menu.title"), this.width / 2, 8, 16777215);
|
context.drawCenteredTextWithShadow(this.textRenderer, I18n.translate("midnightcontrols.menu.title"), this.width / 2, 8, 16777215);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MidnightControlsBackground implements Background {
|
public static class MidnightControlsBackground implements Background {
|
||||||
private int transparency = 160;
|
private static int transparency = 160;
|
||||||
public MidnightControlsBackground() {}
|
public MidnightControlsBackground() {}
|
||||||
public MidnightControlsBackground(int transparency) {
|
public MidnightControlsBackground(int transparency) {
|
||||||
this.transparency = transparency;
|
MidnightControlsBackground.transparency = transparency;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void render(MatrixStack matrixStack, SpruceWidget widget, int vOffset, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, 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"));
|
fill(context, widget.getX(), widget.getY(), widget.getX() + widget.getWidth(), widget.getY() + widget.getHeight(), Color.black);
|
||||||
}
|
}
|
||||||
private void fill(MatrixStack matrixStack, int x2, int y2, int x1, int y1, Color color) {
|
private static void fill(DrawContext context, int x2, int y2, int x1, int y1, Color color) {
|
||||||
matrixStack.push();
|
RenderLayer renderLayer = RenderLayer.getGui();
|
||||||
|
VertexConsumer vertexConsumer = ((DrawContextAccessor)context).getVertexConsumers().getBuffer(renderLayer);
|
||||||
|
|
||||||
Matrix4f matrix = matrixStack.peek().getPositionMatrix();
|
|
||||||
float r = (float)(color.getRed()) / 255.0F;
|
float r = (float)(color.getRed()) / 255.0F;
|
||||||
float g = (float)(color.getGreen()) / 255.0F;
|
float g = (float)(color.getGreen()) / 255.0F;
|
||||||
float b = (float)(color.getBlue()) / 255.0F;
|
float b = (float)(color.getBlue()) / 255.0F;
|
||||||
float t = (float)(transparency) / 255.0F;
|
float t = (float)(transparency) / 255.0F;
|
||||||
BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
|
vertexConsumer.vertex((float)x1, (float)y2, 0.0F).color(r, g, b, t);
|
||||||
RenderSystem.enableBlend();
|
vertexConsumer.vertex((float)x2, (float)y2, 0.0F).color(r, g, b, t);
|
||||||
RenderSystem.disableTexture();
|
vertexConsumer.vertex((float)x2, (float)y1, 0.0F).color(r, g, b, t);
|
||||||
RenderSystem.defaultBlendFunc();
|
vertexConsumer.vertex((float)x1, (float)y1, 0.0F).color(r, g, b, t);
|
||||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
context.draw();
|
||||||
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();
|
|
||||||
BufferRenderer.drawWithShader(bufferBuilder.end());
|
|
||||||
RenderSystem.enableTexture();
|
|
||||||
RenderSystem.disableBlend();
|
|
||||||
matrixStack.pop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import dev.lambdaurora.spruceui.option.SpruceSimpleActionOption;
|
import org.thinkingstudio.obsidianui.option.SpruceSimpleActionOption;
|
||||||
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
import org.thinkingstudio.obsidianui.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.Text;
|
import net.minecraft.text.Text;
|
||||||
@@ -33,7 +33,7 @@ public class ReloadControllerMappingsOption {
|
|||||||
Controller.updateMappings();
|
Controller.updateMappings();
|
||||||
if (client.currentScreen instanceof MidnightControlsSettingsScreen)
|
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.PERIODIC_NOTIFICATION,
|
||||||
Text.translatable("midnightcontrols.controller.mappings.updated"), Text.empty()));
|
Text.translatable("midnightcontrols.controller.mappings.updated"), Text.empty()));
|
||||||
}, Text.translatable("midnightcontrols.tooltip.reload_controller_mappings"));
|
}, Text.translatable("midnightcontrols.tooltip.reload_controller_mappings"));
|
||||||
}
|
}
|
||||||
@@ -10,14 +10,15 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.ring.RingButtonMode;
|
import eu.midnightdust.midnightcontrols.client.ring.RingButtonMode;
|
||||||
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.ring;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the controls ring screen.
|
* Represents the controls ring screen.
|
||||||
*
|
*
|
||||||
@@ -26,19 +27,17 @@ import net.minecraft.text.Text;
|
|||||||
* @since 1.4.3
|
* @since 1.4.3
|
||||||
*/
|
*/
|
||||||
public class RingScreen extends Screen {
|
public class RingScreen extends Screen {
|
||||||
protected final MidnightControlsClient mod;
|
|
||||||
|
|
||||||
public RingScreen() {
|
public RingScreen() {
|
||||||
super(Text.literal("midnightcontrols.menu.title.ring"));
|
super(Text.literal("midnightcontrols.menu.title.ring"));
|
||||||
this.mod = MidnightControlsClient.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
super.init();
|
super.init();
|
||||||
if (mod.ring.getMaxPages() > 1) {
|
if (ring.getMaxPages() > 1) {
|
||||||
this.addDrawableChild(new ButtonWidget(5, 5, 20, 20, Text.of("◀"), button -> this.mod.ring.cyclePage(false)));
|
this.addDrawableChild(ButtonWidget.builder(Text.of("◀"), button -> ring.cyclePage(false)).dimensions(5, 5, 20, 20).build());
|
||||||
this.addDrawableChild(new ButtonWidget(width - 25, 5, 20, 20, Text.of("▶"), button -> this.mod.ring.cyclePage(true)));
|
this.addDrawableChild(ButtonWidget.builder(Text.of("▶"), button -> ring.cyclePage(true)).dimensions(width - 25, 5, 20, 20).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,11 +47,11 @@ public class RingScreen extends Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
super.render(matrices, mouseX, mouseY, delta);
|
super.render(context, mouseX, mouseY, delta);
|
||||||
|
|
||||||
RingPage page = this.mod.ring.getCurrentPage();
|
RingPage page = ring.getCurrentPage();
|
||||||
page.render(matrices, this.textRenderer, this.width, this.height, mouseX, mouseY, delta);
|
page.render(context, this.textRenderer, this.width, this.height, mouseX, mouseY, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -60,28 +59,28 @@ public class RingScreen extends Screen {
|
|||||||
super.close();
|
super.close();
|
||||||
assert client != null;
|
assert client != null;
|
||||||
client.currentScreen = null;
|
client.currentScreen = null;
|
||||||
RingPage page = this.mod.ring.getCurrentPage();
|
RingPage page = ring.getCurrentPage();
|
||||||
if (RingPage.selected >= 0 && page.actions[RingPage.selected] != null)
|
if (RingPage.selected >= 0 && page.actions[RingPage.selected] != null)
|
||||||
page.actions[RingPage.selected].activate(RingButtonMode.PRESS);
|
page.actions[RingPage.selected].activate(RingButtonMode.PRESS);
|
||||||
RingPage.selected = -1;
|
RingPage.selected = -1;
|
||||||
this.removed();
|
this.removed();
|
||||||
}
|
}
|
||||||
@Override
|
// @Override
|
||||||
public boolean changeFocus(boolean lookForwards) {
|
// public boolean changeFocus(boolean lookForwards) {
|
||||||
if (lookForwards) {
|
// if (lookForwards) {
|
||||||
if (RingPage.selected < 7) ++RingPage.selected;
|
// if (RingPage.selected < 7) ++RingPage.selected;
|
||||||
else RingPage.selected = -1;
|
// else RingPage.selected = -1;
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
if (RingPage.selected > -1) --RingPage.selected;
|
// if (RingPage.selected > -1) --RingPage.selected;
|
||||||
else RingPage.selected = 7;
|
// else RingPage.selected = 7;
|
||||||
}
|
// }
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||||
if (mod.ring.getCurrentPage().onClick(width, height, (int) mouseX, (int) mouseY)) {
|
if (ring.getCurrentPage().onClick(width, height, (int) mouseX, (int) mouseY)) {
|
||||||
this.close();
|
this.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -11,11 +11,11 @@ package eu.midnightdust.midnightcontrols.client.gui.widget;
|
|||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||||
import dev.lambdaurora.spruceui.Position;
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
import org.thinkingstudio.obsidianui.SpruceTexts;
|
||||||
import dev.lambdaurora.spruceui.widget.AbstractSpruceIconButtonWidget;
|
import org.thinkingstudio.obsidianui.widget.AbstractSpruceIconButtonWidget;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -45,12 +45,12 @@ public class ControllerButtonWidget extends AbstractSpruceIconButtonWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int renderIcon(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
protected int renderIcon(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
int x = this.getX();
|
int x = this.getX();
|
||||||
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;
|
||||||
}
|
}
|
||||||
var size = MidnightControlsRenderer.drawButton(matrices, x, this.getY(), this.binding, MinecraftClient.getInstance());
|
var size = MidnightControlsRenderer.drawButton(context, x, this.getY(), this.binding, MinecraftClient.getInstance());
|
||||||
this.iconWidth = size.length();
|
this.iconWidth = size.length();
|
||||||
return size.height();
|
return size.height();
|
||||||
}
|
}
|
||||||
@@ -9,17 +9,16 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import dev.lambdaurora.spruceui.Position;
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
import org.thinkingstudio.obsidianui.SpruceTexts;
|
||||||
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
||||||
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
||||||
|
|
||||||
@@ -31,8 +30,6 @@ import java.util.stream.Collectors;
|
|||||||
* Represents the controls screen.
|
* Represents the controls screen.
|
||||||
*/
|
*/
|
||||||
public class ControllerControlsWidget extends SpruceContainerWidget {
|
public class ControllerControlsWidget extends SpruceContainerWidget {
|
||||||
final MidnightControlsClient mod;
|
|
||||||
private ControlsListWidget bindingsListWidget;
|
|
||||||
private SpruceButtonWidget resetButton;
|
private SpruceButtonWidget resetButton;
|
||||||
public ButtonBinding focusedBinding;
|
public ButtonBinding focusedBinding;
|
||||||
public boolean waiting = false;
|
public boolean waiting = false;
|
||||||
@@ -40,7 +37,6 @@ 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 = MidnightControlsClient.get();
|
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
@@ -49,20 +45,20 @@ public class ControllerControlsWidget extends SpruceContainerWidget {
|
|||||||
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,
|
||||||
Text.translatable("midnightcontrols.menu.keyboard_controls"),
|
Text.translatable("midnightcontrols.menu.keyboard_controls"),
|
||||||
btn -> this.client.setScreen(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);
|
ControlsListWidget bindingsListWidget = new ControlsListWidget(Position.of(this, 0, 43), this.width, this.height - 43 - 35, this);
|
||||||
this.bindingsListWidget.setBackground(new MidnightControlsSettingsScreen.MidnightControlsBackground(130));
|
bindingsListWidget.setBackground(new MidnightControlsSettingsScreen.MidnightControlsBackground(130));
|
||||||
this.addChild(this.bindingsListWidget);
|
this.addChild(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 -> MidnightControlsConfig.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(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
drawCenteredText(matrices, this.client.textRenderer, Text.translatable("midnightcontrols.menu.title.controller_controls"),
|
context.drawCenteredTextWithShadow(this.client.textRenderer, Text.translatable("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(context, mouseX, mouseY, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finishBindingEdit(int... buttons) {
|
public void finishBindingEdit(int... buttons) {
|
||||||
@@ -14,19 +14,22 @@ import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import dev.lambdaurora.spruceui.Position;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
import net.minecraft.util.Identifier;
|
||||||
import dev.lambdaurora.spruceui.navigation.NavigationDirection;
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
import dev.lambdaurora.spruceui.navigation.NavigationUtils;
|
import org.thinkingstudio.obsidianui.SpruceTexts;
|
||||||
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
import org.thinkingstudio.obsidianui.navigation.NavigationDirection;
|
||||||
import dev.lambdaurora.spruceui.widget.SpruceSeparatorWidget;
|
import org.thinkingstudio.obsidianui.navigation.NavigationUtils;
|
||||||
import dev.lambdaurora.spruceui.widget.SpruceWidget;
|
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
||||||
import dev.lambdaurora.spruceui.widget.container.SpruceEntryListWidget;
|
import org.thinkingstudio.obsidianui.widget.SpruceIconButtonWidget;
|
||||||
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
|
import org.thinkingstudio.obsidianui.widget.SpruceSeparatorWidget;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.SpruceWidget;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.container.SpruceEntryListWidget;
|
||||||
|
import org.thinkingstudio.obsidianui.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.gui.DrawContext;
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -86,9 +89,9 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
super(parent);
|
super(parent);
|
||||||
this.binding = binding;
|
this.binding = binding;
|
||||||
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), 120, this.binding, btn -> {
|
||||||
gui.focusedBinding = binding;
|
gui.focusedBinding = binding;
|
||||||
MidnightControlsClient.get().input.beginControlsInput(gui);
|
MidnightControlsClient.input.beginControlsInput(gui);
|
||||||
}) {
|
}) {
|
||||||
protected Text getNarrationMessage() {
|
protected Text getNarrationMessage() {
|
||||||
return binding.isNotBound() ? Text.translatable("narrator.controls.unbound", bindingName)
|
return binding.isNotBound() ? Text.translatable("narrator.controls.unbound", bindingName)
|
||||||
@@ -96,13 +99,24 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.children.add(editButton);
|
this.children.add(editButton);
|
||||||
this.resetButton = new SpruceButtonWidget(Position.of(this,
|
this.resetButton = new SpruceIconButtonWidget(Position.of(this,
|
||||||
this.editButton.getPosition().getRelativeX() + this.editButton.getWidth() + 2, 0),
|
this.editButton.getPosition().getRelativeX() + this.editButton.getWidth() + 2, 0),
|
||||||
44, 20, Text.translatable("controls.reset"),
|
37, 20, Text.empty(),
|
||||||
btn -> MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton())) {
|
btn -> MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton())) {
|
||||||
protected Text getNarrationMessage() {
|
protected Text getNarrationMessage() {
|
||||||
return Text.translatable("narrator.controls.reset", bindingName);
|
return Text.translatable("narrator.controls.reset", bindingName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Identifier resetTexture = Identifier.of("midnightlib","icon/reset");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int renderIcon(DrawContext drawContext, int mouseX, int mouseY, float delta) {
|
||||||
|
int size = 12;
|
||||||
|
int x = this.getX() + this.getWidth() / 2 - size / 2;
|
||||||
|
int y = this.getY() + this.getHeight() / 2 - size / 2;
|
||||||
|
drawContext.drawGuiTexture(RenderLayer::getGuiTextured, resetTexture, x, y, size, size);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
this.children.add(this.resetButton);
|
this.children.add(this.resetButton);
|
||||||
this.unbindButton = new SpruceButtonWidget(Position.of(this,
|
this.unbindButton = new SpruceButtonWidget(Position.of(this,
|
||||||
@@ -111,7 +125,7 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
btn -> {
|
btn -> {
|
||||||
MidnightControlsConfig.setButtonBinding(binding, UNBOUND);
|
MidnightControlsConfig.setButtonBinding(binding, UNBOUND);
|
||||||
gui.focusedBinding = null;
|
gui.focusedBinding = null;
|
||||||
MidnightControlsClient.get().input.beginControlsInput(null);
|
MidnightControlsClient.input.beginControlsInput(null);
|
||||||
}) {
|
}) {
|
||||||
protected Text getNarrationMessage() {
|
protected Text getNarrationMessage() {
|
||||||
return Text.translatable("midnightcontrols.narrator.unbound", bindingName);
|
return Text.translatable("midnightcontrols.narrator.unbound", bindingName);
|
||||||
@@ -226,14 +240,14 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
/* Rendering */
|
/* Rendering */
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
boolean focused = gui.focusedBinding == this.binding;
|
boolean focused = gui.focusedBinding == this.binding;
|
||||||
|
|
||||||
var textRenderer = ControlsListWidget.this.client.textRenderer;
|
var textRenderer = ControlsListWidget.this.client.textRenderer;
|
||||||
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, this.bindingName, this.getX(), (float) (textY - 9 / 2), 16777215);
|
context.drawText(textRenderer, this.bindingName, this.getX(), (textY - 9 / 2), 16777215, true);
|
||||||
|
|
||||||
this.resetButton.setVisible(!focused);
|
this.resetButton.setVisible(!focused);
|
||||||
this.unbindButton.setVisible(focused);
|
this.unbindButton.setVisible(focused);
|
||||||
@@ -252,7 +266,7 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
this.editButton.setMessage(text.formatted(Formatting.GOLD));
|
this.editButton.setMessage(text.formatted(Formatting.GOLD));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.children.forEach(widget -> widget.render(matrices, mouseX, mouseY, delta));
|
this.children.forEach(widget -> widget.render(context, mouseX, mouseY, delta));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,8 +303,8 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
|||||||
/* Rendering */
|
/* Rendering */
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
this.separatorWidget.render(matrices, mouseX, mouseY, delta);
|
this.separatorWidget.render(context, mouseX, mouseY, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.block.AbstractBlock;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.WorldView;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
@Mixin(AbstractBlock.class)
|
||||||
|
public interface AbstractBlockAccessor {
|
||||||
|
@Invoker("canPlaceAt")
|
||||||
|
boolean midnightcontrols$canPlaceAt(BlockState state, WorldView world, BlockPos pos);
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.AbstractSignEditScreenAccessor;
|
||||||
|
import net.minecraft.block.entity.SignBlockEntity;
|
||||||
|
import net.minecraft.block.entity.SignText;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.AbstractSignEditScreen;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
@Mixin(AbstractSignEditScreen.class)
|
||||||
|
public class AbstractSignEditScreenMixin implements AbstractSignEditScreenAccessor {
|
||||||
|
@Shadow @Final private String[] messages;
|
||||||
|
@Shadow private SignText text;
|
||||||
|
@Shadow @Final protected SignBlockEntity blockEntity;
|
||||||
|
@Shadow @Final private boolean front;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] midnightcontrols$getMessages() {
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void midnightcontrols$setMessage(int line, String text) {
|
||||||
|
this.messages[line] = text;
|
||||||
|
this.text = this.text.withMessage(line, Text.literal(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void midnightcontrols$writeToBlockEntity() {
|
||||||
|
this.blockEntity.setText(this.text, this.front);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
||||||
|
import net.minecraft.client.util.SelectionManager;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
@Mixin(BookEditScreen.class)
|
||||||
|
public interface BookEditScreenAccessor {
|
||||||
|
@Accessor("signing")
|
||||||
|
boolean midnightcontrols$isSigning();
|
||||||
|
|
||||||
|
@Accessor("title")
|
||||||
|
String midnightcontrols$getTitle();
|
||||||
|
|
||||||
|
@Accessor("title")
|
||||||
|
void midnightcontrols$setTitle(String title);
|
||||||
|
|
||||||
|
@Accessor("currentPageSelectionManager")
|
||||||
|
SelectionManager midnightcontrols$getCurrentPageSelectionManager();
|
||||||
|
|
||||||
|
@Invoker("getCurrentPageContent")
|
||||||
|
String midnightcontrols$getCurrentPageContent();
|
||||||
|
|
||||||
|
@Invoker("setPageContent")
|
||||||
|
void midnightcontrols$setPageContent(String newContent);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.screen.ChatScreen;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ChatScreen.class)
|
||||||
|
public abstract class ChatScreenMixin extends Screen {
|
||||||
|
@Shadow protected TextFieldWidget chatField;
|
||||||
|
|
||||||
|
protected ChatScreenMixin(Text title) {
|
||||||
|
super(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(at = @At("TAIL"), method = "init")
|
||||||
|
private void midnightcontrols$moveInputField(CallbackInfo ci) {
|
||||||
|
if (MidnightControlsConfig.moveChat) chatField.setY(4);
|
||||||
|
}
|
||||||
|
@Inject(method = "render", at = @At("HEAD"))
|
||||||
|
private void midnightcontrols$moveInputFieldBackground(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||||
|
if (MidnightControlsConfig.moveChat) context.getMatrices().translate(0f, -this.height + 16, 0f);
|
||||||
|
}
|
||||||
|
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/TextFieldWidget;render(Lnet/minecraft/client/gui/DrawContext;IIF)V", shift = At.Shift.BEFORE))
|
||||||
|
private void midnightcontrols$dontMoveOtherStuff(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||||
|
if (MidnightControlsConfig.moveChat) context.getMatrices().translate(0f, this.height - 16, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
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;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
@@ -36,10 +37,10 @@ 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 midnightcontrols$driftingPrevented = false;
|
@Unique private boolean midnightcontrols$driftingPrevented = false;
|
||||||
|
|
||||||
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile, @Nullable PlayerPublicKey publicKey) {
|
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
|
||||||
super(world, profile, publicKey);
|
super(world, profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
@@ -76,7 +77,7 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick(ZF)V", shift = At.Shift.AFTER))
|
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick()V", shift = At.Shift.AFTER))
|
||||||
public void onInputUpdate(CallbackInfo ci) {
|
public void onInputUpdate(CallbackInfo ci) {
|
||||||
MovementHandler.HANDLER.applyMovement((ClientPlayerEntity) (Object) this);
|
MovementHandler.HANDLER.applyMovement((ClientPlayerEntity) (Object) this);
|
||||||
}
|
}
|
||||||
@@ -87,11 +88,11 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
|
|||||||
if (MidnightControlsConfig.verticalFlyDrifting || !MidnightControls.isExtrasLoaded)
|
if (MidnightControlsConfig.verticalFlyDrifting || !MidnightControls.isExtrasLoaded)
|
||||||
return;
|
return;
|
||||||
int moving = 0;
|
int moving = 0;
|
||||||
if (this.input.sneaking) {
|
if (this.input.playerInput.sneak()) {
|
||||||
--moving;
|
--moving;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.input.jumping) {
|
if (this.input.playerInput.jump()) {
|
||||||
++moving;
|
++moving;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ 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;
|
||||||
|
import net.minecraft.item.ItemGroups;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -29,8 +30,8 @@ public interface CreativeInventoryScreenAccessor {
|
|||||||
* @return the selected tab index
|
* @return the selected tab index
|
||||||
*/
|
*/
|
||||||
@Accessor("selectedTab")
|
@Accessor("selectedTab")
|
||||||
static int getSelectedTab() {
|
static ItemGroup getSelectedTab() {
|
||||||
return 0;
|
return ItemGroups.getDefaultTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,4 +58,10 @@ public interface CreativeInventoryScreenAccessor {
|
|||||||
*/
|
*/
|
||||||
@Invoker("hasScrollbar")
|
@Invoker("hasScrollbar")
|
||||||
boolean midnightcontrols$hasScrollbar();
|
boolean midnightcontrols$hasScrollbar();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers searching the creative inventory from the current value of the internal {@link net.minecraft.client.gui.widget.TextFieldWidget}
|
||||||
|
*/
|
||||||
|
@Invoker("search")
|
||||||
|
void midnightcontrols$search();
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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 net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(DrawContext.class)
|
||||||
|
public interface DrawContextAccessor {
|
||||||
|
@Accessor("vertexConsumers")
|
||||||
|
VertexConsumerProvider.Immediate getVertexConsumers();
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.client.gui.MidnightControlsSettingsScreen;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
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.OptionListWidget;
|
||||||
|
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the new controls settings button.
|
||||||
|
*/
|
||||||
|
@Mixin(GameOptionsScreen.class)
|
||||||
|
public abstract class GameOptionsScreenMixin extends Screen {
|
||||||
|
@Shadow @Nullable protected OptionListWidget body;
|
||||||
|
@Unique TextIconButtonWidget midnightcontrols$button = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"),
|
||||||
|
(button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true)
|
||||||
|
.dimension(20,20).texture(id("icon/controller"), 20, 20).build();
|
||||||
|
|
||||||
|
protected GameOptionsScreenMixin(Text title) {
|
||||||
|
super(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "initBody", at = @At("TAIL"))
|
||||||
|
public void midnightcontrols$addMCButton(CallbackInfo ci) {
|
||||||
|
if (this.getClass().toString().equals(ControlsOptionsScreen.class.toString())) {
|
||||||
|
this.midnightcontrols$setButtonPos();
|
||||||
|
this.addSelectableChild(midnightcontrols$button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Inject(method = "init", at = @At("TAIL"))
|
||||||
|
public void midnightcontrols$drawMCButton(CallbackInfo ci) {
|
||||||
|
if (this.getClass().toString().equals(ControlsOptionsScreen.class.toString())) {
|
||||||
|
this.addDrawableChild(midnightcontrols$button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "refreshWidgetPositions", at = @At("TAIL"))
|
||||||
|
public void midnightcontrols$onResize(CallbackInfo ci) {
|
||||||
|
this.midnightcontrols$setButtonPos();
|
||||||
|
}
|
||||||
|
@Unique
|
||||||
|
public void midnightcontrols$setButtonPos() {
|
||||||
|
if (body != null) {
|
||||||
|
midnightcontrols$button.setPosition(body.getWidth() / 2 + 158, body.getY() + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.llamalad7.mixinextras.sugar.Local;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
|
import net.minecraft.client.render.RenderTickCounter;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(GameRenderer.class)
|
||||||
|
public abstract class GameRendererMixin {
|
||||||
|
@Shadow @Final private MinecraftClient client;
|
||||||
|
|
||||||
|
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getScaledX(Lnet/minecraft/client/util/Window;)D", shift = At.Shift.BEFORE))
|
||||||
|
private void midnightcontrols$onRender(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) {
|
||||||
|
if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER)
|
||||||
|
MidnightControlsClient.input.onPreRenderScreen(this.client.currentScreen);
|
||||||
|
}
|
||||||
|
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;draw()V", shift = At.Shift.BEFORE))
|
||||||
|
private void midnightcontrols$renderVirtualCursor(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) {
|
||||||
|
MidnightControlsRenderer.renderVirtualCursor(drawContext, client);
|
||||||
|
if (MidnightControlsClient.isWayland) MidnightControlsRenderer.renderWaylandCursor(drawContext, client);
|
||||||
|
drawContext.draw();
|
||||||
|
}
|
||||||
|
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z"), method = "renderWorld")
|
||||||
|
private void midnigtcontrols$captureMatrices(RenderTickCounter tickCounter, CallbackInfo ci, @Local(ordinal = 2) Matrix4f matrices) {
|
||||||
|
TouchUtils.lastProjMat.set(RenderSystem.getProjectionMatrix());
|
||||||
|
TouchUtils.lastModMat.set(RenderSystem.getModelViewMatrix());
|
||||||
|
TouchUtils.lastWorldSpaceMatrix.set(matrices);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,24 +9,22 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.EMICompat;
|
import eu.midnightdust.midnightcontrols.client.compat.EMICompat;
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
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.Slot;
|
||||||
import net.minecraft.screen.slot.SlotActionType;
|
import net.minecraft.screen.slot.SlotActionType;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
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.Accessor;
|
||||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -55,28 +53,27 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor {
|
|||||||
public abstract void midnightcontrols$onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
|
public abstract void midnightcontrols$onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
|
||||||
|
|
||||||
@Inject(method = "render", at = @At("RETURN"))
|
@Inject(method = "render", at = @At("RETURN"))
|
||||||
public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
public void onRender(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.hudEnable) {
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.hudEnable) {
|
||||||
var client = MinecraftClient.getInstance();
|
var client = MinecraftClient.getInstance();
|
||||||
matrices.push();
|
|
||||||
int x = 2, y = client.getWindow().getScaledHeight() - 2 - MidnightControlsRenderer.ICON_SIZE;
|
int x = 2, y = client.getWindow().getScaledHeight() - 2 - MidnightControlsRenderer.ICON_SIZE;
|
||||||
if (MidnightControlsCompat.isEMIPresent() && EMICompat.isEMIEnabled()) {
|
if (PlatformFunctions.isModLoaded("emi") && EMICompat.isEMIEnabled()) {
|
||||||
x += 42;
|
x += 42;
|
||||||
}
|
}
|
||||||
if (!ButtonBinding.TAKE_ALL.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, ButtonBinding.TAKE_ALL,true, client) + 2;
|
if (!ButtonBinding.TAKE_ALL.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(context, x, y, ButtonBinding.TAKE_ALL,true, client) + 2;
|
||||||
if (!ButtonBinding.EXIT.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, ButtonBinding.EXIT, true, client) + 2;
|
if (!ButtonBinding.EXIT.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(context, x, y, ButtonBinding.EXIT, true, client) + 2;
|
||||||
if (MidnightControlsCompat.isReiPresent()) {
|
if (PlatformFunctions.isModLoaded("roughlyenoughitems")) {
|
||||||
x = 2;
|
x = 2;
|
||||||
y -= 24;
|
y -= 24;
|
||||||
}
|
}
|
||||||
if (MidnightControlsCompat.isEMIPresent() && EMICompat.isEMIEnabled() && EMICompat.isSearchBarCentered()) {
|
if (PlatformFunctions.isModLoaded("emi") && EMICompat.isEMIEnabled() && EMICompat.isSearchBarCentered()) {
|
||||||
x = client.getWindow().getScaledWidth() - 55 - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.pickup"))
|
x = client.getWindow().getScaledWidth() - 4 - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.pickup"))
|
||||||
- client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.quick_move"))
|
- client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.quick_move"))
|
||||||
- MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.TAKE) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.QUICK_MOVE);
|
- 2 * MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.TAKE) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.QUICK_MOVE);
|
||||||
|
y += 2;
|
||||||
}
|
}
|
||||||
if (!ButtonBinding.TAKE.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, ButtonBinding.TAKE, true, client);
|
if (!ButtonBinding.TAKE.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(context, x, y, ButtonBinding.TAKE, true, client);
|
||||||
if (!ButtonBinding.QUICK_MOVE.isNotBound()) MidnightControlsRenderer.drawButtonTip(matrices, x, y, ButtonBinding.QUICK_MOVE, true, client);
|
if (!ButtonBinding.QUICK_MOVE.isNotBound()) MidnightControlsRenderer.drawButtonTip(context, x, y, ButtonBinding.QUICK_MOVE, true, client);
|
||||||
matrices.pop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.client.input.Input;
|
||||||
|
import net.minecraft.util.math.Vec2f;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(Input.class)
|
||||||
|
public interface InputAccessor {
|
||||||
|
@Accessor
|
||||||
|
void setMovementVector(Vec2f input);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.client.util.InputUtil;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
@Mixin(InputUtil.class)
|
||||||
|
public abstract class InputUtilMixin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kabliz
|
||||||
|
* @reason This method is static, and there is a terrible UX issue if raw input is turned on at the same time as
|
||||||
|
* eye tracking. Raw input only tracks literal mice and not other devices, leading to the game appearing to be
|
||||||
|
* unresponsive and the player not understanding why. This overwrite preserves the user's mouse preferences,
|
||||||
|
* while not interfering with eye tracking, and the two modes can be switched between during a play session.
|
||||||
|
*/
|
||||||
|
@Inject(method = "isRawMouseMotionSupported", at = @At("HEAD"), cancellable = true)
|
||||||
|
private static void setRawMouseMotionSupported(CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
if (MidnightControlsConfig.eyeTrackerAsMouse) cir.setReturnValue(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
@Mixin(KeyBinding.class)
|
@Mixin(KeyBinding.class)
|
||||||
public class KeyBindingMixin implements KeyBindingAccessor {
|
public abstract class KeyBindingMixin implements KeyBindingAccessor {
|
||||||
@Shadow
|
@Shadow
|
||||||
private int timesPressed;
|
private int timesPressed;
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||||
|
import net.minecraft.client.Keyboard;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
@Mixin(Keyboard.class)
|
||||||
|
public class KeyboardMixin {
|
||||||
|
@Redirect(method = "onKey", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;"))
|
||||||
|
private Screen midnightcontrols$ignoreTouchOverlay(MinecraftClient instance) {
|
||||||
|
if (instance.currentScreen instanceof TouchscreenOverlay) return null;
|
||||||
|
return instance.currentScreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,18 +9,16 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
import com.llamalad7.mixinextras.sugar.Local;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||||
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;
|
||||||
import net.minecraft.client.network.ClientPlayerInteractionManager;
|
import net.minecraft.client.network.ClientPlayerInteractionManager;
|
||||||
import net.minecraft.client.render.GameRenderer;
|
import net.minecraft.client.render.GameRenderer;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.client.world.ClientWorld;
|
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
@@ -30,44 +28,45 @@ import net.minecraft.util.hit.HitResult;
|
|||||||
import net.minecraft.util.math.BlockPos;
|
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 net.minecraft.util.profiler.Profiler;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.lwjgl.glfw.GLFW;
|
||||||
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;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.reacharound;
|
||||||
|
|
||||||
@Mixin(MinecraftClient.class)
|
@Mixin(MinecraftClient.class)
|
||||||
public abstract class MinecraftClientMixin {
|
public abstract class MinecraftClientMixin {
|
||||||
@Shadow
|
@Shadow @Nullable public HitResult crosshairTarget;
|
||||||
@Nullable
|
|
||||||
public HitResult crosshairTarget;
|
|
||||||
|
|
||||||
@Shadow
|
@Shadow @Nullable public ClientPlayerEntity player;
|
||||||
@Nullable
|
|
||||||
public ClientPlayerEntity player;
|
|
||||||
|
|
||||||
@Shadow
|
@Shadow @Nullable public ClientPlayerInteractionManager interactionManager;
|
||||||
@Nullable
|
|
||||||
public ClientPlayerInteractionManager interactionManager;
|
|
||||||
|
|
||||||
@Shadow
|
@Shadow @Final public GameRenderer gameRenderer;
|
||||||
@Final
|
|
||||||
public GameRenderer gameRenderer;
|
|
||||||
|
|
||||||
@Shadow
|
@Shadow private int itemUseCooldown;
|
||||||
private int itemUseCooldown;
|
|
||||||
|
|
||||||
private BlockPos midnightcontrols$lastTargetPos;
|
@Shadow public abstract void setScreen(Screen screen);
|
||||||
private Vec3d midnightcontrols$lastPos;
|
|
||||||
private Direction midnightcontrols$lastTargetSide;
|
@Shadow public int attackCooldown;
|
||||||
|
|
||||||
|
@Shadow protected abstract void handleInputEvents();
|
||||||
|
|
||||||
|
@Unique private BlockPos midnightcontrols$lastTargetPos;
|
||||||
|
@Unique private Vec3d midnightcontrols$lastPos;
|
||||||
|
@Unique 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) {
|
||||||
MidnightControlsClient.get().onMcInit((MinecraftClient) (Object) this);
|
MidnightControlsClient.onMcInit((MinecraftClient) (Object) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "tick", at = @At("HEAD"))
|
@Inject(method = "tick", at = @At("HEAD"))
|
||||||
@@ -88,7 +87,7 @@ public abstract class MinecraftClientMixin {
|
|||||||
var side = hitResult.getSide();
|
var side = hitResult.getSide();
|
||||||
|
|
||||||
boolean sidewaysBlockPlacing = this.midnightcontrols$lastTargetPos == null || !targetPos.equals(this.midnightcontrols$lastTargetPos.offset(this.midnightcontrols$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.midnightcontrols$lastTargetPos == null || targetPos.equals(this.midnightcontrols$lastTargetPos.offset(this.midnightcontrols$lastTargetSide)));
|
boolean backwardsBlockPlacing = this.player.input.getMovementInput().y < 0.0f && (this.midnightcontrols$lastTargetPos == null || targetPos.equals(this.midnightcontrols$lastTargetPos.offset(this.midnightcontrols$lastTargetSide)));
|
||||||
|
|
||||||
if (cooldown > 1
|
if (cooldown > 1
|
||||||
&& !targetPos.equals(this.midnightcontrols$lastTargetPos)
|
&& !targetPos.equals(this.midnightcontrols$lastTargetPos)
|
||||||
@@ -109,37 +108,37 @@ public abstract class MinecraftClientMixin {
|
|||||||
// }
|
// }
|
||||||
this.midnightcontrols$lastPos = this.player.getPos();
|
this.midnightcontrols$lastPos = this.player.getPos();
|
||||||
}
|
}
|
||||||
@Inject(method = "render", at = @At("HEAD"))
|
|
||||||
private void onRender(CallbackInfo ci) {
|
@Inject(at = @At("TAIL"), method = "setScreen")
|
||||||
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
private void setScreen(Screen screen, CallbackInfo info) {
|
||||||
}
|
if (MidnightControlsConfig.hideNormalMouse){
|
||||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.AFTER))
|
if (screen != null && !(screen instanceof TouchscreenOverlay)) GLFW.glfwSetInputMode(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_HIDDEN);
|
||||||
private void renderVirtualCursor(boolean fullRender, CallbackInfo ci) {
|
else GLFW.glfwSetInputMode(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
|
||||||
MidnightControlsRenderer.renderVirtualCursor(new MatrixStack(), (MinecraftClient) (Object) this);
|
}
|
||||||
|
MidnightControlsClient.onScreenOpen(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@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;"), cancellable = true)
|
||||||
private void onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand) {
|
private void onItemUse(CallbackInfo ci, @Local Hand hand, @Local ItemStack stackInHand) {
|
||||||
var mod = MidnightControlsClient.get();
|
if (player != null && !stackInHand.isEmpty() && this.player.getPitch(0.f) > 35.0F && 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) {
|
||||||
var hitResult = mod.reacharound.getLastReacharoundResult();
|
var hitResult = reacharound.getLastReacharoundResult();
|
||||||
|
|
||||||
if (hitResult == null)
|
if (hitResult == null || this.interactionManager == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hitResult = mod.reacharound.withSideForReacharound(hitResult, stackInHand);
|
hitResult = reacharound.withSideForReacharound(hitResult, stackInHand);
|
||||||
|
|
||||||
int previousStackCount = stackInHand.getCount();
|
int previousStackCount = stackInHand.getCount();
|
||||||
var result = this.interactionManager.interactBlock(this.player, hand, hitResult);
|
var result = this.interactionManager.interactBlock(this.player, hand, hitResult);
|
||||||
if (result.isAccepted()) {
|
if (result.isAccepted()) {
|
||||||
if (result.shouldSwingHand()) {
|
//if (result.shouldSwingHand()) {
|
||||||
this.player.swingHand(hand);
|
this.player.swingHand(hand);
|
||||||
if (!stackInHand.isEmpty() && (stackInHand.getCount() != previousStackCount || this.interactionManager.hasCreativeInventory())) {
|
if (!stackInHand.isEmpty() && (stackInHand.getCount() != previousStackCount || this.player.isInCreativeMode())) {
|
||||||
this.gameRenderer.firstPersonRenderer.resetEquipProgress(hand);
|
this.gameRenderer.firstPersonRenderer.resetEquipProgress(hand);
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
|
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
}
|
}
|
||||||
@@ -151,4 +150,21 @@ public abstract class MinecraftClientMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: Replace this with MixinExtras' Expressions once that's officially released
|
||||||
|
@Inject(method = "tick", at = @At(value = "INVOKE",target = "Lnet/minecraft/client/gui/hud/DebugHud;shouldShowDebugHud()Z"))
|
||||||
|
private void midnightcontrols$handleKeybindsWithTouchOverlay(CallbackInfo ci, @Local Profiler profiler) {
|
||||||
|
if (client.currentScreen instanceof TouchscreenOverlay) {
|
||||||
|
profiler.swap("Keybindings");
|
||||||
|
this.handleInputEvents();
|
||||||
|
if (this.attackCooldown > 0) {
|
||||||
|
--this.attackCooldown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed, as it will cause item actions not to work in touchscreen mode otherwise with the above method
|
||||||
|
@Inject(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z"), cancellable = true)
|
||||||
|
private void midnightcontrols$dontHandleItemAndBlockInteractions(CallbackInfo ci) {
|
||||||
|
if (client.currentScreen instanceof TouchscreenOverlay) ci.cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.client.Mouse;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
@Mixin(Mouse.class)
|
||||||
|
public interface MouseAccessor {
|
||||||
|
@Invoker("onCursorPos")
|
||||||
|
void midnightcontrols$onCursorPos(long window, double x, double y);
|
||||||
|
@Invoker("onMouseButton")
|
||||||
|
void midnightcontrols$onMouseButton(long window, int button, int action, int mods);
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* 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.touch.gui.TouchscreenOverlay;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.Mouse;
|
||||||
|
import net.minecraft.client.util.GlfwUtil;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.ThrowablePotionItem;
|
||||||
|
import net.minecraft.item.consume.UseAction;
|
||||||
|
import net.minecraft.util.math.Smoother;
|
||||||
|
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.Unique;
|
||||||
|
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;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mouse.EyeTrackerHandler;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsConfig.doMixedInput;
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds extra access to the mouse.
|
||||||
|
*/
|
||||||
|
@Mixin(Mouse.class)
|
||||||
|
public abstract class MouseMixin implements MouseAccessor {
|
||||||
|
@Shadow @Final private MinecraftClient client;
|
||||||
|
|
||||||
|
@Shadow private double y;
|
||||||
|
|
||||||
|
@Shadow private double cursorDeltaX;
|
||||||
|
|
||||||
|
@Shadow private double cursorDeltaY;
|
||||||
|
|
||||||
|
@Shadow private double x;
|
||||||
|
|
||||||
|
@Shadow private boolean cursorLocked;
|
||||||
|
|
||||||
|
@Shadow private boolean hasResolutionChanged;
|
||||||
|
|
||||||
|
@Shadow private double glfwTime;
|
||||||
|
|
||||||
|
@Shadow @Final private Smoother cursorXSmoother;
|
||||||
|
|
||||||
|
@Shadow @Final private Smoother cursorYSmoother;
|
||||||
|
|
||||||
|
@Shadow private boolean leftButtonClicked;
|
||||||
|
|
||||||
|
@Inject(method = "onMouseButton", at = @At(value = "HEAD"), cancellable = true)
|
||||||
|
private void midnightcontrols$onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) {
|
||||||
|
if (window != this.client.getWindow().getHandle()) return;
|
||||||
|
if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && client.currentScreen != null) {
|
||||||
|
MidnightControlsClient.input.tryGoBack(client.currentScreen);
|
||||||
|
}
|
||||||
|
else if ((client.currentScreen == null && doMixedInput() || client.currentScreen instanceof TouchscreenOverlay) && client.player != null && button == GLFW_MOUSE_BUTTON_1) {
|
||||||
|
double mouseX = x / client.getWindow().getScaleFactor();
|
||||||
|
double mouseY = y / client.getWindow().getScaleFactor();
|
||||||
|
int centerX = client.getWindow().getScaledWidth() / 2;
|
||||||
|
if (action == 1 && mouseY >= (double) (client.getWindow().getScaledHeight() - 22) && 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)) {
|
||||||
|
client.player.getInventory().setSelectedSlot(slot);
|
||||||
|
TouchInput.clickStartTime = -1;
|
||||||
|
ci.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (action == 1) {
|
||||||
|
TouchInput.clickStartTime = System.currentTimeMillis();
|
||||||
|
boolean bl = false;
|
||||||
|
if (client.currentScreen instanceof TouchscreenOverlay overlay) bl = overlay.mouseClicked(mouseX, mouseY, button);
|
||||||
|
if (!bl) TouchInput.firstHitResult = TouchUtils.getTargetedObject(mouseX, mouseY);
|
||||||
|
if (client.currentScreen == null) ci.cancel();
|
||||||
|
}
|
||||||
|
else if (TouchInput.mouseReleased(mouseX, mouseY, button)) ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void midnightcontrols$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 midnightcontrols$onCursorLocked(CallbackInfo ci) {
|
||||||
|
if ((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse) ||
|
||||||
|
MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN || doMixedInput())
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "updateMouse", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void midnightcontrols$updateMouse(CallbackInfo ci) {
|
||||||
|
if (MidnightControlsConfig.eyeTrackerAsMouse && cursorLocked && client.isWindowFocused()) {
|
||||||
|
// Eye Tracking is only for the camera controlling cursor, we need the normal cursor everywhere else.
|
||||||
|
if (!client.options.smoothCameraEnabled) {
|
||||||
|
cursorXSmoother.clear();
|
||||||
|
cursorYSmoother.clear();
|
||||||
|
}
|
||||||
|
EyeTrackerHandler.updateMouseWithEyeTracking(x + cursorDeltaX, y + cursorDeltaY, client,
|
||||||
|
glfwTime, leftButtonClicked, midnightcontrols$isUsingLongRangedTool(), cursorXSmoother, cursorYSmoother);
|
||||||
|
glfwTime = GlfwUtil.getTime();
|
||||||
|
cursorDeltaX = 0.0;
|
||||||
|
cursorDeltaY = 0.0;
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
if (doMixedInput() && client.isWindowFocused()) {
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private boolean midnightcontrols$isUsingLongRangedTool() {
|
||||||
|
if (client.player == null) return false;
|
||||||
|
ItemStack stack = client.player.getActiveItem();
|
||||||
|
return (leftButtonClicked && (stack.getUseAction() == UseAction.BOW || stack.getUseAction() == UseAction.CROSSBOW ||
|
||||||
|
stack.getUseAction() == UseAction.SPEAR || stack.getItem() instanceof ThrowablePotionItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/InputUtil;setCursorParameters(JIDD)V",shift = At.Shift.BEFORE), cancellable = true)
|
||||||
|
private void midnightcontrols$lockCursor(CallbackInfo ci) {
|
||||||
|
if ((doMixedInput() || MidnightControlsConfig.eyeTrackerAsMouse)) {
|
||||||
|
//In eye tracking mode, we cannot have the cursor locked to the center.
|
||||||
|
GLFW.glfwSetInputMode(client.getWindow().getHandle(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||||
|
client.setScreen(null);
|
||||||
|
hasResolutionChanged = true;
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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 net.minecraft.client.gui.screen.ingame.RecipeBookScreen;
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(RecipeBookScreen.class)
|
||||||
|
public interface RecipeBookScreenAccessor {
|
||||||
|
@Accessor("recipeBook")
|
||||||
|
RecipeBookWidget<?> getRecipeBook();
|
||||||
|
}
|
||||||
@@ -27,7 +27,4 @@ public interface RecipeBookWidgetAccessor {
|
|||||||
|
|
||||||
@Accessor("currentTab")
|
@Accessor("currentTab")
|
||||||
void setCurrentTab(RecipeGroupButtonWidget currentTab);
|
void setCurrentTab(RecipeGroupButtonWidget currentTab);
|
||||||
|
|
||||||
@Invoker("refreshResults")
|
|
||||||
void midnightcontrols$refreshResults(boolean resetCurrentPage);
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputHandlers;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.gui.SilentTexturedButtonWidget;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.Drawable;
|
||||||
|
import net.minecraft.client.gui.Element;
|
||||||
|
import net.minecraft.client.gui.Selectable;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay.WIDGETS_LOCATION;
|
||||||
|
|
||||||
|
@Mixin(Screen.class)
|
||||||
|
public abstract class ScreenMixin {
|
||||||
|
@Shadow protected abstract <T extends Element & Drawable & Selectable> T addDrawableChild(T drawableElement);
|
||||||
|
|
||||||
|
@Shadow public int width;
|
||||||
|
|
||||||
|
@Inject(method = "init(Lnet/minecraft/client/MinecraftClient;II)V", at = @At("TAIL"))
|
||||||
|
public void midnightcontrols$addCloseButton(MinecraftClient client, int width, int height, CallbackInfo ci) {
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && (MidnightControlsConfig.closeButtonScreens.stream().anyMatch(s -> this.getClass().getName().startsWith(s) || ((Object)this) instanceof HandledScreen<?>))) {
|
||||||
|
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(this.width - 30, 10), 20, 20, Text.empty(), btn ->
|
||||||
|
InputHandlers.handleExit().press(client, ButtonBinding.BACK, 0f, ButtonState.PRESS), 20, 160, 20, WIDGETS_LOCATION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import net.minecraft.client.gui.tab.Tab;
|
||||||
|
import net.minecraft.client.gui.tab.TabManager;
|
||||||
|
import net.minecraft.client.gui.widget.TabNavigationWidget;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(TabNavigationWidget.class)
|
||||||
|
public interface TabNavigationWidgetAccessor {
|
||||||
|
@Accessor
|
||||||
|
TabManager getTabManager();
|
||||||
|
@Accessor
|
||||||
|
ImmutableList<Tab> getTabs();
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* 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.MidnightColorUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.TouchMode;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
|
||||||
|
import net.minecraft.block.ShapeContext;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.*;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.item.BlockItem;
|
||||||
|
import net.minecraft.item.ItemPlacementContext;
|
||||||
|
import net.minecraft.item.ItemUsageContext;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
import net.minecraft.util.hit.HitResult;
|
||||||
|
import net.minecraft.util.math.ColorHelper;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
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.Redirect;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.reacharound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a mixin to WorldRenderer.
|
||||||
|
* <p>
|
||||||
|
* Handles the rendering of the block outline of the reach-around features.
|
||||||
|
*/
|
||||||
|
@Mixin(WorldRenderer.class)
|
||||||
|
public abstract class WorldRendererMixin {
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private MinecraftClient client;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
private ClientWorld world;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private BufferBuilderStorage bufferBuilders;
|
||||||
|
|
||||||
|
@Redirect(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/BlockHitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"))
|
||||||
|
private HitResult.Type dontRenderOutline(BlockHitResult instance) {
|
||||||
|
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
|
||||||
|
return HitResult.Type.MISS;
|
||||||
|
}
|
||||||
|
return instance.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(
|
||||||
|
method = "renderTargetBlockOutline",
|
||||||
|
at = @At("HEAD")
|
||||||
|
)
|
||||||
|
private void onOutlineRender(Camera camera, VertexConsumerProvider.Immediate vertexConsumers, MatrixStack matrices, boolean translucent, CallbackInfo ci) {
|
||||||
|
if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN)
|
||||||
|
&& MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
|
||||||
|
this.midnightcontrols$renderFingerOutline(matrices, camera);
|
||||||
|
}
|
||||||
|
this.midnightcontrols$renderReacharoundOutline(matrices, camera);
|
||||||
|
}
|
||||||
|
@Unique
|
||||||
|
private void midnightcontrols$renderFingerOutline(MatrixStack matrices, Camera camera) {
|
||||||
|
if (TouchInput.firstHitResult == null || TouchInput.firstHitResult.getType() != HitResult.Type.BLOCK)
|
||||||
|
return;
|
||||||
|
BlockHitResult result = (BlockHitResult) TouchInput.firstHitResult;
|
||||||
|
var blockPos = result.getBlockPos();
|
||||||
|
if (this.world.getWorldBorder().contains(blockPos) && this.client.player != null) {
|
||||||
|
var outlineShape = this.world.getBlockState(blockPos).getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
|
||||||
|
Color rgb = MidnightColorUtil.hex2Rgb(MidnightControlsConfig.touchOutlineColorHex);
|
||||||
|
if (MidnightControlsConfig.touchOutlineColorHex.isEmpty()) rgb = RainbowColor.radialRainbow(1,1);
|
||||||
|
var pos = camera.getPos();
|
||||||
|
matrices.push();
|
||||||
|
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
|
||||||
|
VertexRendering.drawOutline(matrices, vertexConsumer, outlineShape, blockPos.getX() - pos.getX(), blockPos.getY() - pos.getY(), blockPos.getZ() - pos.getZ(),
|
||||||
|
ColorHelper.withAlpha(MidnightControlsConfig.touchOutlineColorAlpha, rgb.getRGB()));
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Unique
|
||||||
|
private void midnightcontrols$renderReacharoundOutline(MatrixStack matrices, Camera camera) {
|
||||||
|
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !MidnightControlsConfig.shouldRenderReacharoundOutline)
|
||||||
|
return;
|
||||||
|
var result = reacharound.getLastReacharoundResult();
|
||||||
|
if (result == null)
|
||||||
|
return;
|
||||||
|
var blockPos = result.getBlockPos();
|
||||||
|
if (this.world.getWorldBorder().contains(blockPos) && this.client.player != null) {
|
||||||
|
var stack = this.client.player.getStackInHand(Hand.MAIN_HAND);
|
||||||
|
if (stack == null || !(stack.getItem() instanceof BlockItem))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var block = ((BlockItem) stack.getItem()).getBlock();
|
||||||
|
result = reacharound.withSideForReacharound(result, block);
|
||||||
|
var context = new ItemPlacementContext(new ItemUsageContext(this.client.player, Hand.MAIN_HAND, result));
|
||||||
|
|
||||||
|
var placementState = block.getPlacementState(context);
|
||||||
|
if (placementState == null)
|
||||||
|
return;
|
||||||
|
var pos = camera.getPos();
|
||||||
|
|
||||||
|
var outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
|
||||||
|
Color rgb = MidnightColorUtil.hex2Rgb(MidnightControlsConfig.reacharoundOutlineColorHex);
|
||||||
|
if (MidnightControlsConfig.reacharoundOutlineColorHex.isEmpty()) rgb = RainbowColor.radialRainbow(1,1);
|
||||||
|
matrices.push();
|
||||||
|
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
|
||||||
|
VertexRendering.drawOutline(matrices, vertexConsumer, outlineShape, blockPos.getX() - pos.getX(), blockPos.getY() - pos.getY(), blockPos.getZ() - pos.getZ(),
|
||||||
|
ColorHelper.withAlpha(MidnightControlsConfig.touchOutlineColorAlpha, rgb.getRGB()));
|
||||||
|
matrices.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.mouse;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.util.GlfwUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import net.minecraft.util.math.Smoother;
|
||||||
|
|
||||||
|
public class EyeTrackerHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on the updateMouse method in the Mouse.class, this changes the mouse algorithm to suit eye tracking.
|
||||||
|
* This requires the cursor to not be locked, and the raw input setting to be turned off.
|
||||||
|
*/
|
||||||
|
public static void updateMouseWithEyeTracking(double mouseX, double mouseY, MinecraftClient client, double lastMouseUpdateTime, boolean holdingLeftMouseButton, boolean usingLongRangedTool, Smoother smoothX, Smoother smoothY) {
|
||||||
|
if (client.player == null) return;
|
||||||
|
/* The player wants objects of interest to be moved under the crosshair that is always center of screen.
|
||||||
|
* Normal mouse controls operate with the delta values from the direction of mouse movement,
|
||||||
|
* but in eye tracking we want to use the cursor's actual x,y values (their point of gaze), relative to
|
||||||
|
* the screen center (where the crosshair is). This new eye tracking delta creates a vector that points
|
||||||
|
* from the crosshair to the gaze point. As the player keeps their eyes on the object of interest, we pull
|
||||||
|
* that object into the center until the object is underneath the crosshair.
|
||||||
|
*/
|
||||||
|
double deltaTime = GlfwUtil.getTime() - lastMouseUpdateTime;
|
||||||
|
|
||||||
|
// The center of screen is the new (0,0)
|
||||||
|
double centerX = client.getWindow().getWidth() / 2.0;
|
||||||
|
double centerY = client.getWindow().getHeight() / 2.0;
|
||||||
|
double gazeRawX = mouseX - centerX;
|
||||||
|
double gazeRawY = mouseY - centerY;
|
||||||
|
|
||||||
|
//This part follows the original mouse.java somewhat closely, with different constants
|
||||||
|
double feeling = 2.5;
|
||||||
|
double sensitivity = client.options.getMouseSensitivity().getValue() * feeling;
|
||||||
|
double spyglass = sensitivity * sensitivity * sensitivity;
|
||||||
|
double moveScalar = spyglass * 8.0;
|
||||||
|
|
||||||
|
double frameScalar;
|
||||||
|
if(client.options.getPerspective().isFirstPerson() && client.player.isUsingSpyglass()) {
|
||||||
|
frameScalar = spyglass;
|
||||||
|
} else {
|
||||||
|
frameScalar = moveScalar;
|
||||||
|
}
|
||||||
|
if(holdingLeftMouseButton && !usingLongRangedTool) {
|
||||||
|
frameScalar *= 0.5; //Don't move the camera so much while mining. It's annoying.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The longest vector connects the center to the corner of the screen, so that is our maximum magnitude for
|
||||||
|
// normalization. We use normalized screen size vector for resolution independent control
|
||||||
|
double magnitudeMax = Math.sqrt(centerX*centerX + centerY*centerY);
|
||||||
|
double normalizedX = gazeRawX / magnitudeMax;
|
||||||
|
double normalizedY = gazeRawY / magnitudeMax;
|
||||||
|
|
||||||
|
double moveX = normalizedX * frameScalar;
|
||||||
|
double moveY = normalizedY * frameScalar;
|
||||||
|
if (client.options.smoothCameraEnabled) {
|
||||||
|
moveX = smoothX.smooth(moveX, moveScalar*deltaTime);
|
||||||
|
moveY = smoothY.smooth(moveY, moveScalar*deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The player entity's needs their facing rotated.
|
||||||
|
double invertY = 1.0;
|
||||||
|
double moveMagnitude = Math.sqrt(normalizedX*normalizedX + normalizedY*normalizedY);
|
||||||
|
if (client.options.getInvertYMouse().getValue()) {
|
||||||
|
invertY = -1.0;
|
||||||
|
}
|
||||||
|
boolean notInDeadzone = (moveMagnitude > MidnightControlsConfig.eyeTrackerDeadzone) && !usingLongRangedTool;
|
||||||
|
if (client.player != null && notInDeadzone) {
|
||||||
|
client.player.changeLookDirection(moveX, moveY * invertY);
|
||||||
|
client.getTutorialManager().onUpdateMouse(moveX, moveY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,16 +9,14 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.Config;
|
import com.google.gson.Gson;
|
||||||
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||||
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.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.option.KeyBinding;
|
|
||||||
import net.minecraft.client.option.StickyKeyBinding;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.text.OrderedText;
|
import net.minecraft.text.OrderedText;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -36,7 +34,6 @@ public class ButtonBindingRingAction extends RingAction {
|
|||||||
this.binding = binding;
|
this.binding = binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.binding.getTranslationKey();
|
return this.binding.getTranslationKey();
|
||||||
}
|
}
|
||||||
@@ -51,10 +48,10 @@ public class ButtonBindingRingAction extends RingAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
public void drawIcon(@NotNull DrawContext context, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
||||||
List<OrderedText> lines = textRenderer.wrapLines(Text.translatable(this.getName()), MidnightRing.ELEMENT_SIZE);
|
List<OrderedText> lines = textRenderer.wrapLines(Text.translatable(this.getName()), MidnightRing.ELEMENT_SIZE);
|
||||||
for (int i = 0; i < lines.size(); ++i) {
|
for (int i = 0; i < lines.size(); ++i) {
|
||||||
drawCenteredTextWithShadow(matrices, textRenderer, lines.get(i), x + MidnightRing.ELEMENT_SIZE / 2, y + MidnightRing.ELEMENT_SIZE / 2 - textRenderer.fontHeight / 2 * (lines.size()-1) - textRenderer.fontHeight / 2 + textRenderer.fontHeight * i, 0xffffff);
|
context.drawCenteredTextWithShadow(textRenderer, lines.get(i), x + MidnightRing.ELEMENT_SIZE / 2, y + MidnightRing.ELEMENT_SIZE / 2 - textRenderer.fontHeight / 2 * (lines.size()-1) - textRenderer.fontHeight / 2 + textRenderer.fontHeight * i, 0xffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +62,7 @@ public class ButtonBindingRingAction extends RingAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable RingAction parse(@NotNull Config config) {
|
public @Nullable RingAction parse(@NotNull Gson config) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
@@ -34,16 +34,14 @@ public final class MidnightRing {
|
|||||||
|
|
||||||
private final Map<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 MidnightControlsClient mod;
|
|
||||||
private int currentPage = 0;
|
private int currentPage = 0;
|
||||||
|
|
||||||
public MidnightRing(@NotNull MidnightControlsClient mod) {
|
public MidnightRing() {
|
||||||
this.mod = mod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerAction(@NotNull String name, @NotNull RingAction.Factory factory) {
|
public void registerAction(@NotNull String name, @NotNull RingAction.Factory factory) {
|
||||||
if (this.actionFactories.containsKey(name)) {
|
if (this.actionFactories.containsKey(name)) {
|
||||||
this.mod.warn("Tried to register a ring action twice: \"" + name + "\".");
|
MidnightControls.warn("Tried to register a ring action twice: \"" + name + "\".");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.actionFactories.put(name, factory);
|
this.actionFactories.put(name, factory);
|
||||||
@@ -64,8 +62,8 @@ public final class MidnightRing {
|
|||||||
for (String binding : configBindings) {
|
for (String binding : configBindings) {
|
||||||
ButtonBinding buttonBinding = InputManager.getBinding(binding);
|
ButtonBinding buttonBinding = InputManager.getBinding(binding);
|
||||||
if (buttonBinding != null) {
|
if (buttonBinding != null) {
|
||||||
RingPage page = this.pages.get(MathHelper.fastFloor(bindingIndex / 8f));
|
RingPage page = this.pages.get(MathHelper.floor(bindingIndex / 8f));
|
||||||
page.actions[bindingIndex - 8 * (MathHelper.fastFloor(bindingIndex / 8f))] = (new ButtonBindingRingAction(buttonBinding));
|
page.actions[bindingIndex - 8 * (MathHelper.floor(bindingIndex / 8f))] = (new ButtonBindingRingAction(buttonBinding));
|
||||||
++bindingIndex;
|
++bindingIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,8 +86,8 @@ public final class MidnightRing {
|
|||||||
|
|
||||||
for (ButtonBinding buttonBinding : unboundBindings) {
|
for (ButtonBinding buttonBinding : unboundBindings) {
|
||||||
if (buttonBinding != null) {
|
if (buttonBinding != null) {
|
||||||
RingPage page = this.pages.get(MathHelper.fastFloor(bindingIndex / 8f));
|
RingPage page = this.pages.get(MathHelper.floor(bindingIndex / 8f));
|
||||||
page.actions[bindingIndex - 8 * (MathHelper.fastFloor(bindingIndex / 8f))] = (new ButtonBindingRingAction(buttonBinding));
|
page.actions[bindingIndex - 8 * (MathHelper.floor(bindingIndex / 8f))] = (new ButtonBindingRingAction(buttonBinding));
|
||||||
++bindingIndex;
|
++bindingIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,11 +9,10 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.Config;
|
import com.google.gson.Gson;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
import net.minecraft.client.font.TextRenderer;
|
||||||
import net.minecraft.client.gui.DrawableHelper;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -28,21 +27,12 @@ import java.util.function.Supplier;
|
|||||||
* @version 1.5.0
|
* @version 1.5.0
|
||||||
* @since 1.4.0
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public abstract class RingAction extends DrawableHelper implements Nameable {
|
public abstract class RingAction {
|
||||||
protected boolean activated = false;
|
protected boolean activated = false;
|
||||||
|
|
||||||
public RingAction() {
|
public RingAction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the text name of the ring action.
|
|
||||||
*
|
|
||||||
* @return the text name
|
|
||||||
*/
|
|
||||||
public Text getTextName() {
|
|
||||||
return Text.translatable(this.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the action is activated or not.
|
* Returns whether the action is activated or not.
|
||||||
*
|
*
|
||||||
@@ -60,12 +50,12 @@ 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, int index) {
|
public void render(@NotNull DrawContext context, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered, int index) {
|
||||||
fill(matrices, x, y, x + MidnightRing.ELEMENT_SIZE, y + MidnightRing.ELEMENT_SIZE, hovered || RingPage.selected == index ? 0xbb777777 : 0xbb000000);
|
context.fill(x, y, x + MidnightRing.ELEMENT_SIZE, y + MidnightRing.ELEMENT_SIZE, hovered || RingPage.selected == index ? 0xbb777777 : 0xbb000000);
|
||||||
drawIcon(matrices, textRenderer, x, y, hovered);
|
drawIcon(context, textRenderer, x, y, hovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered);
|
public abstract void drawIcon(@NotNull DrawContext context, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a factory for {@link RingAction}.
|
* Represents a factory for {@link RingAction}.
|
||||||
@@ -76,6 +66,6 @@ public abstract class RingAction extends DrawableHelper implements Nameable {
|
|||||||
public interface Factory {
|
public interface Factory {
|
||||||
@NotNull Supplier<RingAction> newFromGui(@NotNull Screen screen);
|
@NotNull Supplier<RingAction> newFromGui(@NotNull Screen screen);
|
||||||
|
|
||||||
@Nullable RingAction parse(@NotNull Config config);
|
@Nullable RingAction parse(@NotNull Gson config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,21 +9,11 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.ring;
|
package eu.midnightdust.midnightcontrols.client.ring;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.Config;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
|
||||||
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.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.ChatScreen;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a ring page.
|
* Represents a ring page.
|
||||||
*
|
*
|
||||||
@@ -31,7 +21,7 @@ import java.util.Optional;
|
|||||||
* @version 1.5.0
|
* @version 1.5.0
|
||||||
* @since 1.4.0
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public class RingPage extends DrawableHelper {
|
public class RingPage {
|
||||||
public static final RingPage DEFAULT = new RingPage("Default");
|
public static final RingPage DEFAULT = new RingPage("Default");
|
||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
@@ -48,17 +38,17 @@ public class RingPage extends DrawableHelper {
|
|||||||
/**
|
/**
|
||||||
* Renders the ring page.
|
* Renders the ring page.
|
||||||
*
|
*
|
||||||
* @param matrices the matrices
|
* @param context the context
|
||||||
* @param width the screen width
|
* @param width the screen width
|
||||||
* @param height the screen height
|
* @param height the screen height
|
||||||
* @param mouseX the mouse X-coordinate
|
* @param mouseX the mouse X-coordinate
|
||||||
* @param mouseY the mouse Y-coordinate
|
* @param mouseY the mouse Y-coordinate
|
||||||
* @param tickDelta the tick delta
|
* @param tickDelta the tick delta
|
||||||
*/
|
*/
|
||||||
public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int width, int height, int mouseX, int mouseY, float tickDelta) {
|
public void render(@NotNull DrawContext context, @NotNull TextRenderer textRenderer, int width, int height, int mouseX, int mouseY, float tickDelta) {
|
||||||
int centerX = width / 2;
|
int centerX = width / 2;
|
||||||
int centerY = height / 2;
|
int centerY = height / 2;
|
||||||
if (MidnightControlsClient.get().ring.getMaxPages() > 1) drawCenteredText(matrices, textRenderer, name, centerX, 5, 0xffffff);
|
if (MidnightControlsClient.ring.getMaxPages() > 1) context.drawCenteredTextWithShadow(textRenderer, name, centerX, 5, 0xffffff);
|
||||||
|
|
||||||
int offset = MidnightRing.ELEMENT_SIZE + (MidnightRing.ELEMENT_SIZE / 2) + 5;
|
int offset = MidnightRing.ELEMENT_SIZE + (MidnightRing.ELEMENT_SIZE / 2) + 5;
|
||||||
|
|
||||||
@@ -67,7 +57,7 @@ public class RingPage extends DrawableHelper {
|
|||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
var ringAction = this.actions[i];
|
var ringAction = this.actions[i];
|
||||||
if (ringAction != null)
|
if (ringAction != null)
|
||||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
ringAction.render(context, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
||||||
x += MidnightRing.ELEMENT_SIZE + 5;
|
x += MidnightRing.ELEMENT_SIZE + 5;
|
||||||
}
|
}
|
||||||
y += MidnightRing.ELEMENT_SIZE + 5;
|
y += MidnightRing.ELEMENT_SIZE + 5;
|
||||||
@@ -75,7 +65,7 @@ public class RingPage extends DrawableHelper {
|
|||||||
for (int i = 3; i < 5; i++) {
|
for (int i = 3; i < 5; i++) {
|
||||||
var ringAction = this.actions[i];
|
var ringAction = this.actions[i];
|
||||||
if (ringAction != null)
|
if (ringAction != null)
|
||||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
ringAction.render(context, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
||||||
x += (MidnightRing.ELEMENT_SIZE + 5) * 2;
|
x += (MidnightRing.ELEMENT_SIZE + 5) * 2;
|
||||||
}
|
}
|
||||||
y += MidnightRing.ELEMENT_SIZE + 5;
|
y += MidnightRing.ELEMENT_SIZE + 5;
|
||||||
@@ -83,7 +73,7 @@ public class RingPage extends DrawableHelper {
|
|||||||
for (int i = 5; i < 8; i++) {
|
for (int i = 5; i < 8; i++) {
|
||||||
var ringAction = this.actions[i];
|
var ringAction = this.actions[i];
|
||||||
if (ringAction != null)
|
if (ringAction != null)
|
||||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
ringAction.render(context, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
||||||
x += MidnightRing.ELEMENT_SIZE + 5;
|
x += MidnightRing.ELEMENT_SIZE + 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.touch;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
|
import net.minecraft.util.hit.HitResult;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsConfig.doMixedInput;
|
||||||
|
|
||||||
|
public class TouchInput {
|
||||||
|
private static final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
public static long clickStartTime;
|
||||||
|
public static HitResult firstHitResult = null;
|
||||||
|
public static boolean isDragging = false;
|
||||||
|
|
||||||
|
public static void tick() {
|
||||||
|
if ((client.currentScreen == null && doMixedInput()) || client.currentScreen instanceof TouchscreenOverlay) {
|
||||||
|
double scaleFactor = client.getWindow().getScaleFactor();
|
||||||
|
if (clickStartTime > 0 && System.currentTimeMillis() - clickStartTime >= MidnightControlsConfig.touchBreakDelay) {
|
||||||
|
mouseHeldDown(client.mouse.getX() / scaleFactor, client.mouse.getY() / scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void mouseHeldDown(double mouseX, double mouseY) {
|
||||||
|
assert client != null;
|
||||||
|
assert client.player != null;
|
||||||
|
assert client.interactionManager != null;
|
||||||
|
|
||||||
|
if (client.player.getMainHandStack() != null && TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())) {
|
||||||
|
client.interactionManager.interactItem(client.player, client.player.getActiveHand());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HitResult result = TouchUtils.getTargetedObject(mouseX, mouseY);
|
||||||
|
if (result == null || firstHitResult == null) {
|
||||||
|
client.interactionManager.cancelBlockBreaking();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result instanceof BlockHitResult blockHit && firstHitResult instanceof BlockHitResult firstBlock && blockHit.getBlockPos().equals(firstBlock.getBlockPos())) {
|
||||||
|
if (MidnightControlsConfig.debug) System.out.println(blockHit.getBlockPos().toString());
|
||||||
|
if (client.interactionManager.updateBlockBreakingProgress(blockHit.getBlockPos(), blockHit.getSide())) {
|
||||||
|
client.particleManager.addBlockBreakingParticles(blockHit.getBlockPos(), blockHit.getSide());
|
||||||
|
client.player.swingHand(Hand.MAIN_HAND);
|
||||||
|
} else client.interactionManager.cancelBlockBreaking();
|
||||||
|
firstHitResult = TouchUtils.getTargetedObject(mouseX, mouseY);
|
||||||
|
}
|
||||||
|
else if (result instanceof EntityHitResult entityHit && firstHitResult instanceof EntityHitResult firstEntity && entityHit.getEntity().getUuid().compareTo(firstEntity.getEntity().getUuid()) == 0) {
|
||||||
|
if (client.interactionManager.interactEntity(client.player, entityHit.getEntity(), client.player.getActiveHand()) == ActionResult.SUCCESS) {
|
||||||
|
client.player.swingHand(Hand.MAIN_HAND);
|
||||||
|
}
|
||||||
|
firstHitResult = TouchUtils.getTargetedObject(mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||||
|
isDragging = false;
|
||||||
|
firstHitResult = null;
|
||||||
|
if (client.interactionManager != null) client.interactionManager.cancelBlockBreaking();
|
||||||
|
if ((client.currentScreen == null || !client.currentScreen.mouseReleased(mouseX, mouseY, button)) && System.currentTimeMillis() - clickStartTime < MidnightControlsConfig.touchBreakDelay) {
|
||||||
|
assert client.player != null;
|
||||||
|
assert client.world != null;
|
||||||
|
assert client.interactionManager != null;
|
||||||
|
clickStartTime = -1;
|
||||||
|
|
||||||
|
if (client.player.getMainHandStack() != null && TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())) {
|
||||||
|
client.interactionManager.stopUsingItem(client.player);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
HitResult result = TouchUtils.getTargetedObject(mouseX, mouseY);
|
||||||
|
if (result == null) return false;
|
||||||
|
|
||||||
|
|
||||||
|
if (result instanceof BlockHitResult blockHit) {
|
||||||
|
BlockPos blockPos = blockHit.getBlockPos().offset(blockHit.getSide());
|
||||||
|
BlockState state = client.world.getBlockState(blockPos);
|
||||||
|
|
||||||
|
if (client.world.isAir(blockPos) || state.isReplaceable()) {
|
||||||
|
ItemStack stackInHand = client.player.getMainHandStack();
|
||||||
|
int previousStackCount = stackInHand.getCount();
|
||||||
|
var interaction = client.interactionManager.interactBlock(client.player, client.player.getActiveHand(), blockHit);
|
||||||
|
if (interaction.isAccepted()) {
|
||||||
|
//if (interaction.shouldSwingHand()) {
|
||||||
|
client.player.swingHand(client.player.preferredHand);
|
||||||
|
if (!stackInHand.isEmpty() && (stackInHand.getCount() != previousStackCount || client.player.isInCreativeMode())) {
|
||||||
|
client.gameRenderer.firstPersonRenderer.resetEquipProgress(client.player.preferredHand);
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result instanceof EntityHitResult entityHit) {
|
||||||
|
client.interactionManager.attackEntity(client.player, entityHit.getEntity());
|
||||||
|
client.player.swingHand(Hand.MAIN_HAND);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clickStartTime = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.touch;
|
||||||
|
|
||||||
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.TouchMode;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.Camera;
|
||||||
|
import net.minecraft.entity.projectile.ProjectileUtil;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.consume.UseAction;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
|
import net.minecraft.util.hit.HitResult;
|
||||||
|
import net.minecraft.util.math.Box;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.RaycastContext;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightReacharound.getPlayerRange;
|
||||||
|
|
||||||
|
public class TouchUtils {
|
||||||
|
private static final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
|
public static final Matrix4f lastWorldSpaceMatrix = new Matrix4f();
|
||||||
|
public static final Matrix4f lastProjMat = new Matrix4f();
|
||||||
|
public static final Matrix4f lastModMat = new Matrix4f();
|
||||||
|
|
||||||
|
public static HitResult getTargetedObject(double mouseX, double mouseY) {
|
||||||
|
if (client.player == null || client.world == null || MidnightControlsConfig.touchMode == TouchMode.CROSSHAIR || PlatformFunctions.isModLoaded("vulkanmod")) {
|
||||||
|
return client.crosshairTarget;
|
||||||
|
}
|
||||||
|
Vec3d near = screenSpaceToWorldSpace(mouseX, mouseY, 0);
|
||||||
|
Vec3d far = screenSpaceToWorldSpace(mouseX, mouseY, 1);
|
||||||
|
|
||||||
|
float playerRange = getPlayerRange(client);
|
||||||
|
EntityHitResult entityCast = ProjectileUtil.raycast(client.player, near, far, Box.from(client.player.getPos()).expand(playerRange), entity -> (!entity.isSpectator() && entity.isAttackable()), playerRange * playerRange);
|
||||||
|
|
||||||
|
if (entityCast != null && entityCast.getType() == HitResult.Type.ENTITY) return entityCast;
|
||||||
|
|
||||||
|
BlockHitResult result = client.world.raycast(new RaycastContext(near, far, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player));
|
||||||
|
|
||||||
|
if (client.player.getPos().distanceTo(result.getPos()) > playerRange) return null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Taken from https://github.com/0x3C50/Renderer/blob/master/src/main/java/me/x150/renderer/util/RendererUtils.java#L270
|
||||||
|
* Credits to 0x3C50 */
|
||||||
|
public static Vec3d screenSpaceToWorldSpace(double x, double y, double d) {
|
||||||
|
Camera camera = client.getEntityRenderDispatcher().camera;
|
||||||
|
int displayHeight = client.getWindow().getScaledHeight();
|
||||||
|
int displayWidth = client.getWindow().getScaledWidth();
|
||||||
|
int[] viewport = new int[4];
|
||||||
|
GL11.glGetIntegerv(GL11.GL_VIEWPORT, viewport);
|
||||||
|
Vector3f target = new Vector3f();
|
||||||
|
|
||||||
|
Matrix4f matrixProj = new Matrix4f(lastProjMat);
|
||||||
|
Matrix4f matrixModel = new Matrix4f(lastModMat);
|
||||||
|
|
||||||
|
matrixProj.mul(matrixModel)
|
||||||
|
.mul(lastWorldSpaceMatrix)
|
||||||
|
.unproject((float) x / displayWidth * viewport[2],
|
||||||
|
(float) (displayHeight - y) / displayHeight * viewport[3], (float) d, viewport, target);
|
||||||
|
|
||||||
|
return new Vec3d(target.x, target.y, target.z).add(camera.getPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasInWorldUseAction(ItemStack stack) {
|
||||||
|
UseAction action = stack.getUseAction();
|
||||||
|
return action == UseAction.BOW || action == UseAction.BRUSH || action == UseAction.SPEAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.touch.gui;
|
||||||
|
|
||||||
|
import net.minecraft.component.DataComponentTypes;
|
||||||
|
import net.minecraft.item.consume.UseAction;
|
||||||
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class ItemUseButtonWidget extends SpruceButtonWidget {
|
||||||
|
|
||||||
|
public ItemUseButtonWidget(Position position, int width, int height, Text message, PressAction action) {
|
||||||
|
super(position, width, height, message, action);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void onRelease(double mouseX, double mouseY) {
|
||||||
|
assert client.player != null;
|
||||||
|
assert client.interactionManager != null;
|
||||||
|
UseAction action = client.player.getMainHandStack().getUseAction();
|
||||||
|
if (action == UseAction.SPYGLASS || action == UseAction.TOOT_HORN) client.interactionManager.stopUsingItem(client.player);
|
||||||
|
super.onRelease(mouseX, mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(boolean visible) {
|
||||||
|
if (visible && client.player != null && client.player.getMainHandStack() != null) {
|
||||||
|
UseAction action = client.player.getMainHandStack().getUseAction();
|
||||||
|
if (action == UseAction.EAT) {
|
||||||
|
this.setMessage(Text.translatable(MidnightControlsConstants.NAMESPACE+".action.eat"));
|
||||||
|
} else if (action == UseAction.DRINK) {
|
||||||
|
this.setMessage(Text.translatable(MidnightControlsConstants.NAMESPACE+".action.drink"));
|
||||||
|
} else if (client.player.getMainHandStack().getComponents().contains(DataComponentTypes.EQUIPPABLE)) {
|
||||||
|
this.setMessage(Text.translatable(MidnightControlsConstants.NAMESPACE+".action.equip"));
|
||||||
|
} else if (!action.equals(UseAction.NONE)) {
|
||||||
|
this.setMessage(Text.translatable(MidnightControlsConstants.NAMESPACE+".action.use"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setAlpha(MidnightControlsConfig.touchTransparency / 100f);
|
||||||
|
super.setVisible(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
package eu.midnightdust.midnightcontrols.client.touch.gui;
|
||||||
|
|
||||||
import dev.lambdaurora.spruceui.Position;
|
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
||||||
import dev.lambdaurora.spruceui.widget.SpruceTexturedButtonWidget;
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.SpruceTexturedButtonWidget;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
@@ -23,4 +24,18 @@ public class SilentTexturedButtonWidget extends SpruceTexturedButtonWidget {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void playDownSound() {}
|
public void playDownSound() {}
|
||||||
|
@Override
|
||||||
|
protected void onRelease(double mouseX, double mouseY) {
|
||||||
|
this.setActive(false);
|
||||||
|
super.onClick(mouseX, mouseY);
|
||||||
|
super.onRelease(mouseX, mouseY);
|
||||||
|
this.setActive(true);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onClick(double mouseX, double mouseY) {
|
||||||
|
this.setActive(true);
|
||||||
|
super.onClick(mouseX, mouseY);
|
||||||
|
TouchInput.clickStartTime = -1;
|
||||||
|
this.setActive(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
* 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.touch.gui;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.ChatScreen;
|
||||||
|
import net.minecraft.client.gui.screen.GameMenuScreen;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.component.DataComponentTypes;
|
||||||
|
import net.minecraft.item.consume.UseAction;
|
||||||
|
import net.minecraft.util.Arm;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
|
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
||||||
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
|
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
||||||
|
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
||||||
|
import net.minecraft.client.option.KeyBinding;
|
||||||
|
import net.minecraft.client.texture.MissingSprite;
|
||||||
|
import net.minecraft.client.texture.Sprite;
|
||||||
|
import net.minecraft.client.util.InputUtil;
|
||||||
|
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Direction;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.input;
|
||||||
|
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 = id("textures/gui/widgets.png");
|
||||||
|
private SilentTexturedButtonWidget inventoryButton;
|
||||||
|
private SilentTexturedButtonWidget swapHandsButton;
|
||||||
|
private SilentTexturedButtonWidget dropButton;
|
||||||
|
private ItemUseButtonWidget useButton;
|
||||||
|
private SilentTexturedButtonWidget jumpButton;
|
||||||
|
private SilentTexturedButtonWidget flyButton;
|
||||||
|
private SilentTexturedButtonWidget flyUpButton;
|
||||||
|
private SilentTexturedButtonWidget flyDownButton;
|
||||||
|
private SilentTexturedButtonWidget forwardButton;
|
||||||
|
private SilentTexturedButtonWidget forwardLeftButton;
|
||||||
|
private SilentTexturedButtonWidget forwardRightButton;
|
||||||
|
private SilentTexturedButtonWidget leftButton;
|
||||||
|
private SilentTexturedButtonWidget rightButton;
|
||||||
|
private SilentTexturedButtonWidget backButton;
|
||||||
|
private SilentTexturedButtonWidget startSneakButton;
|
||||||
|
private SilentTexturedButtonWidget endSneakButton;
|
||||||
|
private int flyButtonEnableTicks = 0;
|
||||||
|
private int forwardButtonTick = 0;
|
||||||
|
|
||||||
|
public TouchscreenOverlay() {
|
||||||
|
super(Text.literal("Touchscreen Overlay"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPause() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {}
|
||||||
|
|
||||||
|
private void pauseGame() {
|
||||||
|
assert this.client != null;
|
||||||
|
this.client.setScreen(new GameMenuScreen(true));
|
||||||
|
if (this.client.isIntegratedServerRunning() && !Objects.requireNonNull(this.client.getServer()).isRemote()) {
|
||||||
|
this.client.getSoundManager().pauseAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the forward button ticks cooldown.
|
||||||
|
*
|
||||||
|
* @param state The button state.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void updateForwardButtonsState(boolean state) {
|
||||||
|
this.forwardButtonTick = state ? -1 : 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the jump buttons.
|
||||||
|
*/
|
||||||
|
private void updateJumpButtons() {
|
||||||
|
assert this.client != null;
|
||||||
|
assert this.client.player != null;
|
||||||
|
float transparency = MidnightControlsConfig.touchTransparency / 100f;
|
||||||
|
|
||||||
|
if (this.client.player.getAbilities().flying) {
|
||||||
|
boolean oldStateFly = this.flyButton.isVisible();
|
||||||
|
this.jumpButton.setVisible(false);
|
||||||
|
this.flyButton.setVisible(true);
|
||||||
|
this.flyUpButton.setVisible(true);
|
||||||
|
this.flyDownButton.setVisible(true);
|
||||||
|
this.flyButton.setAlpha(transparency);
|
||||||
|
this.flyUpButton.setAlpha(transparency);
|
||||||
|
this.flyDownButton.setAlpha(transparency);
|
||||||
|
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);
|
||||||
|
this.jumpButton.setAlpha(transparency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the jump button.
|
||||||
|
*
|
||||||
|
* @param btn The pressed button.
|
||||||
|
*/
|
||||||
|
private void handleJump(SpruceButtonWidget btn) {
|
||||||
|
assert this.client != null;
|
||||||
|
((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(btn.isActive());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Handles the jump button.
|
||||||
|
*
|
||||||
|
* @param state The state.
|
||||||
|
*/
|
||||||
|
private void setJump(boolean state) {
|
||||||
|
assert this.client != null;
|
||||||
|
((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
assert this.client != null;
|
||||||
|
assert this.client.player != null;
|
||||||
|
assert this.client.interactionManager != null;
|
||||||
|
int scaledWidth = this.client.getWindow().getScaledWidth();
|
||||||
|
int scaledHeight = this.client.getWindow().getScaledHeight();
|
||||||
|
int emoteOffset = 0;
|
||||||
|
if (PlatformFunctions.isModLoaded("emotecraft")) {
|
||||||
|
emoteOffset = 10;
|
||||||
|
TextIconButtonWidget emoteButton = TextIconButtonWidget.builder(Text.empty(), btn -> EmotecraftCompat.openEmotecraftScreen(this), true).width(20).texture(id("touch/emote"), 20, 20).build();
|
||||||
|
emoteButton.setPosition(scaledWidth / 2 - 30, 0);
|
||||||
|
this.addDrawableChild(emoteButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextIconButtonWidget chatButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.client.setScreen(new ChatScreen("")), true).width(20).texture(id("touch/chat"), 20, 20).build();
|
||||||
|
chatButton.setPosition(scaledWidth / 2 - 20 + emoteOffset, 0);
|
||||||
|
this.addDrawableChild(chatButton);
|
||||||
|
TextIconButtonWidget pauseButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.pauseGame(), true).width(20).texture(id("touch/pause"), 20, 20).build();
|
||||||
|
pauseButton.setPosition(scaledWidth / 2 + emoteOffset, 0);
|
||||||
|
this.addDrawableChild(pauseButton);
|
||||||
|
// Inventory buttons.
|
||||||
|
int inventoryButtonX = scaledWidth / 2;
|
||||||
|
int inventoryButtonY = scaledHeight - 16 - 5;
|
||||||
|
if (this.client.options.getMainArm().getValue() == Arm.LEFT) {
|
||||||
|
inventoryButtonX = inventoryButtonX - 91 - 24;
|
||||||
|
} else {
|
||||||
|
inventoryButtonX = inventoryButtonX + 91 + 4;
|
||||||
|
}
|
||||||
|
this.addDrawableChild(this.inventoryButton = new SilentTexturedButtonWidget(Position.of(inventoryButtonX, inventoryButtonY), 20, 20, Text.empty(), btn -> {
|
||||||
|
if (this.client.interactionManager.hasRidingInventory()) {
|
||||||
|
this.client.player.openRidingInventory();
|
||||||
|
} else {
|
||||||
|
this.client.getTutorialManager().onInventoryOpened();
|
||||||
|
this.client.setScreen(new InventoryScreen(this.client.player));
|
||||||
|
}
|
||||||
|
}, 20, 0, 20, WIDGETS_LOCATION, 256, 256));
|
||||||
|
;
|
||||||
|
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(this.swapHandsButton = new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY), 20, 20, Text.empty(),
|
||||||
|
button -> {
|
||||||
|
if (button.isActive()) {
|
||||||
|
if (!this.client.player.isSpectator()) {
|
||||||
|
Objects.requireNonNull(this.client.getNetworkHandler()).sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},0, 160, 20, WIDGETS_LOCATION));
|
||||||
|
// Drop
|
||||||
|
this.addDrawableChild(this.dropButton = new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY + 5 + 20), 20, 20, Text.empty(), btn -> {
|
||||||
|
if (btn.isActive() && !client.player.isSpectator() && client.player.dropSelectedItem(false)) {
|
||||||
|
client.player.swingHand(Hand.MAIN_HAND);
|
||||||
|
}
|
||||||
|
}, 20, 160, 20, WIDGETS_LOCATION));
|
||||||
|
// Use
|
||||||
|
this.addDrawableChild(this.useButton = new ItemUseButtonWidget(Position.of(width/2-25, height - 70), 50, 17, Text.translatable(MidnightControlsConstants.NAMESPACE+".action.eat"), btn ->
|
||||||
|
client.interactionManager.interactItem(client.player, client.player.getActiveHand())));
|
||||||
|
// Jump keys
|
||||||
|
this.addDrawableChild(this.jumpButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.empty(), this::handleJump, 0, 40, 20, WIDGETS_LOCATION));
|
||||||
|
this.addDrawableChild(this.flyButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.empty(),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.empty(),
|
||||||
|
this::handleJump, 40, 40, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.addDrawableChild(this.flyDownButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY + 20 + 5), 20, 20, Text.empty(),
|
||||||
|
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.empty(), 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.empty(), 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.addDrawableChild(this.forwardLeftButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20), 20, 20, Text.empty(), 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.addDrawableChild(this.forwardButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY - 5 - 20), 20, 20, Text.empty(), 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.empty(), 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.addDrawableChild(this.rightButton =new SilentTexturedButtonWidget(Position.of(sneakButtonX + 20 + 5, sneakButtonY), 20, 20, Text.empty(),
|
||||||
|
btn -> ((KeyBindingAccessor) this.client.options.rightKey).midnightcontrols$handlePressState(btn.isActive()), 20, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.addDrawableChild(this.backButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY + 20 + 5), 20, 20, Text.empty(),
|
||||||
|
btn -> ((KeyBindingAccessor) this.client.options.backKey).midnightcontrols$handlePressState(btn.isActive()), 40, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
this.addDrawableChild(this.leftButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX - 20 - 5, sneakButtonY), 20, 20, Text.empty(),
|
||||||
|
btn -> ((KeyBindingAccessor) this.client.options.leftKey).midnightcontrols$handlePressState(btn.isActive()), 60, 80, 20, WIDGETS_LOCATION
|
||||||
|
));
|
||||||
|
initCustomButtons(true);
|
||||||
|
initCustomButtons(false);
|
||||||
|
|
||||||
|
this.setButtonProperties(MidnightControlsConfig.touchTransparency / 100f);
|
||||||
|
}
|
||||||
|
private void initCustomButtons(boolean left) {
|
||||||
|
assert client != null;
|
||||||
|
Identifier emptySprite = id("touch/empty");
|
||||||
|
List<String> list = left ? MidnightControlsConfig.leftTouchBinds : MidnightControlsConfig.rightTouchBinds;
|
||||||
|
Sprite missingSprite = client.getGuiAtlasManager().getSprite(MissingSprite.getMissingSpriteId());
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
String bindName = list.get(i);
|
||||||
|
ButtonBinding binding = InputManager.getBinding(bindName);
|
||||||
|
if (binding == null) continue;
|
||||||
|
boolean hasTexture = client.getGuiAtlasManager().getSprite(id("binding/"+bindName)) != missingSprite;
|
||||||
|
if (MidnightControlsConfig.debug) System.out.println(left +" "+id("binding/"+bindName)+" "+ hasTexture);
|
||||||
|
var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> {
|
||||||
|
binding.handle(client, 1.0f, ButtonState.PRESS);
|
||||||
|
if (binding.asKeyBinding().isPresent()) {
|
||||||
|
binding.asKeyBinding().get().setPressed(true);
|
||||||
|
((KeyBindingAccessor)binding.asKeyBinding().get()).midnightcontrols$press();
|
||||||
|
}
|
||||||
|
}, hasTexture)
|
||||||
|
.texture(hasTexture ? id("binding/"+bindName) : emptySprite, 20, 20).dimension(20, 20).build();
|
||||||
|
button.setPosition(left ? (3+(i*23)) : this.width-(23+(i*23)), 3);
|
||||||
|
button.setAlpha(MidnightControlsConfig.touchTransparency / 100f);
|
||||||
|
this.addDrawableChild(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void setButtonProperties(float transparency) {
|
||||||
|
this.inventoryButton.setAlpha(transparency);
|
||||||
|
this.dropButton.setAlpha(transparency);
|
||||||
|
this.swapHandsButton.setAlpha(transparency);
|
||||||
|
this.jumpButton.setAlpha(transparency);
|
||||||
|
this.flyButton.setAlpha(transparency);
|
||||||
|
this.flyUpButton.setAlpha(transparency);
|
||||||
|
this.useButton.setAlpha(Math.min(transparency+0.1f, 1.0f));
|
||||||
|
this.flyDownButton.setAlpha(transparency);
|
||||||
|
this.startSneakButton.setAlpha(transparency);
|
||||||
|
this.endSneakButton.setAlpha(transparency);
|
||||||
|
this.forwardButton.setAlpha(transparency);
|
||||||
|
this.forwardLeftButton.setAlpha(Math.max(0.05f, transparency-0.1f));
|
||||||
|
this.forwardRightButton.setAlpha(Math.max(0.05f, transparency-0.1f));
|
||||||
|
this.leftButton.setAlpha(transparency);
|
||||||
|
this.rightButton.setAlpha(transparency);
|
||||||
|
this.backButton.setAlpha(transparency);
|
||||||
|
this.useButton.setAlpha(Math.min(transparency+0.1f, 1.0f));
|
||||||
|
this.endSneakButton.setVisible(false);
|
||||||
|
this.forwardLeftButton.setVisible(false);
|
||||||
|
this.forwardRightButton.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
assert this.client != null;
|
||||||
|
assert this.client.interactionManager != null;
|
||||||
|
assert this.client.player != null;
|
||||||
|
|
||||||
|
if (this.forwardButtonTick > 0) {
|
||||||
|
--this.forwardButtonTick;
|
||||||
|
} else {
|
||||||
|
this.forwardLeftButton.setVisible(false);
|
||||||
|
this.forwardRightButton.setVisible(false);
|
||||||
|
}
|
||||||
|
this.useButton.setVisible(client.player.getMainHandStack() != null && (client.player.getMainHandStack().getUseAction() != UseAction.NONE || client.player.getMainHandStack().getComponents().contains(DataComponentTypes.EQUIPPABLE)) && !TouchUtils.hasInWorldUseAction(client.player.getMainHandStack()));
|
||||||
|
this.updateJumpButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 (TouchInput.isDragging) {
|
||||||
|
if (!MidnightControlsConfig.invertTouch) {
|
||||||
|
deltaX = -deltaX;
|
||||||
|
deltaY = -deltaY;
|
||||||
|
}
|
||||||
|
input.handleTouchscreenLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) deltaY, 0.25d));
|
||||||
|
input.handleTouchscreenLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_X, (float) deltaX, 0.25d));
|
||||||
|
}
|
||||||
|
else TouchInput.isDragging = true;
|
||||||
|
}
|
||||||
|
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.util;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
|
||||||
|
public interface AbstractSignEditScreenAccessor {
|
||||||
|
@Unique
|
||||||
|
String[] midnightcontrols$getMessages();
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
void midnightcontrols$setMessage(int line, String text);
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
void midnightcontrols$writeToBlockEntity();
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.util;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import org.aperlambda.lambdacommon.utils.Pair;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.input;
|
||||||
|
|
||||||
|
public class InventoryUtil {
|
||||||
|
// Finds the closest slot in the GUI within 14 pixels.
|
||||||
|
public static Optional<Slot> findClosestSlot(HandledScreen<?> inventory, int direction) {
|
||||||
|
var accessor = (HandledScreenAccessor) inventory;
|
||||||
|
int guiLeft = accessor.getX();
|
||||||
|
int guiTop = accessor.getY();
|
||||||
|
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();
|
||||||
|
// Finds the hovered slot.
|
||||||
|
var mouseSlot = accessor.midnightcontrols$getSlotAt(mouseX, mouseY);
|
||||||
|
return inventory.getScreenHandler().slots.parallelStream()
|
||||||
|
.filter(Predicate.isEqual(mouseSlot).negate())
|
||||||
|
.map(slot -> {
|
||||||
|
int posX = guiLeft + slot.x + 8;
|
||||||
|
int posY = guiTop + slot.y + 8;
|
||||||
|
|
||||||
|
int otherPosX = (int) mouseX;
|
||||||
|
int otherPosY = (int) mouseY;
|
||||||
|
if (mouseSlot != null) {
|
||||||
|
otherPosX = guiLeft + mouseSlot.x + 8;
|
||||||
|
otherPosY = guiTop + mouseSlot.y + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distance between the slot and the cursor.
|
||||||
|
double distance = Math.sqrt(Math.pow(posX - otherPosX, 2) + Math.pow(posY - otherPosY, 2));
|
||||||
|
return Pair.of(slot, distance);
|
||||||
|
}).filter(entry -> {
|
||||||
|
var slot = entry.key;
|
||||||
|
int posX = guiLeft + slot.x + 8;
|
||||||
|
int posY = guiTop + slot.y + 8;
|
||||||
|
int otherPosX = (int) mouseX;
|
||||||
|
int otherPosY = (int) mouseY;
|
||||||
|
if (mouseSlot != null) {
|
||||||
|
otherPosX = guiLeft + mouseSlot.x + 8;
|
||||||
|
otherPosY = guiTop + mouseSlot.y + 8;
|
||||||
|
}
|
||||||
|
if (direction == 0)
|
||||||
|
return posY < otherPosY;
|
||||||
|
else if (direction == 1)
|
||||||
|
return posY > otherPosY;
|
||||||
|
else if (direction == 2)
|
||||||
|
return posX > otherPosX;
|
||||||
|
else if (direction == 3)
|
||||||
|
return posX < otherPosX;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.min(Comparator.comparingDouble(p -> p.value))
|
||||||
|
.map(p -> p.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int targetMouseX = 0;
|
||||||
|
private static int targetMouseY = 0;
|
||||||
|
|
||||||
|
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
|
||||||
|
public static void moveMouseToClosestSlot(@Nullable Screen screen) {
|
||||||
|
// Makes the mouse attracted to slots. This helps with selecting items when using a controller.
|
||||||
|
if (screen instanceof HandledScreen<?> inventoryScreen) {
|
||||||
|
var accessor = (HandledScreenAccessor) inventoryScreen;
|
||||||
|
int guiLeft = accessor.getX();
|
||||||
|
int guiTop = accessor.getY();
|
||||||
|
int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
||||||
|
int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
|
||||||
|
|
||||||
|
// Finds the closest slot in the GUI within 14 pixels.
|
||||||
|
Optional<net.minecraft.util.Pair<Slot, Double>> closestSlot = inventoryScreen.getScreenHandler().slots.parallelStream()
|
||||||
|
.map(slot -> {
|
||||||
|
int x = guiLeft + slot.x + 8;
|
||||||
|
int y = guiTop + slot.y + 8;
|
||||||
|
|
||||||
|
// Distance between the slot and the cursor.
|
||||||
|
double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2));
|
||||||
|
return new net.minecraft.util.Pair<>(slot, distance);
|
||||||
|
}).filter(entry -> entry.getRight() <= 14.0)
|
||||||
|
.min(Comparator.comparingDouble(net.minecraft.util.Pair::getRight));
|
||||||
|
|
||||||
|
if (closestSlot.isPresent() && client.player != null) {
|
||||||
|
var slot = closestSlot.get().getLeft();
|
||||||
|
if (slot.hasStack() || !client.player.getInventory().getSelectedStack().isEmpty()) {
|
||||||
|
int slotCenterXScaled = guiLeft + slot.x + 8;
|
||||||
|
int slotCenterYScaled = guiTop + slot.y + 8;
|
||||||
|
int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
|
||||||
|
int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()));
|
||||||
|
double deltaX = slotCenterX - targetMouseX;
|
||||||
|
double deltaY = slotCenterY - targetMouseY;
|
||||||
|
|
||||||
|
if (mouseX != slotCenterXScaled || mouseY != slotCenterYScaled) {
|
||||||
|
targetMouseX += (int) (deltaX * 0.75);
|
||||||
|
targetMouseY += (int) (deltaY * 0.75);
|
||||||
|
} else {
|
||||||
|
input.mouseSpeedX *= 0.3F;
|
||||||
|
input.mouseSpeedY *= 0.3F;
|
||||||
|
}
|
||||||
|
input.mouseSpeedX *= .75F;
|
||||||
|
input.mouseSpeedY *= .75F;
|
||||||
|
} else {
|
||||||
|
input.mouseSpeedX *= .1F;
|
||||||
|
input.mouseSpeedY *= .1F;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
input.mouseSpeedX *= .3F;
|
||||||
|
input.mouseSpeedY *= .3F;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
input.mouseSpeedX = 0.F;
|
||||||
|
input.mouseSpeedY = 0.F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
public class MathUtil {
|
||||||
|
public static class PolarUtil {
|
||||||
|
public float polarX;
|
||||||
|
public float polarY;
|
||||||
|
public PolarUtil() {}
|
||||||
|
|
||||||
|
public void calculate(float x, float y, float speedFactor) {
|
||||||
|
calculate(x, y, speedFactor, 0);
|
||||||
|
}
|
||||||
|
public void calculate(float x, float y, float speedFactor, double deadZone) {
|
||||||
|
double inputR = Math.pow(x, 2) + Math.pow(y, 2);
|
||||||
|
inputR = (Math.abs(speedFactor * MathHelper.clamp(inputR,0.f,1.f)));
|
||||||
|
inputR = inputR < deadZone ? 0f : (inputR-deadZone) / (1f-deadZone);
|
||||||
|
double inputTheta = Math.atan2(y, x);
|
||||||
|
polarX = (float) (inputR *Math.cos(inputTheta));
|
||||||
|
polarY = (float) (inputR *Math.sin(inputTheta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.util;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class RainbowColor {
|
||||||
|
public static float hue;
|
||||||
|
public static void tick() {
|
||||||
|
if (hue > 1) hue = 0f;
|
||||||
|
hue = hue + 0.01f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color radialRainbow(float saturation, float brightness) {
|
||||||
|
return Color.getHSBColor(hue, saturation, brightness);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.util;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
|
||||||
|
public class ToggleSneakSprintUtil {
|
||||||
|
public static boolean toggleSneak(ButtonBinding button) {
|
||||||
|
if (client.player == null) return false;
|
||||||
|
boolean isFlying = client.player.getAbilities().flying;
|
||||||
|
var option = client.options.getSneakToggled();
|
||||||
|
|
||||||
|
button.asKeyBinding().ifPresent(binding -> {
|
||||||
|
boolean sneakToggled = option.getValue();
|
||||||
|
if (isFlying && sneakToggled)
|
||||||
|
option.setValue(false);
|
||||||
|
else if (MidnightControlsConfig.controllerToggleSneak != sneakToggled)
|
||||||
|
option.setValue(!sneakToggled);
|
||||||
|
binding.setPressed(button.isPressed());
|
||||||
|
if (isFlying && sneakToggled)
|
||||||
|
option.setValue(true);
|
||||||
|
else if (MidnightControlsConfig.controllerToggleSneak != sneakToggled)
|
||||||
|
option.setValue(sneakToggled);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public static boolean toggleSprint(ButtonBinding button) {
|
||||||
|
if (client.player == null) return false;
|
||||||
|
boolean isFlying = client.player.getAbilities().flying;
|
||||||
|
var option = client.options.getSprintToggled();
|
||||||
|
|
||||||
|
button.asKeyBinding().ifPresent(binding -> {
|
||||||
|
boolean sprintToggled = option.getValue();
|
||||||
|
if (isFlying && sprintToggled)
|
||||||
|
option.setValue(false);
|
||||||
|
else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
|
||||||
|
option.setValue(!sprintToggled);
|
||||||
|
binding.setPressed(button.isPressed());
|
||||||
|
if (client.player.getAbilities().flying && sprintToggled)
|
||||||
|
option.setValue(true);
|
||||||
|
else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
|
||||||
|
option.setValue(sprintToggled);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.util.platform;
|
||||||
|
|
||||||
|
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
|
import net.minecraft.client.gui.widget.PressableWidget;
|
||||||
|
import net.minecraft.item.ItemGroup;
|
||||||
|
import net.minecraft.item.ItemGroups;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ItemGroupUtil {
|
||||||
|
@ExpectPlatform
|
||||||
|
public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean cyclePage(boolean next, CreativeInventoryScreen screen) {
|
||||||
|
try {
|
||||||
|
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||||
|
.map(element -> (PressableWidget) element)
|
||||||
|
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
|
||||||
|
.anyMatch(element -> {
|
||||||
|
if (next && element.getMessage().getString().equals(">")) {
|
||||||
|
element.onPress();
|
||||||
|
return true;
|
||||||
|
} else if (element.getMessage().getString().equals("<")) {
|
||||||
|
element.onPress();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull ItemGroup cycleTab(boolean next, MinecraftClient client) {
|
||||||
|
ItemGroup currentTab = CreativeInventoryScreenAccessor.getSelectedTab();
|
||||||
|
int currentColumn = currentTab.getColumn();
|
||||||
|
ItemGroup.Row currentRow = currentTab.getRow();
|
||||||
|
ItemGroup newTab = null;
|
||||||
|
List<ItemGroup> visibleTabs = ItemGroupUtil.getVisibleGroups((CreativeInventoryScreen) client.currentScreen);
|
||||||
|
for (ItemGroup tab : visibleTabs) {
|
||||||
|
if (tab.getRow().equals(currentRow) && ((newTab == null && ((next && tab.getColumn() > currentColumn) ||
|
||||||
|
(!next && tab.getColumn() < currentColumn))) || (newTab != null && ((next && tab.getColumn() > currentColumn && tab.getColumn() < newTab.getColumn()) ||
|
||||||
|
(!next && tab.getColumn() < currentColumn && tab.getColumn() > newTab.getColumn())))))
|
||||||
|
newTab = tab;
|
||||||
|
}
|
||||||
|
if (newTab == null)
|
||||||
|
for (ItemGroup tab : visibleTabs) {
|
||||||
|
if ((tab.getRow().compareTo(currentRow)) != 0 && ((next && newTab == null || next && newTab.getColumn() > tab.getColumn()) || (!next && newTab == null) || (!next && newTab.getColumn() < tab.getColumn())))
|
||||||
|
newTab = tab;
|
||||||
|
}
|
||||||
|
if (newTab == null) {
|
||||||
|
for (ItemGroup tab : visibleTabs) {
|
||||||
|
if ((next && tab.getRow() == ItemGroup.Row.TOP && tab.getColumn() == 0) ||
|
||||||
|
!next && tab.getRow() == ItemGroup.Row.BOTTOM && (newTab == null || tab.getColumn() > newTab.getColumn()))
|
||||||
|
newTab = tab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newTab == null || newTab.equals(currentTab)) newTab = ItemGroups.getDefaultTab();
|
||||||
|
return newTab;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.util.platform;
|
||||||
|
|
||||||
|
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||||
|
import net.minecraft.network.packet.CustomPayload;
|
||||||
|
import net.minecraft.network.packet.Packet;
|
||||||
|
|
||||||
|
public class NetworkUtil {
|
||||||
|
@ExpectPlatform
|
||||||
|
public static void sendPacketC2S(Packet<?> packet) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
@ExpectPlatform
|
||||||
|
public static void sendPayloadC2S(CustomPayload payload) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user