Compare commits
162 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
9cc5393703 | ||
|
|
8d08fdedf4 | ||
|
|
cdafde01f3 | ||
|
|
c07c4200f7 | ||
|
|
c70da21df6 | ||
|
|
f5d5d93c19 | ||
|
|
429b4ca607 | ||
|
|
dd173836ff | ||
|
|
203fd6cdb6 | ||
|
|
003f79d405 | ||
|
|
f48527402a | ||
|
|
8c4b705e65 | ||
|
|
1def693ae8 | ||
|
|
cfd05bb7b6 | ||
|
|
2e861470d8 | ||
|
|
e87ed53485 | ||
|
|
8847c7f499 | ||
|
|
da2773b1e9 | ||
|
|
3650e756c3 | ||
|
|
6b885beede | ||
|
|
abb3d1de3c | ||
|
|
a8cdfeeba9 | ||
|
|
ed4d310565 | ||
|
|
ac73c99506 | ||
|
|
d45eeac6dc | ||
|
|
77ff589544 | ||
|
|
ce5c0b22db | ||
|
|
98af13fd0b | ||
|
|
2387444d3a | ||
|
|
57860490c8 | ||
|
|
f46aa175a4 | ||
|
|
78390ca02f | ||
|
|
31821b4833 | ||
|
|
e34ba6025a | ||
|
|
9891cd2977 | ||
|
|
8566e859e3 | ||
|
|
735b9e8718 | ||
|
|
71ee3d8e0a | ||
|
|
11f102759c | ||
|
|
02dd543027 | ||
|
|
c247e51d00 | ||
|
|
e3052343d3 | ||
|
|
9e879f9230 | ||
|
|
bda436d863 | ||
|
|
98d2cdae63 | ||
|
|
8e0e444d15 | ||
|
|
f586647e07 | ||
|
|
73ab8456e7 | ||
|
|
1a3d7ce225 | ||
|
|
965ab57159 | ||
|
|
c8dba43b90 | ||
|
|
dd8e62c73e | ||
|
|
b24a158b9b | ||
|
|
df7c7bbdad | ||
|
|
3ddae57eab | ||
|
|
a0701f55f6 | ||
|
|
b15766dfdb | ||
|
|
19ed068da9 | ||
|
|
d2e21f8723 | ||
|
|
b3f7350de9 | ||
|
|
34408d7a2a | ||
|
|
6e64c7c97d | ||
|
|
bca73c93cc | ||
|
|
913e79fe5b | ||
|
|
b1334a0455 | ||
|
|
ce9495c79c | ||
|
|
ff8270d18a | ||
|
|
3f33549760 | ||
|
|
d034607032 | ||
|
|
e9a11c0ab9 | ||
|
|
e0d90fc56a | ||
|
|
cac23d12a1 | ||
|
|
b982772d31 | ||
|
|
e4ca0db2a2 | ||
|
|
f0cd2a51d1 | ||
|
|
9d37862144 | ||
|
|
c31fb76215 | ||
|
|
b6563af2b1 | ||
|
|
1a0030a680 | ||
|
|
78c858b753 |
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
title: 'Bug: TITLE HERE'
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
@@ -21,15 +21,17 @@ Steps to reproduce the behavior:
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**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):**
|
||||
- OS: [e.g. Linux]
|
||||
- Minecraft [e.g. 1.14.4]
|
||||
- Fabric [e.g. fabric 0.7.2+build.174]
|
||||
- Mods [e.g. aurora_keystrokes v1.0.0, modmenu v1.7.15]
|
||||
- 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]
|
||||
- Branch [e.g. dev]
|
||||
- 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.
|
||||
|
||||
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
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
title: 'Feature: TITLE HERE'
|
||||
labels: enhancement
|
||||
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.
|
||||
|
||||
**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
@@ -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.
|
||||
63
README.md
@@ -1,29 +1,29 @@
|
||||
<div align="center">
|
||||
<img src=https://github.com/TeamMidnightDust/MidnightControls/blob/1.19/src/main/resources/assets/midnightcontrols/icon.png>
|
||||
|
||||
# MidnightControls
|
||||
|
||||
<!-- modrinth_exclude.start -->
|
||||
 <!-- modrinth_exclude.end -->
|
||||
[](https://raw.githubusercontent.com/TeamMidnightDust/MidnightControls/master/LICENSE)
|
||||

|
||||
[![Mod loader: Quilt/Fabric]][quilt] <!-- modrinth_exclude.start -->
|
||||

|
||||
[](https://www.curseforge.com/minecraft/mc-mods/midnightcontrols)
|
||||
<!-- modrinth_exclude.end -->
|
||||
[](https://www.curseforge.com/minecraft/mc-mods/midnightcontrols)
|
||||
[![Modrinth]](https://modrinth.com/mod/midnightcontrols)
|
||||
[](https://github.com/TeamMidnightDust/MidnightControls/releases)
|
||||

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

|
||||

|
||||

|
||||

|
||||
|
||||
<!-- modrinth_exclude.start -->
|
||||
## Build
|
||||
|
||||
Just do `./gradlew build` and everything should build just fine!
|
||||
<!-- modrinth_exclude.end -->
|
||||
Clone the repo with:
|
||||
```
|
||||
git clone https://github.com/TeamMidnightDust/MidnightControls
|
||||
```
|
||||
Enter the folder created and run:
|
||||
```
|
||||
./gradlew build
|
||||
```
|
||||
After this is done, everything should be built just fine!
|
||||
|
||||
## 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==
|
||||
|
||||
[Modrinth]: https://img.shields.io/modrinth/dt/bXX9h73M?logoColor=white&logo=data:image/svg%2bxml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNTEyIDUxNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTUwMy4xNiAzMjMuNTZDNTE0LjU1IDI4MS40NyA1MTUuMzIgMjM1LjkxIDUwMy4yIDE5MC43NkM0NjYuNTcgNTQuMjI5OSAzMjYuMDQgLTI2LjgwMDEgMTg5LjMzIDkuNzc5OTFDODMuODEwMSAzOC4wMTk5IDExLjM4OTkgMTI4LjA3IDAuNjg5OTQxIDIzMC40N0g0My45OUM1NC4yOSAxNDcuMzMgMTEzLjc0IDc0LjcyOTggMTk5Ljc1IDUxLjcwOThDMzA2LjA1IDIzLjI1OTggNDE1LjEzIDgwLjY2OTkgNDUzLjE3IDE4MS4zOEw0MTEuMDMgMTkyLjY1QzM5MS42NCAxNDUuOCAzNTIuNTcgMTExLjQ1IDMwNi4zIDk2LjgxOThMMjk4LjU2IDE0MC42NkMzMzUuMDkgMTU0LjEzIDM2NC43MiAxODQuNSAzNzUuNTYgMjI0LjkxQzM5MS4zNiAyODMuOCAzNjEuOTQgMzQ0LjE0IDMwOC41NiAzNjkuMTdMMzIwLjA5IDQxMi4xNkMzOTAuMjUgMzgzLjIxIDQzMi40IDMxMC4zIDQyMi40MyAyMzUuMTRMNDY0LjQxIDIyMy45MUM0NjguOTEgMjUyLjYyIDQ2Ny4zNSAyODEuMTYgNDYwLjU1IDMwOC4wN0w1MDMuMTYgMzIzLjU2WiIgZmlsbD0iIzMwYjI3YiIvPgogIDxwYXRoIGQ9Ik0zMjEuOTkgNTA0LjIyQzE4NS4yNyA1NDAuOCA0NC43NTAxIDQ1OS43NyA4LjExMDExIDMyMy4yNEMzLjg0MDExIDMwNy4zMSAxLjE3IDI5MS4zMyAwIDI3NS40Nkg0My4yN0M0NC4zNiAyODcuMzcgNDYuNDY5OSAyOTkuMzUgNDkuNjc5OSAzMTEuMjlDNTMuMDM5OSAzMjMuOCA1Ny40NSAzMzUuNzUgNjIuNzkgMzQ3LjA3TDEwMS4zOCAzMjMuOTJDOTguMTI5OSAzMTYuNDIgOTUuMzkgMzA4LjYgOTMuMjEgMzAwLjQ3QzY5LjE3IDIxMC44NyAxMjIuNDEgMTE4Ljc3IDIxMi4xMyA5NC43NjAxQzIyOS4xMyA5MC4yMTAxIDI0Ni4yMyA4OC40NDAxIDI2Mi45MyA4OS4xNTAxTDI1NS4xOSAxMzNDMjQ0LjczIDEzMy4wNSAyMzQuMTEgMTM0LjQyIDIyMy41MyAxMzcuMjVDMTU3LjMxIDE1NC45OCAxMTguMDEgMjIyLjk1IDEzNS43NSAyODkuMDlDMTM2Ljg1IDI5My4xNiAxMzguMTMgMjk3LjEzIDEzOS41OSAzMDAuOTlMMTg4Ljk0IDI3MS4zOEwxNzQuMDcgMjMxLjk1TDIyMC42NyAxODQuMDhMMjc5LjU3IDE3MS4zOUwyOTYuNjIgMTkyLjM4TDI2OS40NyAyMTkuODhMMjQ1Ljc5IDIyNy4zM0wyMjguODcgMjQ0LjcyTDIzNy4xNiAyNjcuNzlDMjM3LjE2IDI2Ny43OSAyNTMuOTUgMjg1LjYzIDI1My45OCAyODUuNjRMMjc3LjcgMjc5LjMzTDI5NC41OCAyNjAuNzlMMzMxLjQ0IDI0OS4xMkwzNDIuNDIgMjczLjgyTDMwNC4zOSAzMjAuNDVMMjQwLjY2IDM0MC42M0wyMTIuMDggMzA4LjgxTDE2Mi4yNiAzMzguN0MxODcuOCAzNjcuNzggMjI2LjIgMzgzLjkzIDI2Ni4wMSAzODAuNTZMMjc3LjU0IDQyMy41NUMyMTguMTMgNDMxLjQxIDE2MC4xIDQwNi44MiAxMjQuMDUgMzYxLjY0TDg1LjYzOTkgMzg0LjY4QzEzNi4yNSA0NTEuMTcgMjIzLjg0IDQ4NC4xMSAzMDkuNjEgNDYxLjE2QzM3MS4zNSA0NDQuNjQgNDE5LjQgNDAyLjU2IDQ0NS40MiAzNDkuMzhMNDg4LjA2IDM2NC44OEM0NTcuMTcgNDMxLjE2IDM5OC4yMiA0ODMuODIgMzIxLjk5IDUwNC4yMloiIGZpbGw9IiMzMGIyN2IiLz4KPC9zdmc+
|
||||
|
||||
223
build.gradle
@@ -1,64 +1,22 @@
|
||||
plugins {
|
||||
id 'fabric-loom' version '0.11-SNAPSHOT'
|
||||
id 'fabric-loom' version '1.6-SNAPSHOT'
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
||||
id 'com.modrinth.minotaur' version '1.2.+'
|
||||
id "me.shedaniel.unified-publishing" version "0.1.+"
|
||||
}
|
||||
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonObject
|
||||
import com.modrinth.minotaur.TaskModrinthUpload
|
||||
import com.modrinth.minotaur.request.VersionType
|
||||
import com.modrinth.minotaur.responses.ResponseError
|
||||
import org.apache.http.client.config.CookieSpecs
|
||||
import org.apache.http.client.config.RequestConfig
|
||||
import org.apache.http.client.entity.EntityBuilder
|
||||
import org.apache.http.client.methods.HttpPatch
|
||||
import org.apache.http.entity.ContentType
|
||||
import org.apache.http.impl.client.HttpClientBuilder
|
||||
import org.apache.http.util.EntityUtils
|
||||
|
||||
group = project.maven_group
|
||||
version = "${project.mod_version}+${getMCVersionString()}"
|
||||
archivesBaseName = project.archives_base_name
|
||||
version = "${project.mod_version}+${project.minecraft_version}"
|
||||
|
||||
// This field defines the Java version your mod target.
|
||||
def targetJavaVersion = 17
|
||||
def targetJavaVersion = 21
|
||||
|
||||
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 {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
@@ -68,11 +26,12 @@ repositories {
|
||||
url 'https://maven.gegy.dev'
|
||||
}
|
||||
maven {
|
||||
name 'CottonMC'
|
||||
url 'https://server.bbkr.space/artifactory/libs-snapshot'
|
||||
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" }
|
||||
@@ -93,29 +52,43 @@ dependencies {
|
||||
// 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}"
|
||||
include modImplementation ("maven.modrinth:obsidianui:${project.obsidianui_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}"
|
||||
modCompileOnlyApi ("com.terraformersmc:modmenu:${project.modmenu_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
|
||||
// Compatibility mods
|
||||
modImplementation("maven.modrinth:ok-zoomer:${project.ok_zoomer_version}")
|
||||
modImplementation "io.github.ennuil:LibZoomer:${project.libzoomer_version}"
|
||||
modImplementation "org.quiltmc:quilt-json5:1.0.0"
|
||||
modImplementation("me.shedaniel:RoughlyEnoughItems-runtime-fabric:${project.rei_version}")
|
||||
modImplementation "maven.modrinth:emotecraft:${project.emotecraft_version}"
|
||||
modImplementation "io.github.kosmx:bendy-lib:${project.bendylib_version}"
|
||||
|
||||
// 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}"
|
||||
|
||||
modCompileOnlyApi "io.github.cottonmc:LibGui:${project.libgui_version}"
|
||||
modCompileOnlyApi "org.quiltmc:quilt-json5:1.0.0"
|
||||
modCompileOnly "maven.modrinth:sodium:${project.sodium_version}"
|
||||
modCompileOnlyApi "maven.modrinth:emi:${project.emi_version}"
|
||||
modCompileOnlyApi "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")
|
||||
}
|
||||
|
||||
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")
|
||||
@@ -142,113 +115,53 @@ processResources {
|
||||
}
|
||||
}
|
||||
|
||||
task publishModrinth(type: TaskModrinthUpload) {
|
||||
dependsOn(build)
|
||||
onlyIf {
|
||||
System.getenv('MODRINTH_TOKEN')
|
||||
}
|
||||
|
||||
token = System.getenv('MODRINTH_TOKEN')
|
||||
projectId = project.modrinth_id
|
||||
versionNumber = version
|
||||
versionName = "midnightcontrols ${project.mod_version} (${getMCVersionString()})"
|
||||
addGameVersion((String) project.minecraft_version)
|
||||
addLoader('fabric')
|
||||
versionType = isMCVersionNonRelease() ? VersionType.BETA : VersionType.RELEASE
|
||||
|
||||
// Changelog fetching
|
||||
def changelogText = file('CHANGELOG.md').text
|
||||
def regexVersion = ((String) project.mod_version).replaceAll('\\.', /\\./).replaceAll('\\+', '\\+')
|
||||
def changelogRegex = ~"###? ${regexVersion}\\n\\n(( *- .+\\n)+)"
|
||||
def matcher = changelogText =~ changelogRegex
|
||||
|
||||
if (matcher.find()) {
|
||||
changelog = matcher.group(1)
|
||||
|
||||
def changelogLines = changelogText.split('\n')
|
||||
def linkRefRegex = ~'^\\[([A-z0-9 _\\-/+.]+)]: '
|
||||
for (int i = changelogLines.length - 1; i > 0; i--) {
|
||||
def line = changelogLines[i]
|
||||
if ((line =~ linkRefRegex).find())
|
||||
changelog += '\n' + line
|
||||
else break
|
||||
}
|
||||
}
|
||||
|
||||
// Readme
|
||||
doFirst {
|
||||
final def client = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
|
||||
final def patch = new HttpPatch((String) (apiURL + '/v1/mod/' + projectId))
|
||||
patch.addHeader("Authorization", token)
|
||||
|
||||
var json = new JsonObject()
|
||||
json.addProperty("body", parseReadme())
|
||||
patch.setEntity(EntityBuilder.create()
|
||||
.setText(json.toString())
|
||||
.setContentType(ContentType.APPLICATION_JSON)
|
||||
.build())
|
||||
|
||||
final def response = client.execute(patch)
|
||||
final int status = response.getStatusLine().getStatusCode()
|
||||
|
||||
final def gson = new GsonBuilder().create()
|
||||
if (status == 200) {
|
||||
project.getLogger().lifecycle("Successfully updated readme to ${projectId}.")
|
||||
} else {
|
||||
errorInfo = gson.fromJson(EntityUtils.toString(response.getEntity()), ResponseError.class)
|
||||
project.getLogger().error("Upload failed! Status: ${status} Error: ${errorInfo.getError()} Reason: ${errorInfo.getDescription()}")
|
||||
throw new GradleException("Upload failed! Status: ${status} Reason: ${errorInfo.getDescription()}")
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
// configure the maven publication
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifact(sourcesJar) {
|
||||
builtBy remapSourcesJar
|
||||
}
|
||||
|
||||
pom {
|
||||
name = 'midnightcontrols'
|
||||
description = 'Adds better controls, and controller support.'
|
||||
}
|
||||
|
||||
pom.withXml {
|
||||
def dependenciesNode = asNode().appendNode('dependencies')
|
||||
|
||||
configurations.shadow.allDependencies.each {
|
||||
def dependencyNode = dependenciesNode.appendNode('dependency')
|
||||
|
||||
dependencyNode.appendNode('groupId', it.group)
|
||||
dependencyNode.appendNode('artifactId', it.name)
|
||||
dependencyNode.appendNode('version', it.version)
|
||||
dependencyNode.appendNode('scope', 'compile')
|
||||
}
|
||||
unifiedPublishing {
|
||||
project {
|
||||
displayName = "MidnightControls v$project.version - Fabric $project.minecraft_version"
|
||||
releaseType = "$project.release_type"
|
||||
changelog = releaseChangelog()
|
||||
gameVersions = []
|
||||
gameLoaders = ["fabric","quilt"]
|
||||
mainPublication remapJar
|
||||
relations {
|
||||
includes {
|
||||
curseforge = "midnightlib"
|
||||
modrinth = "midnightlib"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven {
|
||||
name 'GithubPackages'
|
||||
url uri('https://maven.pkg.github.com/LambdAurora/midnightcontrols')
|
||||
credentials {
|
||||
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
|
||||
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
|
||||
var CURSEFORGE_TOKEN = project.findProperty("CURSEFORGE_TOKEN") ?: System.getenv("CURSEFORGE_TOKEN")
|
||||
if (CURSEFORGE_TOKEN != null) {
|
||||
curseforge {
|
||||
token = CURSEFORGE_TOKEN
|
||||
id = rootProject.curseforge_id
|
||||
gameVersions.addAll "Java 21", project.minecraft_version
|
||||
}
|
||||
}
|
||||
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')
|
||||
}
|
||||
|
||||
var MODRINTH_TOKEN = project.findProperty("MODRINTH_TOKEN") ?: System.getenv("MODRINTH_TOKEN")
|
||||
if (MODRINTH_TOKEN != null) {
|
||||
modrinth {
|
||||
token = MODRINTH_TOKEN
|
||||
id = rootProject.modrinth_id
|
||||
version = "$project.version"
|
||||
gameVersions.addAll project.minecraft_version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
269
controller_banner.svg
Normal file
@@ -0,0 +1,269 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="1920"
|
||||
height="1080"
|
||||
viewBox="0 0 1920 1080"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
sodipodi:docname="controller_banner.svg"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||
inkscape:export-filename="/home/martin/Bilder/Bilder/MidnightControlsBanner.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview893"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="px"
|
||||
showgrid="true"
|
||||
inkscape:zoom="0.40120419"
|
||||
inkscape:cx="928.45492"
|
||||
inkscape:cy="816.29258"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1050"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid956" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs888">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2059">
|
||||
<stop
|
||||
style="stop-color:#ed02a0;stop-opacity:0.72909278"
|
||||
offset="0"
|
||||
id="stop2055" />
|
||||
<stop
|
||||
style="stop-color:#8900cb;stop-opacity:0.73234183"
|
||||
offset="1"
|
||||
id="stop2057" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect904"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Füllregel Gerade-Ungerade im <b>Füllung und Kontur</b>-Dialog verwenden, wenn das Anwenden des Ausschnitts mit nachfolgendem Umwandeln in Pfade kein Ergebnis bringt" />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect900"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Füllregel Gerade-Ungerade im <b>Füllung und Kontur</b>-Dialog verwenden, wenn das Anwenden des Ausschnitts mit nachfolgendem Umwandeln in Pfade kein Ergebnis bringt" />
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
id="path-effect896"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false"
|
||||
message="Füllregel Gerade-Ungerade im <b>Füllung und Kontur</b>-Dialog verwenden, wenn das Anwenden des Ausschnitts mit nachfolgendem Umwandeln in Pfade kein Ergebnis bringt" />
|
||||
<rect
|
||||
x="500"
|
||||
y="800"
|
||||
width="840"
|
||||
height="220"
|
||||
id="rect7833" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient1152">
|
||||
<stop
|
||||
style="stop-color:#ed02a0;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1148" />
|
||||
<stop
|
||||
style="stop-color:#8900cb;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1150" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2059"
|
||||
id="linearGradient1154"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1920"
|
||||
y2="1080"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1152"
|
||||
id="linearGradient4289"
|
||||
x1="-398"
|
||||
y1="56"
|
||||
x2="1522"
|
||||
y2="1136"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(398,-56)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1152"
|
||||
id="linearGradient7579"
|
||||
x1="-398"
|
||||
y1="56"
|
||||
x2="1522"
|
||||
y2="1136"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(398,-56)" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath878">
|
||||
<path
|
||||
id="path880"
|
||||
style="display:none;fill:url(#linearGradient882);stroke-width:1.00028"
|
||||
d="m 1170.0221,-4.111892 a 21.817197,20.751893 3.393352 0 0 -8.3753,3.68511674 21.817197,20.751893 3.393352 0 0 -4.1775,28.99380526 l 0.2304,0.284584 a 21.817197,20.751893 3.393352 0 0 30.5488,3.770316 21.817197,20.751893 3.393352 0 0 3.9128,-29.0289691 21.817197,20.751893 3.393352 0 0 -22.1392,-7.7048529 z M 858.04762,85.714292 c -7.15183,1.731644 -11.32417,8.932859 -9.35312,16.146398 l 22.2005,81.24794 c 1.97106,7.21354 9.31675,11.62594 16.46858,9.8943 L 1086.714,144.73497 c 7.1518,-1.73163 11.3223,-8.9324 9.3512,-16.14595 l -22.2005,-81.247936 c -1.971,-7.213536 -9.3149,-11.626381 -16.4667,-9.894748 z M 756.02165,124.73884 a 50.906793,48.421082 3.3933293 0 0 -19.54511,8.59585 50.906793,48.421082 3.3933293 0 0 -9.74699,67.65414 l 0.53564,0.66651 a 50.906793,48.421082 3.3933293 0 0 71.28286,8.79621 50.906793,48.421082 3.3933293 0 0 9.13065,-67.73384 50.906793,48.421082 3.3933293 0 0 -51.65705,-17.97887 z M 1139.8366,44.661798 a 21.817197,20.751893 3.393352 0 0 -8.3752,3.685094 21.817197,20.751893 3.393352 0 0 -4.1775,28.993805 l 0.2304,0.284584 a 21.817197,20.751893 3.393352 0 0 30.5487,3.770339 21.817197,20.751893 3.393352 0 0 3.9147,-29.029436 21.817197,20.751893 3.393352 0 0 -22.1411,-7.704386 z m 84.4396,-20.445031 a 21.817197,20.751893 3.393352 0 0 -8.3754,3.685117 21.817197,20.751893 3.393352 0 0 -4.1774,28.993806 l 0.2285,0.285027 a 21.817197,20.751893 3.393352 0 0 30.5488,3.77034 21.817197,20.751893 3.393352 0 0 3.9147,-29.02946 21.817197,20.751893 3.393352 0 0 -22.1392,-7.70483 z M 1193.05,74.672751 a 21.817197,20.751893 3.393352 0 0 -8.3759,3.68321 21.817197,20.751893 3.393352 0 0 -4.1769,28.995709 l 0.2303,0.28458 a 21.817197,20.751893 3.393352 0 0 30.5488,3.77035 21.817197,20.751893 3.393352 0 0 3.9128,-29.029006 21.817197,20.751893 3.393352 0 0 -22.1391,-7.704843 z M 865.52481,226.88685 c -7.36616,1.78355 -11.66248,9.20165 -9.63236,16.63136 l 5.86309,21.45735 -27.90161,6.7557 c -7.15183,1.73165 -11.32229,8.9324 -9.35123,16.14595 l 2.77837,10.1681 c 1.97106,7.21354 9.31487,11.6264 16.46669,9.89476 l 27.90161,-6.75571 6.22966,22.7989 c 2.03012,7.42971 9.59558,11.97577 16.96174,10.19223 l 8.59091,-2.08008 c 7.36616,-1.78354 11.6606,-9.2012 9.63048,-16.63091 l -6.22966,-22.7989 23.68151,-5.73391 c 7.15183,-1.73165 11.32229,-8.93242 9.35123,-16.14595 l -2.77837,-10.16811 c -1.97106,-7.21354 -9.31486,-11.62639 -16.46669,-9.89474 l -23.68151,5.73391 -5.86309,-21.45735 c -2.03012,-7.42971 -9.5937,-11.97623 -16.95987,-10.19269 z m 272.15169,-63.56116 a 50.906793,48.421082 3.3933293 0 0 -19.5432,8.59539 50.906793,48.421082 3.3933293 0 0 -9.747,67.65414 l 0.5356,0.66651 a 50.906793,48.421082 3.3933293 0 0 71.2829,8.79621 50.906793,48.421082 3.3933293 0 0 9.1307,-67.73384 50.906793,48.421082 3.3933293 0 0 -51.659,-17.97841 z" />
|
||||
<path
|
||||
id="lpe_path-effect896"
|
||||
style="fill:url(#linearGradient882);stroke-width:1.00028"
|
||||
class="powerclip"
|
||||
d="M 636.0108,56.943474 H 846.95389 V 569.86886 H 636.0108 Z m 534.0113,-61.055366 a 21.817197,20.751893 3.393352 0 0 -8.3753,3.68511674 21.817197,20.751893 3.393352 0 0 -4.1775,28.99380526 l 0.2304,0.284584 a 21.817197,20.751893 3.393352 0 0 30.5488,3.770316 21.817197,20.751893 3.393352 0 0 3.9128,-29.0289691 21.817197,20.751893 3.393352 0 0 -22.1392,-7.7048529 z M 858.04762,85.714292 c -7.15183,1.731644 -11.32417,8.932859 -9.35312,16.146398 l 22.2005,81.24794 c 1.97106,7.21354 9.31675,11.62594 16.46858,9.8943 L 1086.714,144.73497 c 7.1518,-1.73163 11.3223,-8.9324 9.3512,-16.14595 l -22.2005,-81.247936 c -1.971,-7.213536 -9.3149,-11.626381 -16.4667,-9.894748 z M 756.02165,124.73884 a 50.906793,48.421082 3.3933293 0 0 -19.54511,8.59585 50.906793,48.421082 3.3933293 0 0 -9.74699,67.65414 l 0.53564,0.66651 a 50.906793,48.421082 3.3933293 0 0 71.28286,8.79621 50.906793,48.421082 3.3933293 0 0 9.13065,-67.73384 50.906793,48.421082 3.3933293 0 0 -51.65705,-17.97887 z M 1139.8366,44.661798 a 21.817197,20.751893 3.393352 0 0 -8.3752,3.685094 21.817197,20.751893 3.393352 0 0 -4.1775,28.993805 l 0.2304,0.284584 a 21.817197,20.751893 3.393352 0 0 30.5487,3.770339 21.817197,20.751893 3.393352 0 0 3.9147,-29.029436 21.817197,20.751893 3.393352 0 0 -22.1411,-7.704386 z m 84.4396,-20.445031 a 21.817197,20.751893 3.393352 0 0 -8.3754,3.685117 21.817197,20.751893 3.393352 0 0 -4.1774,28.993806 l 0.2285,0.285027 a 21.817197,20.751893 3.393352 0 0 30.5488,3.77034 21.817197,20.751893 3.393352 0 0 3.9147,-29.02946 21.817197,20.751893 3.393352 0 0 -22.1392,-7.70483 z M 1193.05,74.672751 a 21.817197,20.751893 3.393352 0 0 -8.3759,3.68321 21.817197,20.751893 3.393352 0 0 -4.1769,28.995709 l 0.2303,0.28458 a 21.817197,20.751893 3.393352 0 0 30.5488,3.77035 21.817197,20.751893 3.393352 0 0 3.9128,-29.029006 21.817197,20.751893 3.393352 0 0 -22.1391,-7.704843 z M 865.52481,226.88685 c -7.36616,1.78355 -11.66248,9.20165 -9.63236,16.63136 l 5.86309,21.45735 -27.90161,6.7557 c -7.15183,1.73165 -11.32229,8.9324 -9.35123,16.14595 l 2.77837,10.1681 c 1.97106,7.21354 9.31487,11.6264 16.46669,9.89476 l 27.90161,-6.75571 6.22966,22.7989 c 2.03012,7.42971 9.59558,11.97577 16.96174,10.19223 l 8.59091,-2.08008 c 7.36616,-1.78354 11.6606,-9.2012 9.63048,-16.63091 l -6.22966,-22.7989 23.68151,-5.73391 c 7.15183,-1.73165 11.32229,-8.93242 9.35123,-16.14595 l -2.77837,-10.16811 c -1.97106,-7.21354 -9.31486,-11.62639 -16.46669,-9.89474 l -23.68151,5.73391 -5.86309,-21.45735 c -2.03012,-7.42971 -9.5937,-11.97623 -16.95987,-10.19269 z m 272.15169,-63.56116 a 50.906793,48.421082 3.3933293 0 0 -19.5432,8.59539 50.906793,48.421082 3.3933293 0 0 -9.747,67.65414 l 0.5356,0.66651 a 50.906793,48.421082 3.3933293 0 0 71.2829,8.79621 50.906793,48.421082 3.3933293 0 0 9.1307,-67.73384 50.906793,48.421082 3.3933293 0 0 -51.659,-17.97841 z" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1152"
|
||||
id="linearGradient882"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.96459266,-0.23355313,0.26584317,0.97291549,369.02066,-147.43741)"
|
||||
x1="-398"
|
||||
y1="56"
|
||||
x2="1522"
|
||||
y2="1136" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath884">
|
||||
<path
|
||||
id="path886"
|
||||
style="display:none;fill:url(#linearGradient888);stroke-width:1.00027"
|
||||
d="m 1026.6374,528.82806 a 20.752793,21.815894 86.926601 0 0 -9.2243,-0.58528 20.752793,21.815894 86.926601 0 0 -18.53105,23.48045 l 0.0557,0.35396 a 20.752793,21.815894 86.926601 0 0 24.81605,17.20206 20.752793,21.815894 86.926601 0 0 18.3173,-23.63171 20.752793,21.815894 86.926601 0 0 -15.4337,-16.81948 z M 707.37883,465.4963 c -7.15078,-1.7386 -14.49832,2.66675 -16.47273,9.87849 l -22.23828,81.2277 c -1.97441,7.21175 2.19438,14.41711 9.34515,16.15571 l 199.32113,48.46175 c 7.15073,1.73859 14.49643,-2.66722 16.47084,-9.87896 l 22.23828,-81.2277 c 1.97441,-7.21174 -2.19254,-14.41666 -9.34327,-16.15524 z M 598.02135,453.23104 a 48.423182,50.903752 86.926623 0 0 -21.5241,-1.36927 48.423182,50.903752 86.926623 0 0 -43.23978,54.7896 l 0.12713,0.82721 a 48.423182,50.903752 86.926623 0 0 57.90649,40.13811 48.423182,50.903752 86.926623 0 0 42.74098,-55.13985 48.423182,50.903752 86.926623 0 0 -36.01072,-39.2458 z m 377.16446,104.5578 a 20.752793,21.815894 86.926601 0 0 -9.22414,-0.58526 20.752793,21.815894 86.926601 0 0 -18.53108,23.48045 l 0.0557,0.35396 a 20.752793,21.815894 86.926601 0 0 24.8159,17.20204 20.752793,21.815894 86.926601 0 0 18.31921,-23.63124 20.752793,21.815894 86.926601 0 0 -15.43563,-16.81995 z m 84.42719,20.52712 a 20.752793,21.815894 86.926601 0 0 -9.2243,-0.58529 20.752793,21.815894 86.926601 0 0 -18.531,23.48045 l 0.054,0.35352 a 20.752793,21.815894 86.926601 0 0 24.8159,17.20204 20.752793,21.815894 86.926601 0 0 18.3193,-23.63122 20.752793,21.815894 86.926601 0 0 -15.4338,-16.8195 z m -53.2258,29.9599 a 20.752793,21.815894 86.926601 0 0 -9.22373,-0.58718 20.752793,21.815894 86.926601 0 0 -18.53161,23.48235 l 0.0557,0.35395 a 20.752793,21.815894 86.926601 0 0 24.81584,17.20205 20.752793,21.815894 86.926601 0 0 18.3174,-23.63169 20.752793,21.815894 86.926601 0 0 -15.4337,-16.81948 z M 641.50831,592.48259 c -7.36508,-1.79069 -14.93245,2.74811 -16.96603,10.17597 l -5.87307,21.452 -27.8975,-6.78283 c -7.15078,-1.7386 -14.49644,2.6672 -16.47085,9.87895 l -2.7831,10.16557 c -1.97441,7.21174 2.1925,14.41666 9.34328,16.15525 l 27.8975,6.78284 -6.24026,22.79322 c -2.03358,7.42786 2.25909,14.85024 9.62417,16.64094 l 8.58964,2.08844 c 7.36508,1.7907 14.93057,-2.74856 16.96415,-10.17642 l 6.24026,-22.79322 23.67803,5.75693 c 7.15078,1.7386 14.49644,-2.66722 16.47085,-9.87896 l 2.7831,-10.16557 c 1.97441,-7.21175 -2.1925,-14.41665 -9.34328,-16.15525 l -23.67803,-5.75693 5.87307,-21.45201 c 2.03358,-7.42785 -2.25721,-14.84978 -9.62229,-16.64048 z m 270.91446,68.20272 a 48.423182,50.903752 86.926623 0 0 -21.52221,-1.3688 48.423182,50.903752 86.926623 0 0 -43.23975,54.78961 l 0.12708,0.8272 a 48.423182,50.903752 86.926623 0 0 57.90652,40.13811 48.423182,50.903752 86.926623 0 0 42.74097,-55.13984 48.423182,50.903752 86.926623 0 0 -36.01261,-39.24628 z" />
|
||||
<path
|
||||
id="lpe_path-effect900"
|
||||
style="fill:url(#linearGradient888);stroke-width:1.00027"
|
||||
class="powerclip"
|
||||
d="M 912.35657,483.93158 H 1121.6656 V 998.54486 H 912.35657 Z m 114.28083,44.89648 a 20.752793,21.815894 86.926601 0 0 -9.2243,-0.58528 20.752793,21.815894 86.926601 0 0 -18.53105,23.48045 l 0.0557,0.35396 a 20.752793,21.815894 86.926601 0 0 24.81605,17.20206 20.752793,21.815894 86.926601 0 0 18.3173,-23.63171 20.752793,21.815894 86.926601 0 0 -15.4337,-16.81948 z M 707.37883,465.4963 c -7.15078,-1.7386 -14.49832,2.66675 -16.47273,9.87849 l -22.23828,81.2277 c -1.97441,7.21175 2.19438,14.41711 9.34515,16.15571 l 199.32113,48.46175 c 7.15073,1.73859 14.49643,-2.66722 16.47084,-9.87896 l 22.23828,-81.2277 c 1.97441,-7.21174 -2.19254,-14.41666 -9.34327,-16.15524 z M 598.02135,453.23104 a 48.423182,50.903752 86.926623 0 0 -21.5241,-1.36927 48.423182,50.903752 86.926623 0 0 -43.23978,54.7896 l 0.12713,0.82721 a 48.423182,50.903752 86.926623 0 0 57.90649,40.13811 48.423182,50.903752 86.926623 0 0 42.74098,-55.13985 48.423182,50.903752 86.926623 0 0 -36.01072,-39.2458 z m 377.16446,104.5578 a 20.752793,21.815894 86.926601 0 0 -9.22414,-0.58526 20.752793,21.815894 86.926601 0 0 -18.53108,23.48045 l 0.0557,0.35396 a 20.752793,21.815894 86.926601 0 0 24.8159,17.20204 20.752793,21.815894 86.926601 0 0 18.31921,-23.63124 20.752793,21.815894 86.926601 0 0 -15.43563,-16.81995 z m 84.42719,20.52712 a 20.752793,21.815894 86.926601 0 0 -9.2243,-0.58529 20.752793,21.815894 86.926601 0 0 -18.531,23.48045 l 0.054,0.35352 a 20.752793,21.815894 86.926601 0 0 24.8159,17.20204 20.752793,21.815894 86.926601 0 0 18.3193,-23.63122 20.752793,21.815894 86.926601 0 0 -15.4338,-16.8195 z m -53.2258,29.9599 a 20.752793,21.815894 86.926601 0 0 -9.22373,-0.58718 20.752793,21.815894 86.926601 0 0 -18.53161,23.48235 l 0.0557,0.35395 a 20.752793,21.815894 86.926601 0 0 24.81584,17.20205 20.752793,21.815894 86.926601 0 0 18.3174,-23.63169 20.752793,21.815894 86.926601 0 0 -15.4337,-16.81948 z M 641.50831,592.48259 c -7.36508,-1.79069 -14.93245,2.74811 -16.96603,10.17597 l -5.87307,21.452 -27.8975,-6.78283 c -7.15078,-1.7386 -14.49644,2.6672 -16.47085,9.87895 l -2.7831,10.16557 c -1.97441,7.21174 2.1925,14.41666 9.34328,16.15525 l 27.8975,6.78284 -6.24026,22.79322 c -2.03358,7.42786 2.25909,14.85024 9.62417,16.64094 l 8.58964,2.08844 c 7.36508,1.7907 14.93057,-2.74856 16.96415,-10.17642 l 6.24026,-22.79322 23.67803,5.75693 c 7.15078,1.7386 14.49644,-2.66722 16.47085,-9.87896 l 2.7831,-10.16557 c 1.97441,-7.21175 -2.1925,-14.41665 -9.34328,-16.15525 l -23.67803,-5.75693 5.87307,-21.45201 c 2.03358,-7.42785 -2.25721,-14.84978 -9.62229,-16.64048 z m 270.91446,68.20272 a 48.423182,50.903752 86.926623 0 0 -21.52221,-1.3688 48.423182,50.903752 86.926623 0 0 -43.23975,54.78961 l 0.12708,0.8272 a 48.423182,50.903752 86.926623 0 0 57.90652,40.13811 48.423182,50.903752 86.926623 0 0 42.74097,-55.13984 48.423182,50.903752 86.926623 0 0 -36.01261,-39.24628 z" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1152"
|
||||
id="linearGradient888"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.96445087,0.23449084,-0.26629564,0.97267307,398.764,38.857662)"
|
||||
x1="-398"
|
||||
y1="56"
|
||||
x2="1522"
|
||||
y2="1136" />
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath890">
|
||||
<path
|
||||
id="path892"
|
||||
style="display:none;fill:url(#linearGradient894)"
|
||||
d="m 1138.793,269.14648 a 21.88452,20.676565 0 0 0 -9.1231,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1484,0.32813 a 21.88452,20.676565 0 0 0 28.7032,10.76562 21.88452,20.676565 0 0 0 11.5175,-27.07226 21.88452,20.676565 0 0 0 -19.4804,-12.59571 z m -327.22269,13.7754 c -7.41435,0 -13.38476,5.96846 -13.38476,13.38281 v 83.50976 c 0,7.41436 5.97041,13.38282 13.38476,13.38282 h 206.66799 c 7.4143,0 13.3828,-5.96846 13.3828,-13.38282 v -83.50976 c 0,-7.41435 -5.9685,-13.38281 -13.3828,-13.38281 z m -109.57617,13.80664 a 51.063881,48.245316 0 0 0 -21.28906,3.7246 51.063881,48.245316 0 0 0 -27.45313,62.94727 l 0.34375,0.76758 a 51.063881,48.245316 0 0 0 66.97657,25.11914 51.063881,48.245316 0 0 0 26.875,-63.16797 51.063881,48.245316 0 0 0 -45.45313,-29.39062 z m 394.48826,12.39257 a 21.88452,20.676565 0 0 0 -9.123,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1484,0.32813 a 21.88452,20.676565 0 0 0 28.7031,10.76562 21.88452,20.676565 0 0 0 11.5195,-27.07226 21.88452,20.676565 0 0 0 -19.4824,-12.59571 z m 87.5391,0 a 21.88452,20.676565 0 0 0 -9.1231,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1465,0.32813 a 21.88452,20.676565 0 0 0 28.7031,10.76562 21.88452,20.676565 0 0 0 11.5196,-27.07226 21.88452,20.676565 0 0 0 -19.4805,-12.59571 z m -43.7695,41.35352 a 21.88452,20.676565 0 0 0 -9.1231,1.5957 21.88452,20.676565 0 0 0 -11.7656,26.97852 l 0.1484,0.32812 a 21.88452,20.676565 0 0 0 28.7031,10.76563 21.88452,20.676565 0 0 0 11.5176,-27.07227 21.88452,20.676565 0 0 0 -19.4804,-12.5957 z m -358.91997,70.29101 c -7.63655,10e-6 -13.78515,6.14862 -13.78515,13.78516 v 22.05469 h -28.92579 c -7.41435,0 -13.38281,5.96845 -13.38281,13.38281 v 10.45117 c 0,7.41435 5.96846,13.38282 13.38281,13.38282 h 28.92579 v 23.43359 c 0,7.63654 6.1486,13.78516 13.78515,13.78516 h 8.90625 c 7.63655,0 13.7832,-6.14862 13.7832,-13.78516 v -23.43359 h 24.55079 c 7.41435,0 13.38281,-5.96847 13.38281,-13.38282 v -10.45117 c 0,-7.41436 -5.96846,-13.38281 -13.38281,-13.38281 h -24.55079 v -22.05469 c 0,-7.63654 -6.14665,-13.78516 -13.7832,-13.78516 z m 281.52147,2.25 a 51.063881,48.245316 0 0 0 -21.2871,3.72461 51.063881,48.245316 0 0 0 -27.4531,62.94727 l 0.3437,0.76758 a 51.063881,48.245316 0 0 0 66.9766,25.11914 51.063881,48.245316 0 0 0 26.875,-63.16797 51.063881,48.245316 0 0 0 -45.4551,-29.39063 z" />
|
||||
<path
|
||||
id="lpe_path-effect904"
|
||||
style="fill:url(#linearGradient894)"
|
||||
class="powerclip"
|
||||
d="M 571.42297,222.78436 H 1252.5483 V 563.60941 H 571.42297 Z m 567.37003,46.36212 a 21.88452,20.676565 0 0 0 -9.1231,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1484,0.32813 a 21.88452,20.676565 0 0 0 28.7032,10.76562 21.88452,20.676565 0 0 0 11.5175,-27.07226 21.88452,20.676565 0 0 0 -19.4804,-12.59571 z m -327.22269,13.7754 c -7.41435,0 -13.38476,5.96846 -13.38476,13.38281 v 83.50976 c 0,7.41436 5.97041,13.38282 13.38476,13.38282 h 206.66799 c 7.4143,0 13.3828,-5.96846 13.3828,-13.38282 v -83.50976 c 0,-7.41435 -5.9685,-13.38281 -13.3828,-13.38281 z m -109.57617,13.80664 a 51.063881,48.245316 0 0 0 -21.28906,3.7246 51.063881,48.245316 0 0 0 -27.45313,62.94727 l 0.34375,0.76758 a 51.063881,48.245316 0 0 0 66.97657,25.11914 51.063881,48.245316 0 0 0 26.875,-63.16797 51.063881,48.245316 0 0 0 -45.45313,-29.39062 z m 394.48826,12.39257 a 21.88452,20.676565 0 0 0 -9.123,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1484,0.32813 a 21.88452,20.676565 0 0 0 28.7031,10.76562 21.88452,20.676565 0 0 0 11.5195,-27.07226 21.88452,20.676565 0 0 0 -19.4824,-12.59571 z m 87.5391,0 a 21.88452,20.676565 0 0 0 -9.1231,1.59766 21.88452,20.676565 0 0 0 -11.7656,26.97656 l 0.1465,0.32813 a 21.88452,20.676565 0 0 0 28.7031,10.76562 21.88452,20.676565 0 0 0 11.5196,-27.07226 21.88452,20.676565 0 0 0 -19.4805,-12.59571 z m -43.7695,41.35352 a 21.88452,20.676565 0 0 0 -9.1231,1.5957 21.88452,20.676565 0 0 0 -11.7656,26.97852 l 0.1484,0.32812 a 21.88452,20.676565 0 0 0 28.7031,10.76563 21.88452,20.676565 0 0 0 11.5176,-27.07227 21.88452,20.676565 0 0 0 -19.4804,-12.5957 z m -358.91997,70.29101 c -7.63655,10e-6 -13.78515,6.14862 -13.78515,13.78516 v 22.05469 h -28.92579 c -7.41435,0 -13.38281,5.96845 -13.38281,13.38281 v 10.45117 c 0,7.41435 5.96846,13.38282 13.38281,13.38282 h 28.92579 v 23.43359 c 0,7.63654 6.1486,13.78516 13.78515,13.78516 h 8.90625 c 7.63655,0 13.7832,-6.14862 13.7832,-13.78516 v -23.43359 h 24.55079 c 7.41435,0 13.38281,-5.96847 13.38281,-13.38282 v -10.45117 c 0,-7.41436 -5.96846,-13.38281 -13.38281,-13.38281 h -24.55079 v -22.05469 c 0,-7.63654 -6.14665,-13.78516 -13.7832,-13.78516 z m 281.52147,2.25 a 51.063881,48.245316 0 0 0 -21.2871,3.72461 51.063881,48.245316 0 0 0 -27.4531,62.94727 l 0.3437,0.76758 a 51.063881,48.245316 0 0 0 66.9766,25.11914 51.063881,48.245316 0 0 0 26.875,-63.16797 51.063881,48.245316 0 0 0 -45.4551,-29.39063 z" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1152"
|
||||
id="linearGradient894"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(398,-56)"
|
||||
x1="-398"
|
||||
y1="56"
|
||||
x2="1522"
|
||||
y2="1136" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:url(#linearGradient1154);fill-opacity:1"
|
||||
id="rect1033"
|
||||
width="1920"
|
||||
height="1080"
|
||||
x="0"
|
||||
y="0"
|
||||
rx="0"
|
||||
ry="0" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||
id="rect2078"
|
||||
width="671.12531"
|
||||
height="330.82504"
|
||||
x="576.42297"
|
||||
y="227.78436"
|
||||
ry="110.27502"
|
||||
sodipodi:type="rect"
|
||||
clip-path="url(#clipPath890)"
|
||||
inkscape:path-effect="#path-effect904"
|
||||
d="m 686.69799,227.78436 h 450.57531 c 61.0923,0 110.275,49.18266 110.275,110.27502 v 110.27501 c 0,61.09236 -49.1827,110.27502 -110.275,110.27502 H 686.69799 c -61.09236,0 -110.27502,-49.18266 -110.27502,-110.27502 V 338.05938 c 0,-61.09236 49.18266,-110.27502 110.27502,-110.27502 z" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41852"
|
||||
id="rect2146"
|
||||
width="199.30905"
|
||||
height="504.61328"
|
||||
x="917.35657"
|
||||
y="488.93158"
|
||||
ry="97.030388"
|
||||
transform="matrix(0.97214881,-0.23436445,0.26615211,0.96393104,0,0)"
|
||||
sodipodi:type="rect"
|
||||
clip-path="url(#clipPath884)"
|
||||
inkscape:path-effect="#path-effect900"
|
||||
d="m 1014.387,488.93158 h 5.2482 c 53.7549,0 97.0304,43.27555 97.0304,97.03039 v 310.5525 c 0,53.75484 -43.2755,97.03039 -97.0304,97.03039 h -5.2482 c -53.75488,0 -97.03043,-43.27555 -97.03043,-97.03039 v -310.5525 c 0,-53.75484 43.27555,-97.03039 97.03043,-97.03039 z" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41852"
|
||||
id="rect2146-3"
|
||||
width="200.94308"
|
||||
height="502.92538"
|
||||
x="641.0108"
|
||||
y="61.943474"
|
||||
ry="97.050156"
|
||||
transform="matrix(0.97237519,0.23342343,-0.26569554,0.96405699,0,0)"
|
||||
sodipodi:type="rect"
|
||||
clip-path="url(#clipPath878)"
|
||||
inkscape:path-effect="#path-effect896"
|
||||
d="m 738.06096,61.943474 h 6.84277 c 53.76579,0 97.05016,43.284366 97.05016,97.050156 V 467.8187 c 0,53.76579 -43.28437,97.05016 -97.05016,97.05016 h -6.84277 c -53.76579,0 -97.05016,-43.28437 -97.05016,-97.05016 V 158.99363 c 0,-53.76579 43.28437,-97.050156 97.05016,-97.050156 z" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||
id="rect2384"
|
||||
width="87.538078"
|
||||
height="55.137505"
|
||||
x="649.37134"
|
||||
y="214"
|
||||
ry="27.568752" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:1.41813"
|
||||
id="rect2384-6"
|
||||
width="87.538078"
|
||||
height="55.137505"
|
||||
x="1089.9797"
|
||||
y="214"
|
||||
ry="27.568752" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 24 KiB |
@@ -3,24 +3,34 @@ org.gradle.jvmargs=-Xmx1G
|
||||
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/use
|
||||
minecraft_version=1.18.1
|
||||
yarn_mappings=1.18.1+build.22
|
||||
loader_version=0.13.3
|
||||
minecraft_version=1.21
|
||||
yarn_mappings=1.21+build.1
|
||||
loader_version=0.15.11
|
||||
|
||||
# Mod Properties
|
||||
mod_version = 0.2.0
|
||||
mod_version = 1.9.7
|
||||
maven_group = eu.midnightdust
|
||||
archives_base_name = midnightcontrols
|
||||
modrinth_id=W1D3UXEc
|
||||
release_type=beta
|
||||
modrinth_id = bXX9h73M
|
||||
curseforge_id = 621768
|
||||
|
||||
# Dependencies
|
||||
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
|
||||
fabric_version=0.46.6+1.18
|
||||
spruceui_version=3.3.2+1.17
|
||||
midnightlib_version=0.4.0
|
||||
modmenu_version=2.0.2
|
||||
emotecraft_version=2.1-MC1.18.1-fabric
|
||||
fabric_version=0.100.1+1.21
|
||||
sodium_version=mc1.19.2-0.4.4
|
||||
obsidianui_version=0.2.6+mc1.21-fabric
|
||||
midnightlib_version=1.5.7-fabric
|
||||
modmenu_version=10.0.0-beta.1
|
||||
emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric
|
||||
bendylib_version=2.0.+
|
||||
rei_version=7.4.456
|
||||
ok_zoomer_version=5.0.0-beta.3+1.17.1
|
||||
libzoomer_version = 0.3.0+1.17.1
|
||||
emi_version=1.1.1+1.20.4+fabric
|
||||
libgui_version=6.0.0+1.19
|
||||
inventorytabs_version=inventorytabs-0.9.beta-1.19.x
|
||||
clothconfig_version=7.0.72
|
||||
yacl_version=2.2.0
|
||||
bedrockify_version=1.9+mc1.20
|
||||
|
||||
# Ok Zoomer and LibZoomer are temporarily disabled for the time being, as we are currently using Reflection at runtime instead in OkZoomerCompat due to there being two major, completely incompatible API versions.
|
||||
# ok_zoomer_version=5.0.0-beta.3+1.17.1
|
||||
# libzoomer_version=0.3.0+1.17.1
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
41
gradlew
vendored
@@ -55,7 +55,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -80,13 +80,11 @@ do
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -133,22 +131,29 @@ location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
@@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
@@ -205,6 +214,12 @@ set -- \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
|
||||
15
gradlew.bat
vendored
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,7 +25,8 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
BIN
icon.png
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 174 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 184 KiB |
@@ -4,6 +4,7 @@ pluginManagement {
|
||||
name 'Fabric'
|
||||
url 'https://maven.fabricmc.net/'
|
||||
}
|
||||
maven { url "https://maven.architectury.dev/" }
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols;
|
||||
|
||||
import dev.lambdaurora.spruceui.util.Nameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.thinkingstudio.obsidianui.util.Nameable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
@@ -24,7 +24,8 @@ import java.util.Optional;
|
||||
*/
|
||||
public enum ControlsMode implements Nameable {
|
||||
DEFAULT,
|
||||
CONTROLLER;
|
||||
CONTROLLER,
|
||||
TOUCHSCREEN;
|
||||
|
||||
/**
|
||||
* Returns the next controls mode available.
|
||||
|
||||
@@ -10,20 +10,16 @@
|
||||
package eu.midnightdust.midnightcontrols;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.event.PlayerChangeControlsModeCallback;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePacket;
|
||||
import eu.midnightdust.midnightcontrols.packet.FeaturePacket;
|
||||
import eu.midnightdust.midnightcontrols.packet.HelloPacket;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Represents the MidnightControls mod.
|
||||
@@ -34,32 +30,32 @@ import java.util.Optional;
|
||||
*/
|
||||
public class MidnightControls implements ModInitializer {
|
||||
private static MidnightControls INSTANCE;
|
||||
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(MidnightControlsConstants.CONTROLS_MODE_CHANNEL.toString());
|
||||
public static final Identifier FEATURE_CHANNEL = new Identifier(MidnightControlsConstants.FEATURE_CHANNEL.toString());
|
||||
public static final Identifier HELLO_CHANNEL = new Identifier(MidnightControlsConstants.HELLO_CHANNEL.toString());
|
||||
|
||||
public static final TranslatableText NOT_BOUND_TEXT = new TranslatableText("midnightcontrols.not_bound");
|
||||
public static final CustomPayload.Id<CustomPayload> CONTROLS_MODE_CHANNEL = new CustomPayload.Id<>(MidnightControlsConstants.CONTROLS_MODE_CHANNEL);
|
||||
public static final CustomPayload.Id<CustomPayload> FEATURE_CHANNEL = new CustomPayload.Id<>(MidnightControlsConstants.FEATURE_CHANNEL);
|
||||
public static final CustomPayload.Id<CustomPayload> HELLO_CHANNEL = new CustomPayload.Id<>(MidnightControlsConstants.HELLO_CHANNEL);
|
||||
public static boolean isExtrasLoaded;
|
||||
|
||||
public final Logger logger = LogManager.getLogger("MidnightControls");
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
INSTANCE = this;
|
||||
isExtrasLoaded = FabricLoader.getInstance().isModLoaded("midnightcontrols-extra");
|
||||
this.log("Initializing MidnightControls...");
|
||||
|
||||
ServerPlayNetworking.registerGlobalReceiver(HELLO_CHANNEL, (server, player, handler, buf, responseSender) -> {
|
||||
String version = buf.readString(32);
|
||||
ControlsMode.byId(buf.readString(32))
|
||||
.ifPresent(controlsMode -> server
|
||||
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode)));
|
||||
server.execute(() -> {
|
||||
ServerPlayNetworking.send(player, FEATURE_CHANNEL, this.makeFeatureBuffer(MidnightControlsFeature.HORIZONTAL_REACHAROUND));
|
||||
});
|
||||
PayloadTypeRegistry.playC2S().register(HelloPacket.PACKET_ID, HelloPacket.codec);
|
||||
PayloadTypeRegistry.playC2S().register(ControlsModePacket.PACKET_ID, ControlsModePacket.codec);
|
||||
PayloadTypeRegistry.playS2C().register(ControlsModePacket.PACKET_ID, ControlsModePacket.codec);
|
||||
PayloadTypeRegistry.playS2C().register(FeaturePacket.PACKET_ID, FeaturePacket.codec);
|
||||
|
||||
ServerPlayNetworking.registerGlobalReceiver(HelloPacket.PACKET_ID, (payload, context) -> {
|
||||
ControlsMode.byId(payload.controlsMode())
|
||||
.ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode));
|
||||
context.responseSender().sendPacket(new FeaturePacket(MidnightControlsFeature.HORIZONTAL_REACHAROUND));
|
||||
});
|
||||
ServerPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL,
|
||||
(server, player, handler, buf, responseSender) -> ControlsMode.byId(buf.readString(32))
|
||||
.ifPresent(controlsMode -> server
|
||||
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode))));
|
||||
ServerPlayNetworking.registerGlobalReceiver(ControlsModePacket.PACKET_ID,
|
||||
(payload, context) -> ControlsMode.byId(payload.controlsMode())
|
||||
.ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,44 +76,6 @@ public class MidnightControls implements ModInitializer {
|
||||
this.logger.info("[MidnightControls] " + warning);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a packet byte buffer made for the midnightcontrols:controls_mode plugin message.
|
||||
*
|
||||
* @param controlsMode the controls mode to send
|
||||
* @return the packet byte buffer
|
||||
*/
|
||||
public PacketByteBuf makeControlsModeBuffer(@NotNull ControlsMode controlsMode) {
|
||||
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
|
||||
return new PacketByteBuf(Unpooled.buffer()).writeString(controlsMode.getName(), 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a packet byte buffer made for the midnightcontrols:feature plugin message.
|
||||
*
|
||||
* @param features the features data to send
|
||||
* @return the packet byte buffer
|
||||
*/
|
||||
public PacketByteBuf makeFeatureBuffer(MidnightControlsFeature... features) {
|
||||
if (features.length == 0)
|
||||
throw new IllegalArgumentException("At least one feature must be provided.");
|
||||
var buffer = new PacketByteBuf(Unpooled.buffer());
|
||||
buffer.writeVarInt(features.length);
|
||||
for (var feature : features) {
|
||||
buffer.writeString(feature.getName(), 64);
|
||||
buffer.writeBoolean(feature.isAllowed());
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public PacketByteBuf makeHello(@NotNull ControlsMode controlsMode) {
|
||||
var version = "";
|
||||
Optional<ModContainer> container;
|
||||
if ((container = FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE)).isPresent()) {
|
||||
version = container.get().getMetadata().getVersion().getFriendlyString();
|
||||
}
|
||||
return new PacketByteBuf(Unpooled.buffer()).writeString(version, 32).writeString(controlsMode.getName(), 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MidnightControls instance.
|
||||
*
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.minecraft.util.Identifier;
|
||||
*/
|
||||
public class MidnightControlsConstants {
|
||||
public static final String NAMESPACE = "midnightcontrols";
|
||||
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(NAMESPACE, "controls_mode");
|
||||
public static final Identifier FEATURE_CHANNEL = new Identifier(NAMESPACE, "feature");
|
||||
public static final Identifier HELLO_CHANNEL = new Identifier(NAMESPACE, "hello");
|
||||
public static final Identifier CONTROLS_MODE_CHANNEL = Identifier.of(NAMESPACE, "controls_mode");
|
||||
public static final Identifier FEATURE_CHANNEL = Identifier.of(NAMESPACE, "feature");
|
||||
public static final Identifier HELLO_CHANNEL = Identifier.of(NAMESPACE, "hello");
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols;
|
||||
|
||||
import dev.lambdaurora.spruceui.util.Nameable;
|
||||
import org.thinkingstudio.obsidianui.util.Nameable;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -61,7 +61,7 @@ public class MidnightControlsFeature implements Nameable {
|
||||
* @return {@code true} if this feature is allowed, else {@code false}
|
||||
*/
|
||||
public boolean isAllowed() {
|
||||
return this.allowed;
|
||||
return MidnightControls.isExtrasLoaded && this.allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,6 +98,15 @@ public class MidnightControlsFeature implements Nameable {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the enabled values from the config.
|
||||
*/
|
||||
public static void refreshEnabled() {
|
||||
MidnightControlsFeature.VERTICAL_REACHAROUND.setEnabled(MidnightControlsConfig.verticalReacharound);
|
||||
MidnightControlsFeature.FAST_BLOCK_PLACING.setEnabled(MidnightControlsConfig.fastBlockPlacing);
|
||||
MidnightControlsFeature.HORIZONTAL_REACHAROUND.setEnabled(MidnightControlsConfig.horizontalReacharound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this feature is available or not.
|
||||
*
|
||||
|
||||
@@ -9,37 +9,50 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
|
||||
import dev.lambdaurora.spruceui.event.OpenScreenCallback;
|
||||
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.gui.TouchscreenOverlay;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.KeyBindingRingAction;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
||||
import dev.lambdaurora.spruceui.hud.HudManager;
|
||||
import org.thinkingstudio.obsidianui.fabric.event.OpenScreenCallback;
|
||||
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.ControlsModePacket;
|
||||
import eu.midnightdust.midnightcontrols.packet.FeaturePacket;
|
||||
import eu.midnightdust.midnightcontrols.packet.HelloPacket;
|
||||
import net.fabricmc.api.ClientModInitializer;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import net.minecraft.client.toast.SystemToast;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
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.*;
|
||||
|
||||
/**
|
||||
* Represents the midnightcontrols client mod.
|
||||
@@ -49,22 +62,23 @@ import java.io.File;
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class MidnightControlsClient extends MidnightControls implements ClientModInitializer {
|
||||
public static boolean lateInitDone = false;
|
||||
private static MidnightControlsClient INSTANCE;
|
||||
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_up"),
|
||||
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "look_up"),
|
||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement");
|
||||
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_right"),
|
||||
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "look_right"),
|
||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.movement");
|
||||
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_down"),
|
||||
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "look_down"),
|
||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.movement");
|
||||
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_left"),
|
||||
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "look_left"),
|
||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.movement");
|
||||
/*public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(new Identifier(midnightcontrolsConstants.NAMESPACE, "ring"),
|
||||
InputUtil.Type.MOUSE, GLFW.GLFW_MOUSE_BUTTON_5, "key.categories.misc");*/
|
||||
public static final Identifier CONTROLLER_BUTTONS = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_buttons.png");
|
||||
public static final Identifier CONTROLLER_EXPANDED = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_expanded.png");
|
||||
public static final Identifier CONTROLLER_AXIS = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_axis.png");
|
||||
public static final Identifier CURSOR_TEXTURE = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/cursor.png");
|
||||
public final static File MAPPINGS_FILE = new File("config/gamecontrollerdb.txt");
|
||||
public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "ring"),
|
||||
InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), "key.categories.misc");
|
||||
public static final Identifier CONTROLLER_BUTTONS = Identifier.of(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_buttons.png");
|
||||
public static final Identifier CONTROLLER_EXPANDED = Identifier.of(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_expanded.png");
|
||||
public static final Identifier CONTROLLER_AXIS = Identifier.of(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_axis.png");
|
||||
public static final Identifier CURSOR_TEXTURE = Identifier.of(MidnightControlsConstants.NAMESPACE, "textures/gui/cursor.png");
|
||||
public final static File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt");
|
||||
public final MidnightInput input = new MidnightInput();
|
||||
public final MidnightRing ring = new MidnightRing(this);
|
||||
public final MidnightReacharound reacharound = new MidnightReacharound();
|
||||
@@ -78,42 +92,54 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT);
|
||||
//KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
||||
KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
||||
|
||||
this.ring.registerAction("keybinding", KeyBindingRingAction.FACTORY);
|
||||
this.ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY);
|
||||
|
||||
ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (payload, context) ->
|
||||
context.responseSender().sendPacket(new ControlsModePacket(MidnightControlsConfig.controlsMode.getName())));
|
||||
ClientPlayNetworking.registerGlobalReceiver(FeaturePacket.PACKET_ID, ((payload, context) -> {}));
|
||||
|
||||
ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (client, handler, buf, responseSender) -> {
|
||||
responseSender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode));
|
||||
});
|
||||
ClientPlayNetworking.registerGlobalReceiver(FEATURE_CHANNEL, (client, handler, buf, responseSender) -> {
|
||||
int features = buf.readVarInt();
|
||||
for (int i = 0; i < features; i++) {
|
||||
var name = buf.readString(64);
|
||||
boolean allowed = buf.readBoolean();
|
||||
MidnightControlsFeature.fromName(name).ifPresent(feature -> client.execute(() -> feature.setAllowed(allowed)));
|
||||
}
|
||||
});
|
||||
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
||||
sender.sendPacket(HELLO_CHANNEL, this.makeHello(MidnightControlsConfig.controlsMode));
|
||||
sender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode));
|
||||
var version = "";
|
||||
Optional<ModContainer> container;
|
||||
if ((container = FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE)).isPresent()) {
|
||||
version = container.get().getMetadata().getVersion().getFriendlyString();
|
||||
}
|
||||
var controlsMode = MidnightControlsConfig.controlsMode.getName();
|
||||
sender.sendPacket(new HelloPacket(version, controlsMode));
|
||||
sender.sendPacket(new ControlsModePacket(controlsMode));
|
||||
});
|
||||
ClientPlayConnectionEvents.DISCONNECT.register(this::onLeave);
|
||||
|
||||
ClientTickEvents.START_CLIENT_TICK.register(this.reacharound::tick);
|
||||
ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
|
||||
ClientTickEvents.START_CLIENT_TICK.register(this::onTick);
|
||||
|
||||
OpenScreenCallback.EVENT.register((client, screen) -> {
|
||||
// if (screen == null && MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) {
|
||||
// screen = new TouchscreenOverlay(this);
|
||||
// screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||
// client.skipGameRender = false;
|
||||
// client.currentScreen = screen;
|
||||
// } else if (screen != null) {
|
||||
OpenScreenCallback.POST.register((client, screen) -> {
|
||||
if (screen == null && MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) {
|
||||
screen = new TouchscreenOverlay(this);
|
||||
screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||
client.skipGameRender = false;
|
||||
client.currentScreen = screen;
|
||||
} else if (screen != null) {
|
||||
this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight());
|
||||
//}
|
||||
}
|
||||
});
|
||||
final MinecraftClient client = MinecraftClient.getInstance();
|
||||
int delay = 0; // delay for 0 sec.
|
||||
int period = 1; // repeat every 0.001 sec. (100 times a second)
|
||||
Timer timer = new Timer();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
input.updateCamera(client);
|
||||
}
|
||||
}, delay, period);
|
||||
|
||||
HudManager.register(this.hud = new MidnightControlsHud(this));
|
||||
FabricLoader.getInstance().getModContainer("midnightcontrols").ifPresent(modContainer -> {
|
||||
ResourceManagerHelper.registerBuiltinResourcePack(Identifier.of("midnightcontrols","bedrock"), modContainer, ResourcePackActivationType.NORMAL);
|
||||
ResourceManagerHelper.registerBuiltinResourcePack(Identifier.of("midnightcontrols","legacy"), modContainer, ResourcePackActivationType.NORMAL);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,23 +148,66 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
|
||||
public 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("midnightcontrols");
|
||||
}
|
||||
this.hud.setVisible(MidnightControlsConfig.hudEnable);
|
||||
Controller.updateMappings();
|
||||
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
||||
if (event == GLFW.GLFW_CONNECTED) {
|
||||
var controller = Controller.byId(jid);
|
||||
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("midnightcontrols.controller.connected", jid),
|
||||
new LiteralText(controller.getName())));
|
||||
} else if (event == GLFW.GLFW_DISCONNECTED) {
|
||||
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("midnightcontrols.controller.disconnected", jid),
|
||||
null));
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
this.switchControlsMode();
|
||||
});
|
||||
this.switchControlsMode();
|
||||
});
|
||||
} catch (Exception e) {e.fillInStackTrace();}
|
||||
|
||||
MidnightControlsCompat.init(this);
|
||||
}
|
||||
ButtonCategory category;
|
||||
/**
|
||||
* This method is called to initialize keybindings
|
||||
*/
|
||||
public 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("midnightcontrols") && !keyBinding.getTranslationKey().contains("ok_zoomer") && !keyBinding.getTranslationKey().contains("okzoomer")) {
|
||||
category = null;
|
||||
InputManager.streamCategories().forEach(buttonCategory -> {
|
||||
if (buttonCategory.getIdentifier().equals(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory())))
|
||||
category = buttonCategory;
|
||||
});
|
||||
if (category == null) {
|
||||
category = new ButtonCategory(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory()));
|
||||
InputManager.registerCategory(category);
|
||||
}
|
||||
ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getTranslationKey()).category(category).linkKeybind(keyBinding).register();
|
||||
if (MidnightControlsConfig.debug) {
|
||||
logger.info(keyBinding.getTranslationKey());
|
||||
logger.info(buttonBinding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InputManager.loadButtonBindings();
|
||||
lateInitDone = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called every Minecraft tick.
|
||||
@@ -146,17 +215,24 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
|
||||
* @param client the client instance
|
||||
*/
|
||||
public void onTick(@NotNull MinecraftClient client) {
|
||||
this.initKeybindings();
|
||||
this.input.tick(client);
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput))
|
||||
this.input.tickController(client);
|
||||
|
||||
/*if (BINDING_RING.wasPressed()) {
|
||||
client.openScreen(new RingScreen());
|
||||
}*/
|
||||
}
|
||||
|
||||
public void onRender(MinecraftClient client) {
|
||||
this.input.onRender(client.getTickDelta(), client);
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,6 +257,7 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
|
||||
|
||||
MidnightControlsConfig.controlsMode = this.previousControlsMode;
|
||||
}
|
||||
ClientPlayNetworking.getSender().sendPacket(new ControlsModePacket(MidnightControlsConfig.controlsMode.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,24 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.blaze3d.platform.GlDebugInfo;
|
||||
import eu.midnightdust.lib.config.MidnightConfig;
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import 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;
|
||||
@@ -21,54 +34,96 @@ import org.lwjgl.glfw.GLFW;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_X;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y;
|
||||
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
|
||||
@Entry public static ControlsMode controlsMode = ControlsMode.DEFAULT;
|
||||
@Entry public static boolean autoSwitchMode = false;
|
||||
@Entry public static boolean debug = false;
|
||||
@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;
|
||||
@Entry(category = MISC, name = "Debug") public static boolean debug = false;
|
||||
// HUD
|
||||
@Entry public static boolean hudEnable = true;
|
||||
@Entry public static HudSide hudSide = HudSide.LEFT;
|
||||
@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 = SCREENS, name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false;
|
||||
// Gameplay
|
||||
@Entry public static boolean analogMovement = true;
|
||||
@Entry public static boolean fastBlockPlacing = true;
|
||||
@Entry public static boolean flyDrifting = false;
|
||||
@Entry public static boolean verticalFlyDrifting = true;
|
||||
@Entry public static boolean horizontalReacharound = false;
|
||||
@Entry public static boolean verticalReacharound = false;
|
||||
@Entry public static boolean shouldRenderReacharoundOutline = true;
|
||||
@Entry public static int[] reacharoundOutlineColor = new int[]{255, 255, 255, 102};
|
||||
// Controller
|
||||
@Entry public static ControllerType controllerType = ControllerType.DEFAULT;
|
||||
@Entry public static double rightDeadZone = 0.25;
|
||||
@Entry public static double leftDeadZone = 0.25;
|
||||
@Entry public static boolean invertRightYAxis = false;
|
||||
@Entry public static boolean invertRightXAxis = false;
|
||||
@Entry public static double DEFAULT_MAX_VALUE = 1;
|
||||
@Entry public static double rotationSpeed = 40.0;
|
||||
@Entry public static double mouseSpeed = 25.0;
|
||||
@Entry public static boolean unfocusedInput = false;
|
||||
@Entry public static boolean virtualMouse = false;
|
||||
@Entry public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
|
||||
// @Entry public static List<Pages> ringPages = new ArrayList<String>();
|
||||
// @Entry public static double maxAnalog1 = 1;
|
||||
// @Entry public static double maxAnalog2 = 1;
|
||||
// @Entry public static double maxAnalog3 = 1;
|
||||
// @Entry public static double maxAnalog4 = 1;
|
||||
@Entry public static Object controllerID = 0;
|
||||
@Entry public static Object secondControllerID = -1;
|
||||
@Entry public static Map<String, String> BINDINGS = Map.of();
|
||||
@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();
|
||||
@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.
|
||||
@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.
|
||||
@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.
|
||||
@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.
|
||||
@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.
|
||||
@Entry(category = VISUAL, name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true;
|
||||
@Entry(category = VISUAL, name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff";
|
||||
@Entry(category = VISUAL, name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102;
|
||||
@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 = "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;
|
||||
@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 = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false;
|
||||
@Entry(category = SCREENS, 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;
|
||||
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false;
|
||||
@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 = CONTROLLER, name = "Controller ID") @Hidden public static Object controllerID = 0;
|
||||
@Entry(category = CONTROLLER, name = "2nd Controller ID") @Hidden public static Object secondControllerID = -1;
|
||||
@Entry(category = VISUAL, name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT;
|
||||
@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");
|
||||
@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 = "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;
|
||||
@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;
|
||||
@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+)\\+?");
|
||||
// Gameplay.
|
||||
// Controller settings
|
||||
@Entry public static double[] maxAnalogValues = new double[]{DEFAULT_MAX_VALUE, DEFAULT_MAX_VALUE, DEFAULT_MAX_VALUE, DEFAULT_MAX_VALUE};
|
||||
@Deprecated @Hidden @Entry public static double[] maxAnalogValues = new double[]{1, 1, 1, 1};
|
||||
@Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = maxAnalogValues[0];
|
||||
@Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = maxAnalogValues[1];
|
||||
@Entry(category = CONTROLLER, name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = maxAnalogValues[2];
|
||||
@Entry(category = CONTROLLER, name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = maxAnalogValues[3];
|
||||
@Entry(category = CONTROLLER, name = "Trigger button fix") public static boolean triggerFix = true;
|
||||
@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 = GAMEPLAY, name = "Enable Hints") public static boolean enableHints = true;
|
||||
@Entry(category = SCREENS, name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true;
|
||||
@Entry(category = MISC, name = "Ring Bindings (WIP)") 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
|
||||
@@ -78,7 +133,6 @@ public class MidnightControlsConfig extends MidnightConfig {
|
||||
MidnightControlsClient.get().log("Configuration loaded.");
|
||||
// Controller controls.
|
||||
InputManager.loadButtonBindings();
|
||||
//this.mod.ring.load(this.config);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,6 +141,16 @@ public class MidnightControlsConfig extends MidnightConfig {
|
||||
public static void save() {
|
||||
MidnightControlsConfig.write("midnightcontrols");
|
||||
MidnightControlsClient.get().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.
|
||||
@@ -95,12 +159,25 @@ public class MidnightControlsConfig extends MidnightConfig {
|
||||
*/
|
||||
public static Controller getController() {
|
||||
var raw = MidnightControlsConfig.controllerID;
|
||||
Controller controller = Controller.byId(GLFW.GLFW_JOYSTICK_1);
|
||||
if (raw instanceof Number) {
|
||||
return Controller.byId(((Number) raw).intValue());
|
||||
controller = Controller.byId(((Number) raw).intValue());
|
||||
} else if (raw instanceof String) {
|
||||
return Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1));
|
||||
controller = Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1));
|
||||
}
|
||||
return 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,14 +234,21 @@ public class MidnightControlsConfig extends MidnightConfig {
|
||||
}
|
||||
|
||||
public static double getAxisMaxValue(int axis) {
|
||||
if (axis >= MidnightControlsConfig.maxAnalogValues.length)
|
||||
return DEFAULT_MAX_VALUE;
|
||||
return MidnightControlsConfig.maxAnalogValues[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) {
|
||||
if (axis < MidnightControlsConfig.maxAnalogValues.length)
|
||||
MidnightControlsConfig.maxAnalogValues[axis] = 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;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +258,7 @@ public class MidnightControlsConfig extends MidnightConfig {
|
||||
*/
|
||||
public static void loadButtonBinding(@NotNull ButtonBinding button) {
|
||||
button.setButton(button.getDefaultButton());
|
||||
var code = MidnightControlsConfig.BINDINGS.getOrDefault("controller.controls." + button.getName(), button.getButtonCode());
|
||||
var code = getBindingsForController().getOrDefault("controller.controls." + button.getName(), button.getButtonCode());
|
||||
|
||||
var matcher = BUTTON_BINDING_PATTERN.matcher(code);
|
||||
|
||||
@@ -198,14 +282,14 @@ public class MidnightControlsConfig extends MidnightConfig {
|
||||
button.setButton(buttons);
|
||||
} catch (Exception e) {
|
||||
MidnightControlsClient.get().warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
||||
MidnightControlsConfig.BINDINGS.put("controller.controls." + button.getName(), button.getButtonCode());
|
||||
setButtonBinding(button, button.getButton());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkValidity(@NotNull ButtonBinding binding, @NotNull String input, String group) {
|
||||
if (group == null) {
|
||||
MidnightControlsClient.get().warn("Malformed config value \"" + input + "\" for binding \"" + binding.getName() + "\".");
|
||||
MidnightControlsConfig.BINDINGS.put("controller.controls." + binding.getName(), binding.getButtonCode());
|
||||
setButtonBinding(binding, binding.getButton());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -219,7 +303,9 @@ public class MidnightControlsConfig extends MidnightConfig {
|
||||
*/
|
||||
public static void setButtonBinding(@NotNull ButtonBinding binding, int[] button) {
|
||||
binding.setButton(button);
|
||||
MidnightControlsConfig.BINDINGS.put("controller.controls." + binding.getName(), binding.getButtonCode());
|
||||
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, int state) {
|
||||
@@ -255,4 +341,70 @@ public class MidnightControlsConfig extends MidnightConfig {
|
||||
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 = 40.0;
|
||||
yAxisRotationSpeed = rotationSpeed;
|
||||
mouseSpeed = 25.0;
|
||||
unfocusedInput = false;
|
||||
virtualMouse = false;
|
||||
virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
|
||||
controllerID = 0;
|
||||
secondControllerID = -1;
|
||||
controllerType = ControllerType.DEFAULT;
|
||||
mouseScreens = Lists.newArrayList("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") && GlDebugInfo.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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,23 +10,29 @@
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget;
|
||||
import org.thinkingstudio.obsidianui.widget.container.SpruceEntryListWidget;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.*;
|
||||
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.gui.TouchscreenOverlay;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.EntryListWidgetAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.*;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
|
||||
import dev.lambdaurora.spruceui.navigation.NavigationDirection;
|
||||
import dev.lambdaurora.spruceui.screen.SpruceScreen;
|
||||
import dev.lambdaurora.spruceui.widget.AbstractSprucePressableButtonWidget;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceElement;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
|
||||
import 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.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.ParentElement;
|
||||
@@ -35,17 +41,14 @@ 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.pack.PackScreen;
|
||||
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
||||
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget;
|
||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
||||
import net.minecraft.client.gui.widget.PressableWidget;
|
||||
import net.minecraft.client.gui.widget.SliderWidget;
|
||||
import net.minecraft.client.gui.widget.*;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.text.TranslatableTextContent;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.aperlambda.lambdacommon.utils.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -53,10 +56,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.glfw.GLFWGamepadState;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
@@ -71,7 +71,9 @@ public class MidnightInput {
|
||||
private static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
||||
// Cooldowns
|
||||
public int actionGuiCooldown = 0;
|
||||
private boolean ignoreNextARelease = false;
|
||||
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;
|
||||
@@ -80,7 +82,8 @@ public class MidnightInput {
|
||||
private int targetMouseY = 0;
|
||||
private float mouseSpeedX = 0.f;
|
||||
private float mouseSpeedY = 0.f;
|
||||
private int inventoryInteractionCooldown = 0;
|
||||
public int inventoryInteractionCooldown = 0;
|
||||
public int screenCloseCooldown = 0;
|
||||
|
||||
private ControllerControlsWidget controlsInput = null;
|
||||
|
||||
@@ -121,10 +124,15 @@ public class MidnightInput {
|
||||
// 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(client, state, false);
|
||||
@@ -137,16 +145,18 @@ public class MidnightInput {
|
||||
this.fetchAxeInput(client, state, true);
|
||||
});
|
||||
|
||||
boolean allowInput = true;
|
||||
|
||||
if (this.controlsInput != null && this.controlsInput.focusedBinding != null)
|
||||
allowInput = false;
|
||||
boolean allowInput = this.controlsInput == null || this.controlsInput.focusedBinding == null;
|
||||
|
||||
if (allowInput)
|
||||
InputManager.updateBindings(client);
|
||||
|
||||
if (this.controlsInput != null
|
||||
&& InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
|
||||
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)) {
|
||||
System.out.println("finished");
|
||||
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++)
|
||||
@@ -173,11 +183,11 @@ public class MidnightInput {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when Minecraft renders.
|
||||
* This method is called to update the camera
|
||||
*
|
||||
* @param client the client instance
|
||||
*/
|
||||
public void onRender(float tickDelta, @NotNull MinecraftClient client) {
|
||||
public void updateCamera(@NotNull MinecraftClient client) {
|
||||
if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
|
||||
return;
|
||||
|
||||
@@ -186,14 +196,17 @@ public class MidnightInput {
|
||||
return;
|
||||
|
||||
if (this.targetYaw != 0.f || this.targetPitch != 0.f) {
|
||||
float rotationYaw = (float) (player.prevYaw + (this.targetYaw / 0.10) * tickDelta);
|
||||
float rotationPitch = (float) (player.prevPitch + (this.targetPitch / 0.10) * tickDelta);
|
||||
float rotationYaw = (float) (client.player.prevYaw + (this.targetYaw * 0.175));
|
||||
float rotationPitch = (float) (client.player.prevPitch + (this.targetPitch * 0.175));
|
||||
client.player.prevYaw = rotationYaw;
|
||||
client.player.prevPitch = 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()) {
|
||||
if (client.player.isRiding() && client.player.getVehicle() != null) {
|
||||
client.player.getVehicle().onPassengerLookAround(client.player);
|
||||
}
|
||||
client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw);
|
||||
MidnightControlsCompat.HANDLERS.forEach(handler -> handler.handleCamera(client, targetYaw, targetPitch));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,23 +260,69 @@ public class MidnightInput {
|
||||
InputManager.STATES.put(btn, state);
|
||||
}
|
||||
}
|
||||
MathUtil.PolarUtil polarLeft = new MathUtil.PolarUtil();
|
||||
MathUtil.PolarUtil polarRight = new MathUtil.PolarUtil();
|
||||
|
||||
private void fetchAxeInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
||||
var buffer = gamepadState.axes();
|
||||
|
||||
polarLeft.calculate(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X), buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y), 1, MidnightControlsConfig.leftDeadZone);
|
||||
float leftX = polarLeft.polarX;
|
||||
float leftY = polarLeft.polarY;
|
||||
polarRight.calculate(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X), buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y), 1, MidnightControlsConfig.rightDeadZone);
|
||||
float rightX = polarRight.polarX;
|
||||
float rightY = polarRight.polarY;
|
||||
|
||||
for (int i = 0; i < buffer.limit(); i++) {
|
||||
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||
float value = buffer.get();
|
||||
|
||||
if (MidnightControlsConfig.analogMovement) {
|
||||
switch (i) {
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_X -> value = leftX;
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_Y -> value = leftY;
|
||||
}
|
||||
}
|
||||
switch (i) {
|
||||
case GLFW_GAMEPAD_AXIS_RIGHT_X -> value = rightX;
|
||||
case GLFW_GAMEPAD_AXIS_RIGHT_Y -> value = rightY;
|
||||
}
|
||||
float absValue = Math.abs(value);
|
||||
|
||||
if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y)
|
||||
value *= -1.0F;
|
||||
|
||||
int state = value > MidnightControlsConfig.rightDeadZone ? 1 : (value < -MidnightControlsConfig.rightDeadZone ? 2 : 0);
|
||||
this.handleAxe(client, axis, value, absValue, state);
|
||||
if (!(client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)))) this.handleAxe(client, axis, value, absValue, state);
|
||||
}
|
||||
if (client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen))) {
|
||||
float x = leftX;
|
||||
float y = leftY;
|
||||
|
||||
if (x == 0 && y == 0) {
|
||||
x = rightX;
|
||||
y = rightY;
|
||||
}
|
||||
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 (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleButton(@NotNull MinecraftClient client, int button, int action, boolean state) {
|
||||
public void handleButton(@NotNull MinecraftClient client, int button, int action, boolean state) {
|
||||
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
||||
if (action == 0 && !this.controlsInput.currentButtons.contains(button)) {
|
||||
this.controlsInput.currentButtons.add(button);
|
||||
@@ -278,16 +337,30 @@ public class MidnightInput {
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == 0 || action == 2) {
|
||||
if (client.currentScreen != null && isScreenInteractive(client.currentScreen)
|
||||
if (client.currentScreen != null && (action == 0 || action == 2) && button == GLFW_GAMEPAD_BUTTON_Y &&
|
||||
MidnightControlsConfig.arrowScreens.contains(client.currentScreen.getClass().getCanonicalName())) {
|
||||
pressKeyboardKey(client, GLFW.GLFW_KEY_ENTER);
|
||||
this.screenCloseCooldown = 5;
|
||||
}
|
||||
else if (action == 0 || action == 2) {
|
||||
if (client.currentScreen != null
|
||||
&& (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN
|
||||
|| button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT)) {
|
||||
if (this.actionGuiCooldown == 0) {
|
||||
if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP) {
|
||||
this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN) {
|
||||
this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||
} else this.handleLeftRight(client.currentScreen, button != GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT);
|
||||
switch (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 (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;
|
||||
}
|
||||
@@ -303,103 +376,73 @@ public class MidnightInput {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.handleInventory(client, button)) {
|
||||
this.ignoreNextARelease = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
|
||||
if (client.currentScreen != null) {
|
||||
if (!MidnightControlsCompat.handleMenuBack(client, client.currentScreen))
|
||||
if (!this.tryGoBack(client.currentScreen))
|
||||
client.currentScreen.onClose();
|
||||
return;
|
||||
else if (FabricLoader.getInstance().isModLoaded("libgui")) LibGuiCompat.handlePress(client.currentScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen)
|
||||
&& this.actionGuiCooldown == 0) {
|
||||
if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt(
|
||||
client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(),
|
||||
client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()) != null) return;
|
||||
if (!this.ignoreNextARelease) {
|
||||
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 (action == 0) {
|
||||
Screen.wrapScreenError(() -> client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1),
|
||||
Screen.wrapScreenError(() -> {
|
||||
((MouseAccessor) client.mouse).setLeftButtonClicked(false);
|
||||
client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1);
|
||||
},
|
||||
"mouseClicked event handler", client.currentScreen.getClass().getCanonicalName());
|
||||
} else if (action == 1) {
|
||||
Screen.wrapScreenError(() -> client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1),
|
||||
Screen.wrapScreenError(() -> {
|
||||
((MouseAccessor) client.mouse).setLeftButtonClicked(false);
|
||||
client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1);
|
||||
},
|
||||
"mouseReleased event handler", client.currentScreen.getClass().getCanonicalName());
|
||||
} else if (action == 2) {
|
||||
Screen.wrapScreenError(() -> {
|
||||
client.currentScreen.setDragging(true);
|
||||
((MouseAccessor) client.mouse).setLeftButtonClicked(true);
|
||||
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), client.mouse.getX(), client.mouse.getY());
|
||||
client.currentScreen.setDragging(false);
|
||||
},
|
||||
"mouseClicked event handler", client.currentScreen.getClass().getCanonicalName());
|
||||
}
|
||||
this.actionGuiCooldown = 5;
|
||||
this.screenCloseCooldown = 5;
|
||||
} else {
|
||||
this.ignoreNextARelease = false;
|
||||
}
|
||||
}
|
||||
else if (button == GLFW.GLFW_GAMEPAD_BUTTON_X && 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.ignoreNextXRelease) {
|
||||
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 (action == 0) {
|
||||
Screen.wrapScreenError(() -> client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2),
|
||||
"mouseClicked event handler", client.currentScreen.getClass().getCanonicalName());
|
||||
} else if (action == 1) {
|
||||
Screen.wrapScreenError(() -> client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2),
|
||||
"mouseReleased event handler", client.currentScreen.getClass().getCanonicalName());
|
||||
}
|
||||
this.screenCloseCooldown = 5;
|
||||
} else {
|
||||
this.ignoreNextXRelease = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Handles inventory interaction.
|
||||
*
|
||||
* @param client the client instance
|
||||
* @param button the button pressed
|
||||
* @return {@code true} if an inventory interaction was done
|
||||
*/
|
||||
private boolean handleInventory(@NotNull MinecraftClient client, int button) {
|
||||
if (!(client.currentScreen instanceof HandledScreen))
|
||||
return false;
|
||||
|
||||
if (client.interactionManager == null || client.player == null)
|
||||
return false;
|
||||
|
||||
if (this.inventoryInteractionCooldown > 0)
|
||||
return true;
|
||||
|
||||
if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
|
||||
client.player.closeHandledScreen();
|
||||
return true;
|
||||
}
|
||||
|
||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||
|
||||
var screen = (HandledScreen) client.currentScreen;
|
||||
var accessor = (HandledScreenAccessor) screen;
|
||||
Slot slot = ((HandledScreenAccessor) client.currentScreen).midnightcontrols$getSlotAt(x, y);
|
||||
|
||||
int slotId;
|
||||
if (slot == null) {
|
||||
if (client.player.currentScreenHandler.getCursorStack().isEmpty())
|
||||
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;
|
||||
switch (button) {
|
||||
case GLFW_GAMEPAD_BUTTON_A:
|
||||
if (screen instanceof CreativeInventoryScreen)
|
||||
if (((CreativeInventoryScreenAccessor) screen).midnightcontrols$isCreativeInventorySlot(slot))
|
||||
actionType = SlotActionType.CLONE;
|
||||
if (slot != null && MidnightControlsCompat.streamCompatHandlers().anyMatch(handler -> handler.isCreativeSlot(screen, slot)))
|
||||
actionType = SlotActionType.CLONE;
|
||||
break;
|
||||
case GLFW.GLFW_GAMEPAD_BUTTON_X:
|
||||
clickData = GLFW_MOUSE_BUTTON_2;
|
||||
break;
|
||||
case GLFW.GLFW_GAMEPAD_BUTTON_Y:
|
||||
actionType = SlotActionType.QUICK_MOVE;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
accessor.midnightcontrols$onMouseClick(slot, slotId, clickData, actionType);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to go back.
|
||||
@@ -409,13 +452,16 @@ public class MidnightInput {
|
||||
*/
|
||||
public boolean tryGoBack(@NotNull Screen screen) {
|
||||
var set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
|
||||
|
||||
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||
.map(element -> (PressableWidget) element)
|
||||
.filter(element -> element.getMessage() instanceof TranslatableText)
|
||||
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
|
||||
.anyMatch(element -> {
|
||||
if (set.stream().anyMatch(key -> key.equals(((TranslatableText) element.getMessage()).getKey()))) {
|
||||
element.onPress();
|
||||
return true;
|
||||
if (element.getMessage().getContent() instanceof TranslatableTextContent translatableText) {
|
||||
if (set.stream().anyMatch(key -> translatableText.getKey().equals(key))) {
|
||||
element.onPress();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@@ -431,13 +477,30 @@ public class MidnightInput {
|
||||
|
||||
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
|
||||
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER)
|
||||
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER))
|
||||
if (asButtonState == 2)
|
||||
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) {
|
||||
if (asButtonState == 2) {
|
||||
asButtonState = 0;
|
||||
}
|
||||
else {
|
||||
// Fixes Triggers not working correctly on some controllers
|
||||
if (MidnightControlsConfig.triggerFix) {
|
||||
value = 1.0f;
|
||||
absValue = 1.0f;
|
||||
state = 1;
|
||||
asButtonState = 1;
|
||||
}
|
||||
//if (MidnightControlsConfig.debug) System.out.println(axis + " "+ value + " " + absValue + " " + state);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
boolean currentPlusState = asButtonState == 1;
|
||||
boolean currentMinusState = asButtonState == 2;
|
||||
boolean currentPlusState = value > getDeadZoneValue(axis);
|
||||
boolean currentMinusState = value < -getDeadZoneValue(axis);
|
||||
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER) currentMinusState = false;
|
||||
if (!MidnightControlsConfig.analogMovement && (axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y)) {
|
||||
currentPlusState = asButtonState == 1;
|
||||
currentMinusState = asButtonState == 2;
|
||||
}
|
||||
var previousPlusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, true), ButtonState.NONE);
|
||||
var previousMinusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, false), ButtonState.NONE);
|
||||
|
||||
@@ -463,9 +526,13 @@ public class MidnightInput {
|
||||
}
|
||||
}
|
||||
|
||||
double deadZone = this.getDeadZoneValue(axis);
|
||||
float axisValue = absValue < deadZone ? 0.f : (float) (absValue - deadZone);
|
||||
axisValue /= (1.0 - deadZone);
|
||||
float axisValue = absValue;
|
||||
if (!MidnightControlsConfig.analogMovement) {
|
||||
double deadZone = this.getDeadZoneValue(axis);
|
||||
axisValue = (float) (absValue - deadZone);
|
||||
axisValue /= (1.0 - deadZone);
|
||||
axisValue *= deadZone;
|
||||
}
|
||||
|
||||
axisValue = (float) Math.min(axisValue / MidnightControlsConfig.getAxisMaxValue(axis), 1);
|
||||
if (currentPlusState)
|
||||
@@ -498,7 +565,23 @@ public class MidnightInput {
|
||||
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
||||
// @TODO allow rebinding to left stick
|
||||
if (accessor.midnightcontrols$hasScrollbar() && absValue >= deadZone) {
|
||||
creativeInventoryScreen.mouseScrolled(0.0, 0.0, -value);
|
||||
creativeInventoryScreen.mouseScrolled(0.0, 0.0, 0, -value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (client.currentScreen instanceof MerchantScreen merchantScreen) {
|
||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||
// @TODO allow rebinding to left stick
|
||||
if (absValue >= deadZone) {
|
||||
merchantScreen.mouseScrolled(0.0, 0.0, 0, -(value * 1.5f));
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (client.currentScreen instanceof StonecutterScreen stonecutterScreen) {
|
||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||
// @TODO allow rebinding to left stick
|
||||
if (absValue >= deadZone) {
|
||||
stonecutterScreen.mouseScrolled(0.0, 0.0, 0, -(value * 1.5f));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -511,10 +594,44 @@ public class MidnightInput {
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (client.currentScreen != null) {
|
||||
float finalValue = value;
|
||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y && absValue >= deadZone && client.currentScreen.children().stream().filter(element -> element instanceof SpruceEntryListWidget)
|
||||
.map(element -> (SpruceEntryListWidget<?>) element)
|
||||
.filter(AbstractSpruceWidget::isFocusedOrHovered)
|
||||
.noneMatch(element -> {
|
||||
element.mouseScrolled(0.0, 0.0, 0, -finalValue);
|
||||
return true;
|
||||
})
|
||||
&&
|
||||
client.currentScreen.children().stream().filter(element -> element instanceof EntryListWidget)
|
||||
.map(element -> (EntryListWidget<?>) element)
|
||||
.filter(element -> element.getType().isFocused())
|
||||
.noneMatch(element -> {
|
||||
element.mouseScrolled(0.0, 0.0, 0, -finalValue);
|
||||
return true;
|
||||
}))
|
||||
{
|
||||
client.currentScreen.mouseScrolled(0.0, 0.0, 0, -(value * 1.5f));
|
||||
}
|
||||
else if (isScreenInteractive(client.currentScreen) && absValue >= deadZone) {
|
||||
if (value > 0 && joystickCooldown == 0) {
|
||||
switch (axis) {
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_Y -> this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_X -> this.handleLeftRight(client.currentScreen, true);
|
||||
}
|
||||
if (axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_X) joystickCooldown = 4;
|
||||
} else if (value < 0 && joystickCooldown == 0) {
|
||||
switch (axis) {
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_Y -> this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||
case GLFW_GAMEPAD_AXIS_LEFT_X -> this.handleLeftRight(client.currentScreen, false);
|
||||
}
|
||||
if (axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_X) joystickCooldown = 4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
absValue -= deadZone;
|
||||
absValue /= (1.0 - deadZone);
|
||||
absValue = (float) MathHelper.clamp(absValue / MidnightControlsConfig.getAxisMaxValue(axis), 0.f, 1.f);
|
||||
if (client.currentScreen == null) {
|
||||
// Handles the look direction.
|
||||
@@ -580,7 +697,7 @@ public class MidnightInput {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
|
||||
public boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
|
||||
if (focused instanceof PressableWidget widget) {
|
||||
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
|
||||
widget.onPress();
|
||||
@@ -593,7 +710,7 @@ public class MidnightInput {
|
||||
labelWidget.onPress();
|
||||
return true;
|
||||
} else if (focused instanceof WorldListWidget list) {
|
||||
list.getSelectedAsOptional().ifPresent(WorldListWidget.Entry::play);
|
||||
list.getSelectedAsOptional().ifPresent(WorldListWidget.WorldEntry::play);
|
||||
return true;
|
||||
} else if (focused instanceof MultiplayerServerListWidget list) {
|
||||
var entry = list.getSelectedOrNull();
|
||||
@@ -609,7 +726,10 @@ public class MidnightInput {
|
||||
var childFocused = widget.getFocused();
|
||||
if (childFocused != null)
|
||||
return this.handleAButton(screen, childFocused);
|
||||
} else if (FabricLoader.getInstance().isModLoaded("yet-another-config-lib") && YACLCompat.handleAButton(screen, focused)) {
|
||||
return true;
|
||||
}
|
||||
else pressKeyboardKey(screen, GLFW_KEY_ENTER);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -625,6 +745,10 @@ public class MidnightInput {
|
||||
this.actionGuiCooldown = 5;
|
||||
return false;
|
||||
}
|
||||
if (FabricLoader.getInstance().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))
|
||||
@@ -639,11 +763,13 @@ public class MidnightInput {
|
||||
return !spruceElement.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
||||
}
|
||||
if (element instanceof SliderWidget slider) {
|
||||
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 false;
|
||||
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;
|
||||
}
|
||||
} else if (element instanceof AlwaysSelectedEntryListWidget) {
|
||||
((EntryListWidgetAccessor) element).midnightcontrols$moveSelection(right ? EntryListWidget.MoveDirection.UP : EntryListWidget.MoveDirection.DOWN);
|
||||
//TODO((EntryListWidgetAccessor) element).midnightcontrols$moveSelection(right ? EntryListWidget.MoveDirection.DOWN : EntryListWidget.MoveDirection.UP);
|
||||
return false;
|
||||
} else if (element instanceof ParentElement entryList) {
|
||||
var focused = entryList.getFocused();
|
||||
@@ -653,6 +779,10 @@ public class MidnightInput {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private double prevX = 0;
|
||||
private double prevY = 0;
|
||||
private double xValue;
|
||||
private int xState;
|
||||
|
||||
/**
|
||||
* Handles the look direction input.
|
||||
@@ -663,14 +793,15 @@ public class MidnightInput {
|
||||
* @param state the state
|
||||
*/
|
||||
public void handleLook(@NotNull MinecraftClient client, int axis, float value, int state) {
|
||||
if (client.player == null) return;
|
||||
// Handles the look direction.
|
||||
if (client.player != null) {
|
||||
if (MidnightControlsConfig.cameraMode == CameraMode.FLAT) {
|
||||
double powValue = Math.pow(value, 2.0);
|
||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||
if (state == 2) {
|
||||
this.targetPitch = -MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
|
||||
this.targetPitch = -MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powValue) * 0.11D;
|
||||
} else if (state == 1) {
|
||||
this.targetPitch = MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
|
||||
this.targetPitch = MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powValue) * 0.11D;
|
||||
}
|
||||
}
|
||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
|
||||
@@ -680,30 +811,69 @@ public class MidnightInput {
|
||||
this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Code below runs for adaptive camera mode
|
||||
|
||||
// Handles the look direction.
|
||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
|
||||
xValue = value;
|
||||
xState = state;
|
||||
return;
|
||||
}
|
||||
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y && client.player != null) {
|
||||
double yStep = (MidnightControlsConfig.yAxisRotationSpeed / 100) * 0.6000000238418579 + 0.20000000298023224;
|
||||
double xStep = (MidnightControlsConfig.rotationSpeed / 100) * 0.6000000238418579 + 0.20000000298023224;
|
||||
|
||||
double cursorDeltaX = 2 * xValue - this.prevX;
|
||||
double cursorDeltaY = 2 * value - this.prevY;
|
||||
boolean slowdown = client.options.getPerspective().isFirstPerson() && 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 (state == 2) {
|
||||
this.targetPitch = -MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powYValue) * 0.11D;
|
||||
} else if (state == 1) {
|
||||
this.targetPitch = MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powYValue) * 0.11D;
|
||||
}
|
||||
|
||||
if (xState == 2) {
|
||||
this.targetYaw = -MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powXValue) * 0.11D;
|
||||
} else if (xState == 1) {
|
||||
this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powXValue) * 0.11D;
|
||||
}
|
||||
|
||||
this.prevY = value;
|
||||
this.prevX = xValue;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean changeFocus(@NotNull Screen screen, NavigationDirection direction) {
|
||||
if (screen instanceof SpruceScreen spruceScreen) {
|
||||
if (spruceScreen.onNavigation(direction, false)) {
|
||||
this.actionGuiCooldown = 5;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!screen.changeFocus(direction.isLookingForward())) {
|
||||
if (screen.changeFocus(direction.isLookingForward())) {
|
||||
this.actionGuiCooldown = 5;
|
||||
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 false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
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 false;
|
||||
}
|
||||
} catch (Exception exception) {MidnightControls.get().warn("Unknown exception encountered while trying to change focus: "+exception);}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isScreenInteractive(@NotNull Screen screen) {
|
||||
return !(screen instanceof AdvancementsScreen || screen instanceof HandledScreen || screen instanceof PackScreen
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FluidBlock;
|
||||
import net.minecraft.block.SlabBlock;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
@@ -73,8 +74,8 @@ public class MidnightReacharound {
|
||||
return MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable();
|
||||
}
|
||||
|
||||
private float getPlayerRange(@NotNull MinecraftClient client) {
|
||||
return client.interactionManager != null ? client.interactionManager.getReachDistance() : 0.f;
|
||||
public static float getPlayerRange(@NotNull MinecraftClient client) {
|
||||
return client.player != null ? Double.valueOf(client.player.getAttributeValue(EntityAttributes.PLAYER_BLOCK_INTERACTION_RANGE)).floatValue() : 0.f;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +102,7 @@ public class MidnightReacharound {
|
||||
BlockPos blockPos = result.getBlockPos().down();
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -120,31 +121,39 @@ public class MidnightReacharound {
|
||||
return null;
|
||||
|
||||
if (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())
|
||||
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) {
|
||||
playerPos = playerPos.up();
|
||||
// Imitates playerPos = playerPos.up();
|
||||
playerPos = playerPosi;
|
||||
this.onSlab = true;
|
||||
} else {
|
||||
this.onSlab = false;
|
||||
}
|
||||
var targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
|
||||
var vector = new BlockPos.Mutable(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
|
||||
var targetPos = new Vec3d(client.crosshairTarget.getPos().getX(), client.crosshairTarget.getPos().getY(), client.crosshairTarget.getPos().getZ()).subtract(playerPos);
|
||||
var vector = new Vec3d(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
|
||||
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 state = client.world.getBlockState(blockPos);
|
||||
var state = client.world.getBlockState(blockyPos);
|
||||
if (!state.isAir())
|
||||
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)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new BlockHitResult(client.crosshairTarget.getPos(), direction, blockPos, false);
|
||||
return new BlockHitResult(blockPos, direction, blockyPos, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2022 Motschen <motschen@midnightdust.eu>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.compat;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import 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.
|
||||
*
|
||||
* @author Motschen
|
||||
* @version 1.7.0
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public class BedrockifyCompat implements CompatHandler {
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull MidnightControlsClient mod) {
|
||||
BedrockifyClient.getInstance().settings.disableFlyingMomentum = false;
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,13 @@ public interface CompatHandler {
|
||||
*/
|
||||
void handle(@NotNull MidnightControlsClient mod);
|
||||
|
||||
/**
|
||||
* Handles custom camera updates
|
||||
*
|
||||
* @param client the Minecraft client instance
|
||||
*/
|
||||
default void handleCamera(@NotNull MinecraftClient client, double targetYaw, double targetPitch) {};
|
||||
|
||||
/**
|
||||
* Returns whether the mouse is required on the specified screen.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package eu.midnightdust.midnightcontrols.client.compat;
|
||||
|
||||
import dev.emi.emi.api.EmiApi;
|
||||
import dev.emi.emi.config.EmiConfig;
|
||||
import dev.emi.emi.screen.EmiScreenManager;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import org.aperlambda.lambdacommon.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
public class EMICompat implements CompatHandler {
|
||||
public static boolean handleTabs(boolean direction) {
|
||||
if (isEMIEnabled() && MidnightControlsClient.get().input.actionGuiCooldown == 0 && EmiScreenManager.getSearchPanel() != null && EmiScreenManager.getSearchPanel().pageLeft != null && EmiScreenManager.getSearchPanel().pageRight != null) {
|
||||
if (direction) EmiScreenManager.getSearchPanel().pageRight.onPress();
|
||||
else EmiScreenManager.getSearchPanel().pageLeft.onPress();
|
||||
MidnightControlsClient.get().input.actionGuiCooldown = 5;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void handle(@NotNull MidnightControlsClient mod) {
|
||||
ButtonCategory category = new ButtonCategory(new Identifier("midnightcontrols","category.emi"));
|
||||
InputManager.registerCategory(category);
|
||||
new ButtonBinding.Builder("emi_page_left")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||
.category(category)
|
||||
.action((client,action,value,buttonState)->handleTabs(false)).cooldown()
|
||||
.filter(((client, buttonBinding) -> EmiApi.getHandledScreen() != null))
|
||||
.register();
|
||||
new ButtonBinding.Builder("emi_page_right")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||
.category(category)
|
||||
.action((client,action,value,buttonState)->handleTabs(true)).cooldown()
|
||||
.filter(((client, buttonBinding) -> EmiApi.getHandledScreen() != null))
|
||||
.register();
|
||||
}
|
||||
public static boolean isEMIEnabled() {
|
||||
return EmiConfig.enabled;
|
||||
}
|
||||
public static boolean isSearchBarCentered() {
|
||||
return EmiConfig.centerSearchBar;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,34 @@
|
||||
/*
|
||||
* 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.compat;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import io.github.kosmx.emotes.arch.gui.EmoteMenuImpl;
|
||||
import io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen;
|
||||
import io.github.kosmx.emotes.main.network.ClientEmotePlay;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
/**
|
||||
* Represents a compatibility handler for Emotecraft.
|
||||
*
|
||||
* @author Motschen
|
||||
* @version 1.4.3
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class EmotecraftCompat implements CompatHandler {
|
||||
@Override
|
||||
public void handle(@NotNull MidnightControlsClient mod) {
|
||||
new ButtonBinding.Builder("key.emotecraft.fastchoose")
|
||||
.buttons(16)
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.action((client, button, value, action) -> {
|
||||
client.setScreen(new FastChosseScreen(null));
|
||||
return true;
|
||||
})
|
||||
.register();
|
||||
new ButtonBinding.Builder("key.emotecraft.stop")
|
||||
.buttons(17)
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.action((client, button, value, action) -> {
|
||||
ClientEmotePlay.clientStopLocalEmote();
|
||||
return true;
|
||||
})
|
||||
.register();
|
||||
public class EmotecraftCompat {
|
||||
private static final MinecraftClient client = MinecraftClient.getInstance();
|
||||
public static void openEmotecraftScreen(Screen parent) {
|
||||
client.setScreen(new EmoteMenuImpl(parent));
|
||||
}
|
||||
public static boolean isEmotecraftScreen(Screen screen) {
|
||||
return screen instanceof FastChosseScreen;
|
||||
}
|
||||
public static void handleEmoteSelector(int index) {
|
||||
|
||||
if (client.currentScreen instanceof FastChosseScreen) {
|
||||
int x = client.getWindow().getWidth() / 2;
|
||||
int y = client.getWindow().getHeight() / 2;
|
||||
if (index == 0) InputManager.queueMousePosition(x-200, y-200);
|
||||
if (index == 1) InputManager.queueMousePosition(x, y-200);
|
||||
if (index == 2) InputManager.queueMousePosition(x+200, y-200);
|
||||
if (index == 3) InputManager.queueMousePosition(x-200, y);
|
||||
if (index == 4) InputManager.queueMousePosition(x+200, y);
|
||||
if (index == 5) InputManager.queueMousePosition(x-200, y+200);
|
||||
if (index == 6) InputManager.queueMousePosition(x, y+200);
|
||||
if (index == 7) InputManager.queueMousePosition(x+200, y+200);
|
||||
|
||||
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package eu.midnightdust.midnightcontrols.client.compat;
|
||||
|
||||
import com.kqp.inventorytabs.tabs.TabManager;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
|
||||
public class InventoryTabsCompat {
|
||||
|
||||
public static void handleInventoryTabs(Screen screen, boolean next) {
|
||||
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
||||
TabManager tabManager = TabManager.getInstance();
|
||||
int tabIndex = tabManager.tabs.indexOf(tabManager.currentTab);
|
||||
if (next) {
|
||||
if (tabIndex < tabManager.tabs.size() - 1) tabManager.onTabClick(tabManager.tabs.get(tabIndex + 1));
|
||||
else tabManager.onTabClick(tabManager.tabs.get(0));
|
||||
} else {
|
||||
if (tabIndex > 0) tabManager.onTabClick(tabManager.tabs.get(tabIndex - 1));
|
||||
else tabManager.onTabClick(tabManager.tabs.get(tabManager.tabs.size() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void handleInventoryPage(Screen screen, boolean next) {
|
||||
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
||||
TabManager tabManager = TabManager.getInstance();
|
||||
if (next) {
|
||||
if (tabManager.canGoForwardAPage()) tabManager.setCurrentPage(tabManager.currentPage + 1);
|
||||
} else {
|
||||
if (tabManager.canGoBackAPage()) tabManager.setCurrentPage(tabManager.currentPage - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package eu.midnightdust.midnightcontrols.client.compat;
|
||||
|
||||
import io.github.cottonmc.cotton.gui.impl.client.CottonScreenImpl;
|
||||
import io.github.cottonmc.cotton.gui.widget.WButton;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.sound.PositionedSoundInstance;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class LibGuiCompat {
|
||||
public static boolean handlePress(@NotNull Screen screen) {
|
||||
if (screen instanceof CottonScreenImpl cottonScreen) {
|
||||
if (cottonScreen.getDescription() != null && cottonScreen.getDescription().getFocus() != null) {
|
||||
if (cottonScreen.getDescription().getFocus() instanceof WButton button && button.getOnClick() != null) {
|
||||
button.getOnClick().run();
|
||||
MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -39,21 +39,23 @@ public class MidnightControlsCompat {
|
||||
* @param mod the mod instance
|
||||
*/
|
||||
public static void init(@NotNull MidnightControlsClient mod) {
|
||||
if (FabricLoader.getInstance().isModLoaded("okzoomer")) {
|
||||
mod.log("Adding okzoomer compatibility...");
|
||||
// "okzoomer" is the mod ID used by Fabric-compatible versions of Ok Zoomer. (5.0.0-beta.6 and below.)
|
||||
// "ok_zoomer" is the mod ID used by Quilt-exclusive versions of Ok Zoomer. (5.0.0-beta.7 and above.)
|
||||
if (FabricLoader.getInstance().isModLoaded("okzoomer") || FabricLoader.getInstance().isModLoaded("ok_zoomer")) {
|
||||
mod.log("Adding Ok Zoomer compatibility...");
|
||||
HANDLERS.add(new OkZoomerCompat());
|
||||
}
|
||||
/*if (isReiPresent()) {
|
||||
mod.log("Adding REI compatiblity...");
|
||||
HANDLERS.add(new ReiCompat());
|
||||
}*/
|
||||
if (isEMIPresent()) {
|
||||
mod.log("Adding EMI compatibility...");
|
||||
HANDLERS.add(new EMICompat());
|
||||
}
|
||||
if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
|
||||
mod.log("Adding HQM compatibility...");
|
||||
HANDLERS.add(new HQMCompat());
|
||||
}
|
||||
if (FabricLoader.getInstance().isModLoaded("emotecraft")) {
|
||||
mod.log("Adding Emotecraft compatibility...");
|
||||
HANDLERS.add(new EmotecraftCompat());
|
||||
if (FabricLoader.getInstance().isModLoaded("bedrockify")) {
|
||||
mod.log("Adding Bedrockify compatibility...");
|
||||
HANDLERS.add(new BedrockifyCompat());
|
||||
}
|
||||
HANDLERS.forEach(handler -> handler.handle(mod));
|
||||
InputManager.loadButtonBindings();
|
||||
@@ -161,4 +163,28 @@ public class MidnightControlsCompat {
|
||||
public static boolean isReiPresent() {
|
||||
return FabricLoader.getInstance().isModLoaded("roughlyenoughitems");
|
||||
}
|
||||
/**
|
||||
* Returns whether EMI is present.
|
||||
*
|
||||
* @return true if EMI is present, else false
|
||||
*/
|
||||
public static boolean isEMIPresent() {
|
||||
return FabricLoader.getInstance().isModLoaded("emi");
|
||||
}
|
||||
/**
|
||||
* 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,6 +9,8 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.compat;
|
||||
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
@@ -21,26 +23,16 @@ import java.util.Set;
|
||||
/**
|
||||
* This plugin is only present for the conditional mixins.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.5.0
|
||||
* @author LambdAurora & Motschen
|
||||
* @version 1.6.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
||||
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>();
|
||||
|
||||
public MidnightControlsMixinPlugin() {
|
||||
this.putConditionalMixin("EntryListWidgetAccessor", MidnightControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("EntryWidgetAccessor", MidnightControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("RecipeViewingScreenAccessor", MidnightControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("VillagerRecipeViewingScreenAccessor", MidnightControlsCompat.isReiPresent());
|
||||
}
|
||||
|
||||
private void putConditionalMixin(@NotNull String path, boolean condition) {
|
||||
this.conditionalMixins.put("eu.midnightdust.midnightcontrols.client.compat.mixin." + path, condition);
|
||||
}
|
||||
private String mixinPackage;
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
this.mixinPackage = mixinPackage + ".";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,7 +42,13 @@ public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
||||
|
||||
@Override
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
* Copyright © 2021-2022 Karen/あけみ <karen@akemi.ai>, LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
* This file is part of MidnightControls.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
@@ -11,49 +11,185 @@ package eu.midnightdust.midnightcontrols.client.compat;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import io.github.ennuil.okzoomer.keybinds.ZoomKeybinds;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Represents a compatibility handler for OkZoomer.
|
||||
* Represents a compatibility handler for Ok Zoomer.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @author Karen/あけみ, LambdAurora
|
||||
* @version 1.4.3
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class OkZoomerCompat implements CompatHandler {
|
||||
private boolean didAllReflectionCallsSucceed = false;
|
||||
|
||||
private KeyBinding okZoomerZoomKey;
|
||||
private KeyBinding okZoomerIncreaseZoomKey;
|
||||
private KeyBinding okZoomerDecreaseZoomKey;
|
||||
private KeyBinding okZoomerResetZoomKey;
|
||||
|
||||
private Method okZoomerAreExtraKeyBindsEnabledMethod;
|
||||
|
||||
public OkZoomerCompat() {
|
||||
// These strings represent the names of the classes, fields, and methods we use from the Ok Zoomer API
|
||||
String okZoomerZoomKeybindsClassString;
|
||||
|
||||
String okZoomerZoomKeyFieldString;
|
||||
String okZoomerIncreaseZoomKeyFieldString;
|
||||
String okZoomerDecreaseZoomKeyFieldString;
|
||||
String okZoomerResetZoomKeyFieldString;
|
||||
|
||||
String okZoomerAreExtraKeyBindsEnabledMethodNameString;
|
||||
|
||||
// These variables represent the actual objects that we reflect to
|
||||
Class<?> okZoomerZoomKeybindsClass;
|
||||
|
||||
Field okZoomerZoomKeyField;
|
||||
Field okZoomerIncreaseZoomKeyField;
|
||||
Field okZoomerDecreaseZoomKeyField;
|
||||
Field okZoomerResetZoomKeyField;
|
||||
|
||||
// First, we need to determine which version of the Ok Zoomer API we're dealing with here.
|
||||
if (LambdaReflection.doesClassExist("io.github.ennuil.okzoomer.keybinds.ZoomKeybinds")) {
|
||||
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.3+1.17.1/src/main/java/io/github/ennuil/okzoomer/keybinds/ZoomKeybinds.java
|
||||
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.3 or below detected!");
|
||||
|
||||
okZoomerZoomKeybindsClassString = "io.github.ennuil.okzoomer.keybinds.ZoomKeybinds";
|
||||
|
||||
okZoomerZoomKeyFieldString = "zoomKey";
|
||||
okZoomerIncreaseZoomKeyFieldString = "increaseZoomKey";
|
||||
okZoomerDecreaseZoomKeyFieldString = "decreaseZoomKey";
|
||||
okZoomerResetZoomKeyFieldString = "resetZoomKey";
|
||||
|
||||
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeybindsEnabled";
|
||||
} else if (LambdaReflection.doesClassExist("io.github.ennuil.okzoomer.key_binds.ZoomKeyBinds")) {
|
||||
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.6+1.18.2/src/main/java/io/github/ennuil/okzoomer/key_binds/ZoomKeyBinds.java
|
||||
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.6, 5.0.0-beta.5, or 5.0.0-beta.4 detected!");
|
||||
|
||||
okZoomerZoomKeybindsClassString = "io.github.ennuil.okzoomer.key_binds.ZoomKeyBinds";
|
||||
|
||||
okZoomerZoomKeyFieldString = "ZOOM_KEY";
|
||||
okZoomerIncreaseZoomKeyFieldString = "INCREASE_ZOOM_KEY";
|
||||
okZoomerDecreaseZoomKeyFieldString = "DECREASE_ZOOM_KEY";
|
||||
okZoomerResetZoomKeyFieldString = "RESET_ZOOM_KEY";
|
||||
|
||||
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeyBindsEnabled";
|
||||
} else if (LambdaReflection.doesClassExist("io.github.ennuil.ok_zoomer.key_binds.ZoomKeyBinds")) {
|
||||
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.7+1.18.2/src/main/java/io/github/ennuil/ok_zoomer/key_binds/ZoomKeyBinds.java
|
||||
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.7 (Quilt) or above detected!");
|
||||
|
||||
okZoomerZoomKeybindsClassString = "io.github.ennuil.ok_zoomer.key_binds.ZoomKeyBinds";
|
||||
|
||||
okZoomerZoomKeyFieldString = "ZOOM_KEY";
|
||||
okZoomerIncreaseZoomKeyFieldString = "INCREASE_ZOOM_KEY";
|
||||
okZoomerDecreaseZoomKeyFieldString = "DECREASE_ZOOM_KEY";
|
||||
okZoomerResetZoomKeyFieldString = "RESET_ZOOM_KEY";
|
||||
|
||||
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeyBindsEnabled";
|
||||
} else {
|
||||
// If all of the above checks fail, then the version of the Ok Zoomer API that the user is trying to use is too new.
|
||||
MidnightControlsClient.get().warn("The version of Ok Zoomer that you are currently using is too new, and is not yet supported by MidnightControls!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Reflect to the ZoomKeyBinds (>= 5.0.0-beta.4) / ZoomKeybinds (<= 5.0.0-beta.3) class.
|
||||
try {
|
||||
okZoomerZoomKeybindsClass = Class.forName(okZoomerZoomKeybindsClassString);
|
||||
} catch (ClassNotFoundException exception) {
|
||||
// This theoretically should never happen.
|
||||
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybinds class!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reflect to all of the keybind fields.
|
||||
try {
|
||||
okZoomerZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerZoomKeyFieldString);
|
||||
okZoomerIncreaseZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerIncreaseZoomKeyFieldString);
|
||||
okZoomerDecreaseZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerDecreaseZoomKeyFieldString);
|
||||
okZoomerResetZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerResetZoomKeyFieldString);
|
||||
} catch (NoSuchFieldException exception) {
|
||||
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybind fields!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialise KeyBinding objects
|
||||
try {
|
||||
okZoomerZoomKey = (KeyBinding) okZoomerZoomKeyField.get(null);
|
||||
okZoomerIncreaseZoomKey = (KeyBinding) okZoomerIncreaseZoomKeyField.get(null);
|
||||
okZoomerDecreaseZoomKey = (KeyBinding) okZoomerDecreaseZoomKeyField.get(null);
|
||||
okZoomerResetZoomKey = (KeyBinding) okZoomerResetZoomKeyField.get(null);
|
||||
} catch (IllegalAccessException exception) {
|
||||
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybind objects!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reflect to the areExtraKeyBindsEnabled (>= 5.0.0-beta.4) / areExtraKeybindsEnabled (<= 5.0.0-beta.3) method.
|
||||
// TODO: Consider replacing this entirely with getExtraKeyBind (>= 5.0.0-beta.4) / getExtraKeybind (<= 5.0.0-beta.3) in the future.
|
||||
try {
|
||||
okZoomerAreExtraKeyBindsEnabledMethod = okZoomerZoomKeybindsClass.getDeclaredMethod(okZoomerAreExtraKeyBindsEnabledMethodNameString);
|
||||
} catch (NoSuchMethodException exception) {
|
||||
MidnightControlsClient.get().warn("MidnightControls failed to reflect to an Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
didAllReflectionCallsSucceed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull MidnightControlsClient mod) {
|
||||
new ButtonBinding.Builder("zoom")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(ZoomKeybinds.zoomKey)
|
||||
.register();
|
||||
if (didAllReflectionCallsSucceed) {
|
||||
new ButtonBinding.Builder("zoom")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(okZoomerZoomKey)
|
||||
.register();
|
||||
|
||||
if (ZoomKeybinds.areExtraKeybindsEnabled()) {
|
||||
new ButtonBinding.Builder("zoom_in")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(ZoomKeybinds.increaseZoomKey)
|
||||
.register();
|
||||
new ButtonBinding.Builder("zoom_out")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(ZoomKeybinds.decreaseZoomKey)
|
||||
.register();
|
||||
new ButtonBinding.Builder("zoom_reset")
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(ZoomKeybinds.resetZoomKey)
|
||||
.register();
|
||||
boolean okZoomerAreExtraKeyBindsEnabled = false;
|
||||
try {
|
||||
okZoomerAreExtraKeyBindsEnabled = (boolean) okZoomerAreExtraKeyBindsEnabledMethod.invoke(null);
|
||||
} catch (IllegalAccessException exception) {
|
||||
MidnightControlsClient.get().warn("MidnightControls encountered an IllegalAccessException while attempting to invoke a reflected Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||
exception.printStackTrace();
|
||||
} catch (InvocationTargetException exception) {
|
||||
MidnightControlsClient.get().warn("MidnightControls encountered an InvocationTargetException while attempting to invoke a reflected Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
if (okZoomerAreExtraKeyBindsEnabled) {
|
||||
new ButtonBinding.Builder("zoom_in")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(okZoomerIncreaseZoomKey)
|
||||
.register();
|
||||
new ButtonBinding.Builder("zoom_out")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(okZoomerDecreaseZoomKey)
|
||||
.register();
|
||||
new ButtonBinding.Builder("zoom_reset")
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(okZoomerResetZoomKey)
|
||||
.register();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,365 +0,0 @@
|
||||
/*
|
||||
* 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.compat;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.mixin.EntryListWidgetAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.mixin.EntryWidgetAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputHandlers;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.PressAction;
|
||||
import me.shedaniel.rei.RoughlyEnoughItemsCoreClient;
|
||||
import me.shedaniel.rei.impl.client.ClientHelperImpl;
|
||||
import me.shedaniel.rei.impl.client.REIRuntimeImpl;
|
||||
import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl;
|
||||
import me.shedaniel.rei.impl.client.gui.screen.CompositeDisplayViewingScreen;
|
||||
import me.shedaniel.rei.impl.client.gui.screen.DefaultDisplayViewingScreen;
|
||||
import me.shedaniel.rei.impl.client.gui.widget.EntryListEntryWidget;
|
||||
import me.shedaniel.rei.impl.client.gui.widget.EntryWidget;
|
||||
import me.shedaniel.rei.impl.client.registry.screen.ScreenRegistryImpl;
|
||||
import me.shedaniel.rei.impl.common.entry.AbstractEntryStack;
|
||||
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.Selectable;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Pair;
|
||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static eu.midnightdust.midnightcontrols.client.compat.CompatHandler.SlotPos.INVALID_SLOT;
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
/**
|
||||
* Represents a compatibility handler for REI.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.7.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class ReiCompat implements CompatHandler {
|
||||
private static EntryListWidget ENTRY_LIST_WIDGET;
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull MidnightControlsClient mod) {
|
||||
/*ButtonBinding.builder(new Identifier("rei", "category_back"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleTab(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "category_next"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleTab(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
ButtonBinding.builder(new Identifier("rei", "page_back"))
|
||||
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, false))
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handlePage(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "page_next"))
|
||||
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, true))
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handlePage(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
ButtonBinding.builder(new Identifier("rei", "recipe_back"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleRecipe(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "recipe_next"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleRecipe(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
// For some reasons this is broken.
|
||||
ButtonBinding.builder(new Identifier("rei", "show_usage"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handleShowRecipeUsage(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
ButtonBinding.builder(new Identifier("rei", "show_recipe"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handleShowRecipeUsage(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
*/
|
||||
}
|
||||
/*
|
||||
|
||||
@Override
|
||||
public boolean requireMouseOnScreen(Screen screen) {
|
||||
return isViewingScreen(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable CompatHandler.SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
|
||||
|
||||
ScreenOverlayImpl overlay = ScreenOverlayImpl.getInstance();
|
||||
if (overlay.isInside(mouseX, mouseY)) {
|
||||
EntryListWidget widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return null;
|
||||
|
||||
return this.getSlotAt(widget, mouseX, mouseY, false);
|
||||
} else if (isViewingScreen(screen)) {
|
||||
for (Element element : screen.children()) {
|
||||
var slot = this.getSlotAt(element, mouseX, mouseY, true);
|
||||
if (slot != null)
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @Nullable CompatHandler.SlotPos getSlotAt(@NotNull Element element, int mouseX, int mouseY, boolean allowEmpty) {
|
||||
if (element instanceof EntryWidget) {
|
||||
EntryWidget entry = (EntryWidget) element;
|
||||
if (entry.containsMouse(mouseX, mouseY)) {
|
||||
if (!allowEmpty && entry.getEntries().isEmpty())
|
||||
return INVALID_SLOT;
|
||||
return new SlotPos(entry.getBounds().getX() + 1, entry.getBounds().getY() + 1);
|
||||
}
|
||||
} else if (element instanceof EntryListWidget) {
|
||||
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
|
||||
for (EntryListEntryWidget entry : entries) {
|
||||
var slot = this.getSlotAt(entry, mouseX, mouseY, allowEmpty);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
}
|
||||
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds widgetWithBounds) {
|
||||
for (var child : widgetWithBounds.children()) {
|
||||
var slot = this.getSlotAt(child, mouseX, mouseY, allowEmpty);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isViewingScreen(Screen screen) {
|
||||
return screen instanceof DefaultDisplayViewingScreen || screen instanceof CompositeDisplayViewingScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
||||
if (!isViewingScreen(screen))
|
||||
return false;
|
||||
|
||||
MinecraftClient.getInstance().setScreen(REIRuntimeImpl.getInstance().getPreviousContainerScreen());
|
||||
REIRuntimeImpl.getInstance().getLastOverlay().init();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static EntryListWidget getEntryListWidget() {
|
||||
if (ENTRY_LIST_WIDGET == null) {
|
||||
ENTRY_LIST_WIDGET = LambdaReflection.getFirstFieldOfType(ContainerScreenOverlay.class, EntryListWidget.class)
|
||||
.map(field -> (EntryListWidget) LambdaReflection.getFieldValue(null, field))
|
||||
.orElse(null);
|
||||
}
|
||||
return ENTRY_LIST_WIDGET;
|
||||
}
|
||||
|
||||
private static @Nullable AbstractEntryStack getCurrentStack(@NotNull MinecraftClient client) {
|
||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||
|
||||
if (isViewingScreen(client.currentScreen)) {
|
||||
for (Element element : client.currentScreen.children()) {
|
||||
EntryStack stack = getCurrentStack(element, x, y);
|
||||
if (stack != null)
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
Optional<ContainerScreenOverlay> overlay = REIRuntimeImpl.getInstance().getOverlay(false,false);
|
||||
if (!overlay.isPresent())
|
||||
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
||||
EntryListWidget widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return ScreenOverlayImpl.getInstance().getInstance().getOverlayMenu()..getScreenFocusedStack(client.currentScreen);
|
||||
|
||||
return getCurrentStack(widget, x, y);
|
||||
}
|
||||
|
||||
private static @Nullable EntryStack getCurrentStack(@NotNull Element element, double mouseX, double mouseY) {
|
||||
if (element instanceof EntryWidget) {
|
||||
EntryWidget entry = (EntryWidget) element;
|
||||
if (entry.containsMouse(mouseX, mouseY))
|
||||
return ((EntryWidgetAccessor) entry).lambdacontrols_getCurrentEntry();
|
||||
} else if (element instanceof EntryListWidget) {
|
||||
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
|
||||
for (EntryListEntryWidget entry : entries) {
|
||||
if (entry.containsMouse(mouseX, mouseY)) {
|
||||
return ((EntryWidgetAccessor) entry).lambdacontrols_getCurrentEntry();
|
||||
}
|
||||
}
|
||||
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds) {
|
||||
for (Element child : ((WidgetWithBounds) element).children()) {
|
||||
EntryStack stack = getCurrentStack(child, mouseX, mouseY);
|
||||
if (stack != null)
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PressAction handleShowRecipeUsage(boolean usage) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action.isUnpressed())
|
||||
return false;
|
||||
|
||||
EntryStack stack = RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
||||
if (stack == null) {
|
||||
stack = getCurrentStack(client);
|
||||
}
|
||||
|
||||
if (stack != null && !stack.isEmpty()) {
|
||||
stack = stack.copy();
|
||||
if (usage) {
|
||||
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addUsagesFor(stack).setInputNotice(stack).fillPreferredOpenedCategory());
|
||||
} else {
|
||||
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addRecipesFor(stack).setOutputNotice(stack).fillPreferredOpenedCategory());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static PressAction handlePage(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action == ButtonState.RELEASE)
|
||||
return false;
|
||||
|
||||
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
|
||||
if (!overlay.isPresent())
|
||||
return false;
|
||||
|
||||
EntryListWidget widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return false;
|
||||
|
||||
if (next)
|
||||
widget.nextPage();
|
||||
else
|
||||
widget.previousPage();
|
||||
widget.updateEntriesPosition();
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handler for category tabs buttons.
|
||||
*
|
||||
* @param next True if the action is to switch to the next tab.
|
||||
* @return The handler.
|
||||
*/
|
||||
/*
|
||||
private static PressAction handleTab(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action != ButtonState.RELEASE)
|
||||
return false;
|
||||
|
||||
if (client.currentScreen instanceof RecipeViewingScreen) {
|
||||
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
|
||||
if (next)
|
||||
screen.getCategoryNext().onClick();
|
||||
else
|
||||
screen.getCategoryBack().onClick();
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof VillagerRecipeViewingScreen) {
|
||||
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
|
||||
List<RecipeCategory<?>> categories = screen.getCategories();
|
||||
int currentTab = screen.getSelectedCategoryIndex();
|
||||
screen.setSelectedCategoryIndex(getNextIndex(currentTab, categories.size(), next));
|
||||
screen.setSelectedRecipeIndex(0);
|
||||
screen.lambdacontrols_init();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static PressAction handleRecipe(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action.isUnpressed())
|
||||
return false;
|
||||
|
||||
if (client.currentScreen instanceof RecipeViewingScreen) {
|
||||
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
|
||||
if (next)
|
||||
screen.getRecipeNext().onClick();
|
||||
else
|
||||
screen.getRecipeBack().onClick();
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof VillagerRecipeViewingScreen) {
|
||||
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
|
||||
List<RecipeCategory<?>> categories = screen.getCategories();
|
||||
int currentTab = screen.getSelectedCategoryIndex();
|
||||
List<RecipeDisplay> recipes = screen.getCategoryMap().get(categories.get(currentTab));
|
||||
|
||||
if (recipes.size() == 0)
|
||||
return true;
|
||||
|
||||
int currentRecipe = screen.getSelectedRecipeIndex();
|
||||
int nextRecipe = getNextIndex(currentRecipe, recipes.size(), next);
|
||||
|
||||
if (nextRecipe == 0) {
|
||||
screen.getScrolling().scrollTo(0.0, true);
|
||||
} else if (nextRecipe == recipes.size() - 1) {
|
||||
screen.getScrolling().scrollTo(screen.getScrolling().getMaxScroll(), true);
|
||||
} else {
|
||||
double scrollAmount = screen.getScrolling().getMaxScroll() / (float) recipes.size();
|
||||
screen.getScrolling().offset(next ? scrollAmount : -scrollAmount, true);
|
||||
}
|
||||
|
||||
screen.setSelectedRecipeIndex(nextRecipe);
|
||||
screen.lambdacontrols_init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static int getNextIndex(int currentIndex, int size, boolean next) {
|
||||
int nextIndex = currentIndex + (next ? 1 : -1);
|
||||
if (nextIndex < 0)
|
||||
nextIndex = size - 1;
|
||||
else if (nextIndex >= size)
|
||||
nextIndex = 0;
|
||||
return nextIndex;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package eu.midnightdust.midnightcontrols.client.compat;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.mixin.sodium.SodiumOptionsGUIAccessor;
|
||||
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
|
||||
public class SodiumCompat {
|
||||
public static void handleTabs(Screen screen, boolean direction) {
|
||||
if (screen instanceof SodiumOptionsGUI optionsGUI) {
|
||||
SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI;
|
||||
final int max = accessor.getPages().size()-1;
|
||||
int i = accessor.getPages().indexOf(accessor.getCurrentPage());
|
||||
i = (direction ? ((max > i) ? ++i : 0) : (i > 0 ? --i : max));
|
||||
if (MidnightControlsConfig.debug) MidnightControls.get().log(""+i);
|
||||
optionsGUI.setPage(accessor.getPages().get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
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 {
|
||||
public static boolean handleAButton(Screen screen, Element element) {
|
||||
if (element instanceof AbstractWidget abstractWidget) {
|
||||
// imitate ender 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;
|
||||
}
|
||||
|
||||
public static boolean handleCategories(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,30 +0,0 @@
|
||||
/*
|
||||
* 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.compat.mixin;
|
||||
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's EntryListWidget.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.5.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Mixin(value = EntryListWidget.class, remap = false)
|
||||
public interface EntryListWidgetAccessor {
|
||||
@Accessor(value = "children")
|
||||
List<Element> getEntries();
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* 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.compat.mixin;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's EntryWidget.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.5.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
//@Mixin(value = EntryWidget.class, remap = false)
|
||||
public interface EntryWidgetAccessor {
|
||||
/*@Invoker("getCurrentEntry")
|
||||
EntryStack midnightcontrols_getCurrentEntry();*/
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.compat.mixin;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's RecipeViewingScreen.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.7.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
//@Mixin(value = DefaultDisplayViewingScreen.class, remap = false)
|
||||
public interface RecipeViewingScreenAccessor {
|
||||
/*@Accessor("categoryBack")
|
||||
Button getCategoryBack();
|
||||
|
||||
@Accessor("categoryNext")
|
||||
Button getCategoryNext();
|
||||
|
||||
@Accessor("recipeBack")
|
||||
Button getRecipeBack();
|
||||
|
||||
@Accessor("recipeNext")
|
||||
Button getRecipeNext();*/
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.compat.mixin;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's VillagerRecipeViewingScreen.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.7.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
//@Mixin(CompositeDisplayViewingScreen.class)
|
||||
public interface VillagerRecipeViewingScreenAccessor {
|
||||
/*@Accessor(value = "categoryMap", remap = false)
|
||||
Map<DisplayCategory<?>, List<Display>> getCategoryMap();
|
||||
|
||||
@Accessor(value = "categories", remap = false)
|
||||
List<DisplayCategory<?>> getCategories();
|
||||
|
||||
@Accessor(value = "selectedCategoryIndex", remap = false)
|
||||
int getSelectedCategoryIndex();
|
||||
|
||||
@Accessor(value = "selectedCategoryIndex", remap = false)
|
||||
void setSelectedCategoryIndex(int selectedCategoryIndex);
|
||||
|
||||
@Accessor(value = "selectedRecipeIndex", remap = false)
|
||||
int getSelectedRecipeIndex();
|
||||
|
||||
@Accessor(value = "selectedRecipeIndex", remap = false)
|
||||
void setSelectedRecipeIndex(int selectedRecipeIndex);
|
||||
|
||||
@Accessor(value = "scrolling", remap = false)
|
||||
ScrollingContainer getScrolling();
|
||||
|
||||
@Invoker("init")
|
||||
void midnightcontrols_init();*/
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package eu.midnightdust.midnightcontrols.client.compat.mixin.sodium;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.OptionPage;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(value = SodiumOptionsGUI.class, remap = false)
|
||||
public interface SodiumOptionsGUIAccessor {
|
||||
@Accessor
|
||||
List<ControlElement<?>> getControls();
|
||||
@Accessor
|
||||
List<OptionPage> getPages();
|
||||
@Accessor
|
||||
OptionPage getCurrentPage();
|
||||
}
|
||||
@@ -9,12 +9,14 @@
|
||||
|
||||
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.gui.RingScreen;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.option.GameOptions;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
||||
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
||||
@@ -44,6 +46,15 @@ public class ButtonBinding {
|
||||
public static final ButtonBinding BACK = new Builder("back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false))
|
||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||
public static final ButtonBinding CHAT = new Builder("chat").buttons(GLFW_GAMEPAD_BUTTON_DPAD_RIGHT).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding CONTROLS_RING = new Builder("controls_ring").buttons(GLFW_GAMEPAD_BUTTON_GUIDE).onlyInGame().cooldown()
|
||||
.action((client, button1, value, action) -> {
|
||||
if (action.isPressed()) {
|
||||
MidnightControlsClient.get().ring.loadFromUnbound();
|
||||
client.setScreen(new RingScreen());
|
||||
}
|
||||
if (action.isUnpressed() && client.currentScreen != null) client.currentScreen.close();
|
||||
return true;
|
||||
}).register();
|
||||
public static final ButtonBinding DROP_ITEM = new Builder("drop_item").buttons(GLFW_GAMEPAD_BUTTON_B).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding FORWARD = new Builder("forward").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true))
|
||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||
@@ -52,6 +63,8 @@ public class ButtonBinding {
|
||||
public static final ButtonBinding HOTBAR_RIGHT = new Builder("hotbar_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||
.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 EXIT = new Builder("exit").buttons(GLFW_GAMEPAD_BUTTON_B).filter((client, buttonBinding) -> client.currentScreen != null && buttonBinding.cooldown == 0 && INVENTORY.cooldown == 0)
|
||||
.action(InputHandlers.handleExit()).cooldown().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))
|
||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||
@@ -62,6 +75,8 @@ public class ButtonBinding {
|
||||
.action(MovementHandler.HANDLER).onlyInGame().register();
|
||||
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
|
||||
.action(InputHandlers::handleScreenshot).cooldown().register();
|
||||
public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B)
|
||||
.action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.inGameHud.getDebugHud().toggleDebugHud(); return true;}).cooldown().register();
|
||||
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
||||
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
|
||||
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
|
||||
@@ -70,16 +85,26 @@ public class ButtonBinding {
|
||||
.action(InputHandlers.handleInventorySlotPad(2)).onlyInInventory().cooldown().register();
|
||||
public static final ButtonBinding SLOT_UP = new Builder("slot_up").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP)
|
||||
.action(InputHandlers.handleInventorySlotPad(0)).onlyInInventory().cooldown().register();
|
||||
public static final ButtonBinding SMOOTH_CAMERA = new Builder("toggle_smooth_camera").onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
||||
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register();
|
||||
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB).onlyInGame().register();
|
||||
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
||||
.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 TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
||||
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown().register();
|
||||
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((client, binding) -> client.currentScreen != null)).cooldown().register();
|
||||
public static final ButtonBinding TAB_RIGHT = new Builder("tab_next").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown().register();
|
||||
public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown().register();
|
||||
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((client, binding) -> client.currentScreen != null)).cooldown().register();
|
||||
public static final ButtonBinding PAGE_LEFT = new Builder("page_back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||
.action(InputHandlers.handlePage(false)).filter(InputHandlers::inInventory).cooldown(30).register();
|
||||
public static final ButtonBinding PAGE_RIGHT = new Builder("page_next").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||
.action(InputHandlers.handlePage(true)).filter(InputHandlers::inInventory).cooldown(30).register();
|
||||
public static final ButtonBinding TAKE = new Builder("take").buttons(GLFW_GAMEPAD_BUTTON_X)
|
||||
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
|
||||
public static final ButtonBinding TAKE_ALL = new Builder("take_all").buttons(GLFW_GAMEPAD_BUTTON_A)
|
||||
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
|
||||
public static final ButtonBinding QUICK_MOVE = new Builder("quick_move").buttons(GLFW_GAMEPAD_BUTTON_Y)
|
||||
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
|
||||
public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").filter(InputHandlers::inGame).buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown().register();
|
||||
public static final ButtonBinding USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register();
|
||||
|
||||
private int[] button;
|
||||
@@ -90,21 +115,34 @@ public class ButtonBinding {
|
||||
protected PairPredicate<MinecraftClient, ButtonBinding> filter;
|
||||
private final List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
|
||||
private boolean hasCooldown;
|
||||
private int cooldownLength = 5;
|
||||
private int cooldown = 0;
|
||||
boolean pressed = false;
|
||||
|
||||
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
||||
this.setButton(this.defaultButton = defaultButton);
|
||||
this.key = key;
|
||||
this.text = new TranslatableText(this.key);
|
||||
this.text = Text.translatable(this.key);
|
||||
this.filter = filter;
|
||||
this.actions.addAll(actions);
|
||||
this.hasCooldown = hasCooldown;
|
||||
}
|
||||
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown, int cooldownLength) {
|
||||
this.setButton(this.defaultButton = defaultButton);
|
||||
this.key = key;
|
||||
this.text = Text.translatable(this.key);
|
||||
this.filter = filter;
|
||||
this.actions.addAll(actions);
|
||||
this.hasCooldown = hasCooldown;
|
||||
this.cooldownLength = cooldownLength;
|
||||
}
|
||||
|
||||
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown) {
|
||||
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown);
|
||||
}
|
||||
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown, int cooldownLength) {
|
||||
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown, cooldownLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the button bound.
|
||||
@@ -221,7 +259,7 @@ public class ButtonBinding {
|
||||
if (state == ButtonState.REPEAT && this.hasCooldown && this.cooldown != 0)
|
||||
return;
|
||||
if (this.hasCooldown && state.isPressed()) {
|
||||
this.cooldown = 5;
|
||||
this.cooldown = cooldownLength;
|
||||
}
|
||||
for (int i = this.actions.size() - 1; i >= 0; i--) {
|
||||
if (this.actions.get(i).press(client, this, value, state))
|
||||
@@ -239,7 +277,7 @@ public class ButtonBinding {
|
||||
* @return the translation key
|
||||
*/
|
||||
public @NotNull String getTranslationKey() {
|
||||
return "midnightcontrols.action." + this.getName();
|
||||
return I18n.hasTranslation("midnightcontrols.action." + this.getName()) ? "midnightcontrols.action." + this.getName() : this.getName();
|
||||
}
|
||||
|
||||
public @NotNull Text getText() {
|
||||
@@ -295,24 +333,23 @@ public class ButtonBinding {
|
||||
}
|
||||
|
||||
public static void init(@NotNull GameOptions options) {
|
||||
ATTACK.mcKeyBinding = options.keyAttack;
|
||||
BACK.mcKeyBinding = options.keyBack;
|
||||
CHAT.mcKeyBinding = options.keyChat;
|
||||
DROP_ITEM.mcKeyBinding = options.keyDrop;
|
||||
FORWARD.mcKeyBinding = options.keyForward;
|
||||
INVENTORY.mcKeyBinding = options.keyInventory;
|
||||
JUMP.mcKeyBinding = options.keyJump;
|
||||
LEFT.mcKeyBinding = options.keyLeft;
|
||||
PICK_BLOCK.mcKeyBinding = options.keyPickItem;
|
||||
PLAYER_LIST.mcKeyBinding = options.keyPlayerList;
|
||||
RIGHT.mcKeyBinding = options.keyRight;
|
||||
SCREENSHOT.mcKeyBinding = options.keyScreenshot;
|
||||
SMOOTH_CAMERA.mcKeyBinding = options.keySmoothCamera;
|
||||
SNEAK.mcKeyBinding = options.keySneak;
|
||||
SPRINT.mcKeyBinding = options.keySprint;
|
||||
SWAP_HANDS.mcKeyBinding = options.keySwapHands;
|
||||
TOGGLE_PERSPECTIVE.mcKeyBinding = options.keyTogglePerspective;
|
||||
USE.mcKeyBinding = options.keyUse;
|
||||
ATTACK.mcKeyBinding = options.attackKey;
|
||||
BACK.mcKeyBinding = options.backKey;
|
||||
CHAT.mcKeyBinding = options.chatKey;
|
||||
DROP_ITEM.mcKeyBinding = options.dropKey;
|
||||
FORWARD.mcKeyBinding = options.forwardKey;
|
||||
INVENTORY.mcKeyBinding = options.inventoryKey;
|
||||
JUMP.mcKeyBinding = options.jumpKey;
|
||||
LEFT.mcKeyBinding = options.leftKey;
|
||||
PICK_BLOCK.mcKeyBinding = options.pickItemKey;
|
||||
PLAYER_LIST.mcKeyBinding = options.playerListKey;
|
||||
RIGHT.mcKeyBinding = options.rightKey;
|
||||
SCREENSHOT.mcKeyBinding = options.screenshotKey;
|
||||
SNEAK.mcKeyBinding = options.sneakKey;
|
||||
SPRINT.mcKeyBinding = options.sprintKey;
|
||||
SWAP_HANDS.mcKeyBinding = options.swapHandsKey;
|
||||
TOGGLE_PERSPECTIVE.mcKeyBinding = options.togglePerspectiveKey;
|
||||
USE.mcKeyBinding = options.useKey;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,37 +360,37 @@ public class ButtonBinding {
|
||||
*/
|
||||
public static @NotNull Text getLocalizedButtonName(int button) {
|
||||
return switch (button % 500) {
|
||||
case -1 -> new TranslatableText("key.keyboard.unknown");
|
||||
case GLFW_GAMEPAD_BUTTON_A -> new TranslatableText("midnightcontrols.button.a");
|
||||
case GLFW_GAMEPAD_BUTTON_B -> new TranslatableText("midnightcontrols.button.b");
|
||||
case GLFW_GAMEPAD_BUTTON_X -> new TranslatableText("midnightcontrols.button.x");
|
||||
case GLFW_GAMEPAD_BUTTON_Y -> new TranslatableText("midnightcontrols.button.y");
|
||||
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER -> new TranslatableText("midnightcontrols.button.left_bumper");
|
||||
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER -> new TranslatableText("midnightcontrols.button.right_bumper");
|
||||
case GLFW_GAMEPAD_BUTTON_BACK -> new TranslatableText("midnightcontrols.button.back");
|
||||
case GLFW_GAMEPAD_BUTTON_START -> new TranslatableText("midnightcontrols.button.start");
|
||||
case GLFW_GAMEPAD_BUTTON_GUIDE -> new TranslatableText("midnightcontrols.button.guide");
|
||||
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB -> new TranslatableText("midnightcontrols.button.left_thumb");
|
||||
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB -> new TranslatableText("midnightcontrols.button.right_thumb");
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> new TranslatableText("midnightcontrols.button.dpad_up");
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> new TranslatableText("midnightcontrols.button.dpad_right");
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> new TranslatableText("midnightcontrols.button.dpad_down");
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> new TranslatableText("midnightcontrols.button.dpad_left");
|
||||
case 100 -> new TranslatableText("midnightcontrols.axis.left_x+");
|
||||
case 101 -> new TranslatableText("midnightcontrols.axis.left_y+");
|
||||
case 102 -> new TranslatableText("midnightcontrols.axis.right_x+");
|
||||
case 103 -> new TranslatableText("midnightcontrols.axis.right_y+");
|
||||
case 104 -> new TranslatableText("midnightcontrols.axis.left_trigger");
|
||||
case 105 -> new TranslatableText("midnightcontrols.axis.right_trigger");
|
||||
case 200 -> new TranslatableText("midnightcontrols.axis.left_x-");
|
||||
case 201 -> new TranslatableText("midnightcontrols.axis.left_y-");
|
||||
case 202 -> new TranslatableText("midnightcontrols.axis.right_x-");
|
||||
case 203 -> new TranslatableText("midnightcontrols.axis.right_y-");
|
||||
case 15 -> new TranslatableText("midnightcontrols.button.l4");
|
||||
case 16 -> new TranslatableText("midnightcontrols.button.l5");
|
||||
case 17 -> new TranslatableText("midnightcontrols.button.r4");
|
||||
case 18 -> new TranslatableText("midnightcontrols.button.r5");
|
||||
default -> new TranslatableText("midnightcontrols.button.unknown", button);
|
||||
case -1 -> Text.translatable("key.keyboard.unknown");
|
||||
case GLFW_GAMEPAD_BUTTON_A -> Text.translatable("midnightcontrols.button.a");
|
||||
case GLFW_GAMEPAD_BUTTON_B -> Text.translatable("midnightcontrols.button.b");
|
||||
case GLFW_GAMEPAD_BUTTON_X -> Text.translatable("midnightcontrols.button.x");
|
||||
case GLFW_GAMEPAD_BUTTON_Y -> Text.translatable("midnightcontrols.button.y");
|
||||
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER -> Text.translatable("midnightcontrols.button.left_bumper");
|
||||
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER -> Text.translatable("midnightcontrols.button.right_bumper");
|
||||
case GLFW_GAMEPAD_BUTTON_BACK -> Text.translatable("midnightcontrols.button.back");
|
||||
case GLFW_GAMEPAD_BUTTON_START -> Text.translatable("midnightcontrols.button.start");
|
||||
case GLFW_GAMEPAD_BUTTON_GUIDE -> Text.translatable("midnightcontrols.button.guide");
|
||||
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB -> Text.translatable("midnightcontrols.button.left_thumb");
|
||||
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB -> Text.translatable("midnightcontrols.button.right_thumb");
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> Text.translatable("midnightcontrols.button.dpad_up");
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> Text.translatable("midnightcontrols.button.dpad_right");
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> Text.translatable("midnightcontrols.button.dpad_down");
|
||||
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> Text.translatable("midnightcontrols.button.dpad_left");
|
||||
case 100 -> Text.translatable("midnightcontrols.axis.left_x+");
|
||||
case 101 -> Text.translatable("midnightcontrols.axis.left_y+");
|
||||
case 102 -> Text.translatable("midnightcontrols.axis.right_x+");
|
||||
case 103 -> Text.translatable("midnightcontrols.axis.right_y+");
|
||||
case 104 -> Text.translatable("midnightcontrols.axis.left_trigger");
|
||||
case 105 -> Text.translatable("midnightcontrols.axis.right_trigger");
|
||||
case 200 -> Text.translatable("midnightcontrols.axis.left_x-");
|
||||
case 201 -> Text.translatable("midnightcontrols.axis.left_y-");
|
||||
case 202 -> Text.translatable("midnightcontrols.axis.right_x-");
|
||||
case 203 -> Text.translatable("midnightcontrols.axis.right_y-");
|
||||
case 15 -> Text.translatable("midnightcontrols.button.l4");
|
||||
case 16 -> Text.translatable("midnightcontrols.button.l5");
|
||||
case 17 -> Text.translatable("midnightcontrols.button.r4");
|
||||
case 18 -> Text.translatable("midnightcontrols.button.r5");
|
||||
default -> Text.translatable("midnightcontrols.button.unknown", button);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -372,18 +409,33 @@ public class ButtonBinding {
|
||||
ButtonBinding.USE
|
||||
));
|
||||
INVENTORY_CATEGORY = InputManager.registerDefaultCategory("key.categories.inventory", category -> category.registerAllBindings(
|
||||
ButtonBinding.EXIT,
|
||||
ButtonBinding.DROP_ITEM,
|
||||
ButtonBinding.HOTBAR_LEFT,
|
||||
ButtonBinding.HOTBAR_RIGHT,
|
||||
ButtonBinding.INVENTORY,
|
||||
ButtonBinding.SWAP_HANDS
|
||||
ButtonBinding.SWAP_HANDS,
|
||||
ButtonBinding.TAB_LEFT,
|
||||
ButtonBinding.TAB_RIGHT,
|
||||
ButtonBinding.PAGE_LEFT,
|
||||
ButtonBinding.PAGE_RIGHT,
|
||||
ButtonBinding.TAKE,
|
||||
ButtonBinding.TAKE_ALL,
|
||||
ButtonBinding.QUICK_MOVE,
|
||||
ButtonBinding.SLOT_UP,
|
||||
ButtonBinding.SLOT_DOWN,
|
||||
ButtonBinding.SLOT_LEFT,
|
||||
ButtonBinding.SLOT_RIGHT
|
||||
));
|
||||
MULTIPLAYER_CATEGORY = InputManager.registerDefaultCategory("key.categories.multiplayer",
|
||||
category -> category.registerAllBindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST));
|
||||
MISC_CATEGORY = InputManager.registerDefaultCategory("key.categories.misc", category -> category.registerAllBindings(
|
||||
ButtonBinding.SCREENSHOT,
|
||||
ButtonBinding.TOGGLE_PERSPECTIVE,
|
||||
ButtonBinding.PAUSE_GAME,
|
||||
//SMOOTH_CAMERA,
|
||||
ButtonBinding.TOGGLE_PERSPECTIVE
|
||||
ButtonBinding.DEBUG_SCREEN,
|
||||
ButtonBinding.CONTROLS_RING
|
||||
));
|
||||
}
|
||||
|
||||
@@ -412,6 +464,7 @@ public class ButtonBinding {
|
||||
private final List<PressAction> actions = new ArrayList<>();
|
||||
private PairPredicate<MinecraftClient, ButtonBinding> filter = Predicates.pairAlwaysTrue();
|
||||
private boolean cooldown = false;
|
||||
private int cooldownLength = 5;
|
||||
private ButtonCategory category = null;
|
||||
private KeyBinding mcBinding = null;
|
||||
|
||||
@@ -426,7 +479,7 @@ public class ButtonBinding {
|
||||
}
|
||||
|
||||
public Builder(@NotNull Identifier identifier) {
|
||||
this(identifier.getNamespace() + "." + identifier.getNamespace());
|
||||
this(identifier.getNamespace() + "." + identifier.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,6 +567,17 @@ public class ButtonBinding {
|
||||
this.cooldown = cooldown;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Sets the cooldown enabled with a custom duration for {@link ButtonBinding}.
|
||||
*
|
||||
* @param cooldownLength duration of {@link ButtonBinding} cooldown
|
||||
* @return the builder instance
|
||||
*/
|
||||
public Builder cooldown(int cooldownLength) {
|
||||
this.cooldownLength = cooldownLength;
|
||||
this.cooldown = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a cooldown on the {@link ButtonBinding}.
|
||||
@@ -553,7 +617,7 @@ public class ButtonBinding {
|
||||
* @return the built {@link ButtonBinding}
|
||||
*/
|
||||
public ButtonBinding build() {
|
||||
var binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown);
|
||||
var binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown, this.cooldownLength);
|
||||
if (this.category != null)
|
||||
this.category.registerBinding(binding);
|
||||
if (this.mcBinding != null)
|
||||
|
||||
@@ -13,9 +13,9 @@ import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.client.toast.SystemToast;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.text.Text;
|
||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -23,7 +23,8 @@ import org.lwjgl.glfw.GLFWGamepadState;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
@@ -31,6 +32,7 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.lwjgl.BufferUtils.createByteBuffer;
|
||||
|
||||
@@ -78,7 +80,7 @@ public record Controller(int id) implements Nameable {
|
||||
* @return the controller's name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
public @NotNull String getName() {
|
||||
var name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
|
||||
return name == null ? String.valueOf(this.id()) : name;
|
||||
}
|
||||
@@ -136,7 +138,7 @@ public record Controller(int id) implements Nameable {
|
||||
}
|
||||
}
|
||||
|
||||
buffer.flip(); // Force Java 8 >.<
|
||||
if (buffer != null) buffer.flip(); // Force Java 8 >.<
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -144,14 +146,22 @@ public record Controller(int id) implements Nameable {
|
||||
* Updates the controller mappings.
|
||||
*/
|
||||
public static void updateMappings() {
|
||||
CompletableFuture.supplyAsync(Controller::updateMappingsSync);
|
||||
}
|
||||
private static boolean updateMappingsSync() {
|
||||
try {
|
||||
if (!MidnightControlsClient.MAPPINGS_FILE.exists())
|
||||
return;
|
||||
MidnightControlsClient.get().log("Updating controller mappings...");
|
||||
Optional<File> databaseFile = getDatabaseFile();
|
||||
if (databaseFile.isPresent()) {
|
||||
var database = ioResourceToBuffer(databaseFile.get().getPath(), 1024);
|
||||
if (database != null) GLFW.glfwUpdateGamepadMappings(database);
|
||||
}
|
||||
if (!MidnightControlsClient.MAPPINGS_FILE.exists())
|
||||
return false;
|
||||
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024);
|
||||
GLFW.glfwUpdateGamepadMappings(buffer);
|
||||
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
e.fillInStackTrace();
|
||||
}
|
||||
|
||||
try (var memoryStack = MemoryStack.stackPush()) {
|
||||
@@ -162,9 +172,10 @@ public record Controller(int id) implements Nameable {
|
||||
var string = l == 0L ? "" : MemoryUtil.memUTF8(l);
|
||||
var client = MinecraftClient.getInstance();
|
||||
if (client != null) {
|
||||
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
|
||||
new TranslatableText("midnightcontrols.controller.mappings.error"), new LiteralText(string)));
|
||||
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
|
||||
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string)));
|
||||
}
|
||||
MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
/* Ignored :concern: */
|
||||
@@ -184,5 +195,21 @@ public record Controller(int id) implements Nameable {
|
||||
controller.isGamepad()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Optional<File> getDatabaseFile() {
|
||||
File databaseFile = new File("config/gamecontrollerdatabase.txt");
|
||||
try {
|
||||
BufferedInputStream in = new BufferedInputStream(new URL("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").openStream());
|
||||
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(databaseFile));
|
||||
byte[] dataBuffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
||||
out.write(dataBuffer, 0, bytesRead);
|
||||
}
|
||||
out.close();
|
||||
} catch (Exception e) {return Optional.empty();}
|
||||
return Optional.of(databaseFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,27 +9,45 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.controller;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
||||
import com.google.common.collect.Lists;
|
||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.RecipeBookWidgetAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.InventoryTabsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.YACLCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.*;
|
||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gl.Framebuffer;
|
||||
import net.minecraft.client.gui.screen.TitleScreen;
|
||||
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.*;
|
||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
||||
import net.minecraft.client.gui.widget.PressableWidget;
|
||||
import net.minecraft.client.gui.widget.TabNavigationWidget;
|
||||
import net.minecraft.client.util.ScreenshotRecorder;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemGroups;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.aperlambda.lambdacommon.utils.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_2;
|
||||
|
||||
/**
|
||||
* Represents some input handlers.
|
||||
@@ -38,49 +56,90 @@ import java.util.stream.Collectors;
|
||||
* @version 1.7.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class InputHandlers {
|
||||
private InputHandlers() {
|
||||
}
|
||||
private static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
||||
return (screen.getItemGroupsOnPage(screen.getCurrentPage()));
|
||||
}
|
||||
|
||||
public static PressAction handleHotbar(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action == ButtonState.RELEASE)
|
||||
return false;
|
||||
|
||||
// When ingame
|
||||
// When in-game
|
||||
if (client.currentScreen == null && client.player != null) {
|
||||
if (next)
|
||||
client.player.getInventory().selectedSlot = client.player.getInventory().selectedSlot == 8 ? 0 : client.player.getInventory().selectedSlot + 1;
|
||||
else
|
||||
client.player.getInventory().selectedSlot = client.player.getInventory().selectedSlot == 0 ? 8 : client.player.getInventory().selectedSlot - 1;
|
||||
if (!client.player.isSpectator()) {
|
||||
if (next)
|
||||
client.player.getInventory().scrollInHotbar(-1.0);
|
||||
else
|
||||
client.player.getInventory().scrollInHotbar(1.0);
|
||||
}
|
||||
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.get().ring.cyclePage(next);
|
||||
} else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) {
|
||||
int currentTab = inventory.getSelectedTab();
|
||||
int nextTab = currentTab + (next ? 1 : -1);
|
||||
if (nextTab < 0)
|
||||
nextTab = ItemGroup.GROUPS.length - 1;
|
||||
else if (nextTab >= ItemGroup.GROUPS.length)
|
||||
nextTab = 0;
|
||||
inventory.midnightcontrols$setSelectedTab(ItemGroup.GROUPS[nextTab]);
|
||||
if (PlatformFunctions.isModLoaded("connectormod")) return true;
|
||||
ItemGroup currentTab = CreativeInventoryScreenAccessor.getSelectedTab();
|
||||
int currentColumn = currentTab.getColumn();
|
||||
ItemGroup.Row currentRow = currentTab.getRow();
|
||||
ItemGroup newTab = null;
|
||||
List<ItemGroup> visibleTabs = 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();
|
||||
inventory.midnightcontrols$setSelectedTab(newTab);
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof InventoryScreen inventoryScreen) {
|
||||
var recipeBook = (RecipeBookWidgetAccessor) inventoryScreen.getRecipeBookWidget();
|
||||
var tabs = recipeBook.getTabButtons();
|
||||
var currentTab = recipeBook.getCurrentTab();
|
||||
if (currentTab == null)
|
||||
} else if (client.currentScreen instanceof InventoryScreen || client.currentScreen instanceof CraftingScreen || client.currentScreen instanceof AbstractFurnaceScreen<?>) {
|
||||
RecipeBookWidget recipeBook;
|
||||
if (client.currentScreen instanceof InventoryScreen inventoryScreen) recipeBook = inventoryScreen.getRecipeBookWidget();
|
||||
else if (client.currentScreen instanceof CraftingScreen craftingScreen) recipeBook = craftingScreen.getRecipeBookWidget();
|
||||
else recipeBook = ((AbstractFurnaceScreen<?>)client.currentScreen).getRecipeBookWidget();
|
||||
var recipeBookAccessor = (RecipeBookWidgetAccessor) recipeBook;
|
||||
var tabs = recipeBookAccessor.getTabButtons();
|
||||
var currentTab = recipeBookAccessor.getCurrentTab();
|
||||
if (currentTab == null || !recipeBook.isOpen()) {
|
||||
if (MidnightControlsCompat.isInventoryTabsPresent()) InventoryTabsCompat.handleInventoryTabs(client.currentScreen, next);
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
recipeBook.setCurrentTab(currentTab = tabs.get(nextTab));
|
||||
recipeBookAccessor.setCurrentTab(currentTab = tabs.get(nextTab));
|
||||
currentTab.setToggled(true);
|
||||
recipeBook.midnightcontrols$refreshResults(true);
|
||||
recipeBookAccessor.midnightcontrols$refreshResults(true);
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof AdvancementsScreenAccessor screen) {
|
||||
var tabs = screen.getTabs().values().stream().distinct().collect(Collectors.toList());
|
||||
var tabs = screen.getTabs().values().stream().distinct().toList();
|
||||
var tab = screen.getSelectedTab();
|
||||
if (tab == null)
|
||||
return false;
|
||||
@@ -91,25 +150,130 @@ public class InputHandlers {
|
||||
nextTab = tabs.size() - 1;
|
||||
else if (nextTab >= tabs.size())
|
||||
nextTab = 0;
|
||||
screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot(), true);
|
||||
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 {
|
||||
if (FabricLoader.getInstance().isModLoaded("sodium"))
|
||||
SodiumCompat.handleTabs(client.currentScreen, next);
|
||||
if (FabricLoader.getInstance().isModLoaded("yet-another-config-lib") && YACLCompat.handleCategories(client.currentScreen, next))
|
||||
return true;
|
||||
}
|
||||
if (MidnightControlsCompat.isInventoryTabsPresent()) InventoryTabsCompat.handleInventoryTabs(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) {
|
||||
try {
|
||||
return client.currentScreen.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) {}
|
||||
}
|
||||
if (MidnightControlsCompat.isInventoryTabsPresent()) InventoryTabsCompat.handleInventoryPage(client.currentScreen, next);
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
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.get().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.get().input.inventoryInteractionCooldown > 0)
|
||||
return true;
|
||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||
|
||||
var accessor = (HandledScreenAccessor) screen;
|
||||
Slot slot = ((HandledScreenAccessor) screen).midnightcontrols$getSlotAt(x, y);
|
||||
|
||||
int slotId;
|
||||
if (slot == null) {
|
||||
if (button.getName().equals("take_all")) {
|
||||
((MouseAccessor) client.mouse).setLeftButtonClicked(true);
|
||||
return false;
|
||||
}
|
||||
slotId = accessor.midnightcontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1;
|
||||
} else {
|
||||
slotId = slot.id;
|
||||
}
|
||||
var actionType = SlotActionType.PICKUP;
|
||||
int clickData = GLFW.GLFW_MOUSE_BUTTON_1;
|
||||
|
||||
MidnightControlsClient.get().input.inventoryInteractionCooldown = 5;
|
||||
switch (button.getName()) {
|
||||
case "take_all" -> {
|
||||
if (screen instanceof CreativeInventoryScreen) {
|
||||
if (slot != null && (((CreativeInventoryScreenAccessor) accessor).midnightcontrols$isCreativeInventorySlot(slot) || MidnightControlsCompat.streamCompatHandlers().anyMatch(handler -> handler.isCreativeSlot(screen, slot))))
|
||||
actionType = SlotActionType.CLONE;
|
||||
}
|
||||
}
|
||||
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.openPauseMenu(false);
|
||||
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.onClose();
|
||||
client.currentScreen.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -131,12 +295,31 @@ public class InputHandlers {
|
||||
|
||||
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||
button.asKeyBinding().ifPresent(binding -> {
|
||||
boolean sneakToggled = client.options.sneakToggled;
|
||||
boolean sneakToggled = client.options.getSneakToggled().getValue();
|
||||
if (client.player.getAbilities().flying && sneakToggled)
|
||||
client.options.sneakToggled = false;
|
||||
client.options.getSneakToggled().setValue(false);
|
||||
else if (MidnightControlsConfig.controllerToggleSneak != sneakToggled)
|
||||
client.options.getSneakToggled().setValue(!sneakToggled);
|
||||
binding.setPressed(button.pressed);
|
||||
if (client.player.getAbilities().flying && sneakToggled)
|
||||
client.options.sneakToggled = true;
|
||||
client.options.getSneakToggled().setValue(true);
|
||||
else if (MidnightControlsConfig.controllerToggleSneak != sneakToggled)
|
||||
client.options.getSneakToggled().setValue(sneakToggled);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
public static boolean handleToggleSprint(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||
button.asKeyBinding().ifPresent(binding -> {
|
||||
boolean sprintToggled = client.options.getSprintToggled().getValue();
|
||||
if (client.player.getAbilities().flying && sprintToggled)
|
||||
client.options.getSprintToggled().setValue(false);
|
||||
else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
|
||||
client.options.getSprintToggled().setValue(!sprintToggled);
|
||||
binding.setPressed(button.pressed);
|
||||
if (client.player.getAbilities().flying && sprintToggled)
|
||||
client.options.getSprintToggled().setValue(true);
|
||||
else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
|
||||
client.options.getSprintToggled().setValue(sprintToggled);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@@ -227,7 +410,7 @@ public class InputHandlers {
|
||||
* @return true if the client is in game, else false
|
||||
*/
|
||||
public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||
return client.currentScreen == null;
|
||||
return (client.currentScreen == null && MidnightControlsClient.get().input.screenCloseCooldown <= 0) || client.currentScreen instanceof TouchscreenOverlay || client.currentScreen instanceof RingScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
package eu.midnightdust.midnightcontrols.client.controller;
|
||||
|
||||
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.util.MouseAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.client.util.InputUtil;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.aperlambda.lambdacommon.Identifier;
|
||||
@@ -26,7 +27,6 @@ import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
@@ -42,15 +42,19 @@ public class InputManager {
|
||||
private static final List<ButtonCategory> CATEGORIES = new ArrayList<>();
|
||||
public static final Int2ObjectMap<ButtonState> STATES = new Int2ObjectOpenHashMap<>();
|
||||
public static final Int2FloatMap BUTTON_VALUES = new Int2FloatOpenHashMap();
|
||||
private int prevTargetMouseX = 0;
|
||||
private int prevTargetMouseY = 0;
|
||||
private int targetMouseX = 0;
|
||||
private int targetMouseY = 0;
|
||||
public int prevTargetMouseX = 0;
|
||||
public int prevTargetMouseY = 0;
|
||||
public int targetMouseX = 0;
|
||||
public int targetMouseY = 0;
|
||||
|
||||
protected InputManager() {
|
||||
}
|
||||
|
||||
public void tick(@NotNull MinecraftClient client) {
|
||||
if (MidnightControlsConfig.autoSwitchMode && !MidnightControlsConfig.isEditing && MidnightControlsConfig.controlsMode != ControlsMode.TOUCHSCREEN)
|
||||
if (MidnightControlsConfig.getController().isConnected() && MidnightControlsConfig.getController().isGamepad())
|
||||
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||
else MidnightControlsConfig.controlsMode = ControlsMode.DEFAULT;
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||
this.controllerTick(client);
|
||||
}
|
||||
@@ -69,8 +73,8 @@ public class InputManager {
|
||||
public void updateMousePosition(@NotNull MinecraftClient client) {
|
||||
Objects.requireNonNull(client, "Client instance cannot be null.");
|
||||
if (this.prevTargetMouseX != this.targetMouseX || this.prevTargetMouseY != this.targetMouseY) {
|
||||
double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getTickDelta() + 0.5;
|
||||
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getTickDelta() + 0.5;
|
||||
double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getRenderTickCounter().getTickDelta(true) + 0.5;
|
||||
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getRenderTickCounter().getTickDelta(true) + 0.5;
|
||||
if (!MidnightControlsConfig.virtualMouse)
|
||||
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
||||
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
||||
@@ -124,6 +128,29 @@ public class InputManager {
|
||||
public static boolean hasBinding(@NotNull Identifier identifier) {
|
||||
return hasBinding(identifier.getNamespace() + "." + identifier.getName());
|
||||
}
|
||||
private static ButtonBinding tempBinding;
|
||||
/**
|
||||
* Returns the binding matching the given string.
|
||||
*
|
||||
* @param name the name of the binding to get
|
||||
* @return true if the binding is registered, else false
|
||||
*/
|
||||
public static ButtonBinding getBinding(@NotNull String name) {
|
||||
if (BINDINGS.parallelStream().map(ButtonBinding::getName).anyMatch(binding -> binding.equalsIgnoreCase(name)))
|
||||
BINDINGS.forEach(binding -> {
|
||||
if (binding.getName().equalsIgnoreCase(name)) InputManager.tempBinding = binding;
|
||||
});
|
||||
return tempBinding;
|
||||
}
|
||||
private static List<ButtonBinding> unboundBindings;
|
||||
public static List<ButtonBinding> getUnboundBindings() {
|
||||
unboundBindings = new ArrayList<>();
|
||||
BINDINGS.forEach(binding -> {
|
||||
if (binding.isNotBound() && !MidnightControlsConfig.ignoredUnboundKeys.contains(binding.getTranslationKey())) unboundBindings.add(binding);
|
||||
});
|
||||
unboundBindings.sort(Comparator.comparing(s -> I18n.translate(s.getTranslationKey())));
|
||||
return unboundBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a button binding.
|
||||
|
||||
@@ -9,12 +9,23 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.controller;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.ButtonState;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.predicate.entity.MovementPredicate;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.apache.commons.lang3.mutable.MutableFloat;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
/**
|
||||
* Represents the movement handler.
|
||||
@@ -30,8 +41,10 @@ public final class MovementHandler implements PressAction {
|
||||
private boolean pressingBack = false;
|
||||
private boolean pressingLeft = false;
|
||||
private boolean pressingRight = false;
|
||||
private float slowdownFactor = 1.f;
|
||||
private float movementForward = 0.f;
|
||||
private float movementSideways = 0.f;
|
||||
private final MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil();
|
||||
|
||||
private MovementHandler() {
|
||||
}
|
||||
@@ -48,8 +61,11 @@ public final class MovementHandler implements PressAction {
|
||||
player.input.pressingBack = this.pressingBack;
|
||||
player.input.pressingLeft = this.pressingLeft;
|
||||
player.input.pressingRight = this.pressingRight;
|
||||
player.input.movementForward = this.movementForward;
|
||||
player.input.movementSideways = this.movementSideways;
|
||||
|
||||
polarUtil.calculate(this.movementSideways, this.movementForward, this.slowdownFactor);
|
||||
player.input.movementForward = polarUtil.polarY;
|
||||
player.input.movementSideways = polarUtil.polarX;
|
||||
|
||||
this.shouldOverrideMovement = false;
|
||||
}
|
||||
|
||||
@@ -69,28 +85,26 @@ public final class MovementHandler implements PressAction {
|
||||
|
||||
this.shouldOverrideMovement = direction != 0;
|
||||
|
||||
if (MidnightControlsConfig.analogMovement) {
|
||||
value = (float) Math.pow(value, 2);
|
||||
} else value = 1.f;
|
||||
if (!MidnightControlsConfig.analogMovement) {
|
||||
value = 1.f;
|
||||
}
|
||||
|
||||
this.slowdownFactor = client.player.shouldSlowDown() ? (MathHelper.clamp(
|
||||
0.3F + (float) client.player.getAttributeValue(EntityAttributes.PLAYER_SNEAKING_SPEED),
|
||||
0.0F,
|
||||
1.0F
|
||||
)) : 1.f;
|
||||
|
||||
if (button == ButtonBinding.FORWARD || button == ButtonBinding.BACK) {
|
||||
// Handle forward movement.
|
||||
this.pressingForward = direction > 0;
|
||||
this.pressingBack = direction < 0;
|
||||
this.movementForward = direction * value;
|
||||
|
||||
// Slowing down if sneaking.
|
||||
if (client.player.input.sneaking)
|
||||
this.movementForward *= 0.3D;
|
||||
} else {
|
||||
// Handle sideways movement.
|
||||
this.pressingLeft = direction > 0;
|
||||
this.pressingRight = direction < 0;
|
||||
this.movementSideways = direction * value;
|
||||
|
||||
// Slowing down if sneaking.
|
||||
if (client.player.input.sneaking)
|
||||
this.movementSideways *= 0.3D;
|
||||
}
|
||||
|
||||
return this.shouldOverrideMovement;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
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 net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.option.StickyKeyBinding;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
package eu.midnightdust.midnightcontrols.client.enums;
|
||||
|
||||
/**
|
||||
* 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,11 +7,9 @@
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
package eu.midnightdust.midnightcontrols.client.enums;
|
||||
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -26,22 +24,23 @@ import java.util.Optional;
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public enum ControllerType implements Nameable {
|
||||
DEFAULT(0, new LiteralText("Default")),
|
||||
DUALSHOCK(1, new LiteralText("Dualshock")),
|
||||
DUALSENSE(2, new LiteralText("Dualsense")),
|
||||
SWITCH(3, new LiteralText("Switch")),
|
||||
XBOX_360(4, new LiteralText("Xbox 360")),
|
||||
XBOX(5, new LiteralText("Xbox")),
|
||||
STEAM_DECK(6, new LiteralText("Steam Deck")),
|
||||
STEAM_CONTROLLER(7, new LiteralText("Steam Controller")),
|
||||
OUYA(8, new LiteralText("Ouya"));
|
||||
DEFAULT(0),
|
||||
DUALSHOCK(1),
|
||||
DUALSENSE(2),
|
||||
SWITCH(3),
|
||||
XBOX_360(4),
|
||||
XBOX(5),
|
||||
STEAM_DECK(6),
|
||||
STEAM_CONTROLLER(7),
|
||||
OUYA(8),
|
||||
NUMBERED(9);
|
||||
|
||||
private final int id;
|
||||
private final Text text;
|
||||
|
||||
ControllerType(int id) {
|
||||
this.id = id;
|
||||
this.text = new TranslatableText("midnightcontrols.controller_type." + this.getName());
|
||||
this.text = Text.translatable("midnightcontrols.controller_type." + this.getName());
|
||||
}
|
||||
|
||||
ControllerType(int id, @NotNull Text text) {
|
||||
@@ -7,10 +7,9 @@
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
package eu.midnightdust.midnightcontrols.client.enums;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -31,7 +30,7 @@ public enum HudSide implements Nameable {
|
||||
private final Text text;
|
||||
|
||||
HudSide() {
|
||||
this.text = new TranslatableText(this.getTranslationKey());
|
||||
this.text = Text.translatable(this.getTranslationKey());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client;
|
||||
package eu.midnightdust.midnightcontrols.client.enums;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -34,7 +33,7 @@ public enum VirtualMouseSkin implements Nameable {
|
||||
|
||||
VirtualMouseSkin(String name) {
|
||||
this.name = name;
|
||||
this.text = new TranslatableText(this.getTranslationKey());
|
||||
this.text = Text.translatable(this.getTranslationKey());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -11,13 +11,12 @@ package eu.midnightdust.midnightcontrols.client.gui;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||
import dev.lambdaurora.spruceui.Position;
|
||||
import dev.lambdaurora.spruceui.option.SpruceOption;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||
import dev.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
|
||||
import org.thinkingstudio.obsidianui.Position;
|
||||
import org.thinkingstudio.obsidianui.option.SpruceOption;
|
||||
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
||||
import org.thinkingstudio.obsidianui.widget.text.SpruceTextAreaWidget;
|
||||
import net.minecraft.client.toast.SystemToast;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
@@ -64,8 +63,8 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
||||
fw.close();
|
||||
} catch (IOException e) {
|
||||
if (this.client != null)
|
||||
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.TUTORIAL_HINT,
|
||||
new TranslatableText("midnightcontrols.controller.mappings.error.write"), LiteralText.EMPTY));
|
||||
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.PERIODIC_NOTIFICATION,
|
||||
Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty()));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -90,7 +89,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
||||
}
|
||||
|
||||
int textFieldWidth = (int) (this.width * (5.0 / 6.0));
|
||||
this.textArea = new SpruceTextAreaWidget(Position.of(this, this.width / 2 - textFieldWidth / 2, 0), textFieldWidth, this.height - 50, new LiteralText(mappings));
|
||||
this.textArea = new SpruceTextAreaWidget(Position.of(this, this.width / 2 - textFieldWidth / 2, 0), textFieldWidth, this.height - 50, Text.literal(mappings));
|
||||
this.textArea.setText(mappings);
|
||||
// Display as many lines as possible
|
||||
this.textArea.setDisplayedLines(this.textArea.getInnerHeight() / this.client.textRenderer.fontHeight);
|
||||
|
||||
@@ -11,14 +11,14 @@ package eu.midnightdust.midnightcontrols.client.gui;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import eu.midnightdust.midnightcontrols.client.HudSide;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import dev.lambdaurora.spruceui.hud.Hud;
|
||||
import org.thinkingstudio.obsidianui.hud.Hud;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.BlockItem;
|
||||
@@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public class MidnightControlsHud extends Hud {
|
||||
private final MidnightControlsClient mod;
|
||||
private MinecraftClient client;
|
||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||
private int attackWidth = 0;
|
||||
private int attackButtonWidth = 0;
|
||||
private int dropItemWidth = 0;
|
||||
@@ -47,22 +47,23 @@ public class MidnightControlsHud extends Hud {
|
||||
private int inventoryButtonWidth = 0;
|
||||
private int swapHandsWidth = 0;
|
||||
private int swapHandsButtonWidth = 0;
|
||||
private boolean showSwapHandsAction = false;
|
||||
private int useWidth = 0;
|
||||
private int useButtonWidth = 0;
|
||||
private BlockHitResult placeHitResult;
|
||||
private String attackAction = "";
|
||||
private String placeAction = "";
|
||||
private int ticksDisplayedCrosshair = 0;
|
||||
private static boolean isCrammed = false;
|
||||
|
||||
public MidnightControlsHud(@NotNull MidnightControlsClient mod) {
|
||||
super(new Identifier(MidnightControlsConstants.NAMESPACE, "hud/button_indicator"));
|
||||
super(Identifier.of(MidnightControlsConstants.NAMESPACE, "hud/button_indicator"));
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(@NotNull MinecraftClient client, int screenWidth, int screenHeight) {
|
||||
super.init(client, screenWidth, screenHeight);
|
||||
this.client = client;
|
||||
this.inventoryWidth = this.width(ButtonBinding.INVENTORY);
|
||||
this.inventoryButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY);
|
||||
this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS);
|
||||
@@ -73,17 +74,23 @@ public class MidnightControlsHud extends Hud {
|
||||
this.useButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.USE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Renders the midnightcontrols' HUD.
|
||||
* Renders the MidnightControls HUD.
|
||||
*/
|
||||
@Override
|
||||
public void render(MatrixStack matrices, float tickDelta) {
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && this.client.currentScreen == null && MidnightControlsConfig.getController().isConnected() && MidnightControlsConfig.getController().isGamepad()) {
|
||||
public void render(DrawContext context, float tickDelta) {
|
||||
if (this.client == null) return;
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && this.client.currentScreen == null) {
|
||||
isCrammed = client.getWindow().getScaledWidth() < 520;
|
||||
int y = bottom(2);
|
||||
this.renderFirstIcons(matrices, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||
this.renderSecondIcons(matrices, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||
this.renderFirstSection(matrices, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||
this.renderSecondSection(matrices, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||
MatrixStack matrices = context.getMatrices();
|
||||
matrices.push();
|
||||
this.renderFirstIcons(context, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||
this.renderSecondIcons(context, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||
this.renderFirstSection(context, MidnightControlsConfig.hudSide == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||
this.renderSecondSection(context, MidnightControlsConfig.hudSide == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
if (this.mod.reacharound.isLastReacharoundVertical()) {
|
||||
@@ -95,86 +102,102 @@ public class MidnightControlsHud extends Hud {
|
||||
scale *= scale;
|
||||
int opacity = ((int) (255 * scale)) << 24;
|
||||
|
||||
this.client.textRenderer.draw(matrices, text, window.getScaledWidth() / 2.f - this.client.textRenderer.getWidth(text) / 2.f,
|
||||
window.getScaledHeight() / 2.f - 4, 0xCCCCCC | opacity);
|
||||
context.drawText(client.textRenderer, text, (int) (window.getScaledWidth() / 2.f - this.client.textRenderer.getWidth(text) / 2.f),
|
||||
(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 currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.inventoryButtonWidth;
|
||||
this.drawButton(matrices, currentX, y, ButtonBinding.INVENTORY, true);
|
||||
this.drawButton(matrices, currentX += (MidnightControlsConfig.hudSide == HudSide.LEFT ? offset : -offset), y, ButtonBinding.SWAP_HANDS, true);
|
||||
if (!ButtonBinding.INVENTORY.isNotBound()) this.drawButton(context, currentX, y, ButtonBinding.INVENTORY, 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;
|
||||
if (this.client.options.showSubtitles && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
||||
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
||||
currentX += -offset;
|
||||
} else {
|
||||
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.dropItemButtonWidth;
|
||||
y -= 24;
|
||||
y -= 20;
|
||||
}
|
||||
this.drawButton(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
||||
if (!ButtonBinding.DROP_ITEM.isNotBound()) 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 currentX = x;
|
||||
if (!this.placeAction.isEmpty()) {
|
||||
if (isCrammed && showSwapHandsAction && !this.client.options.getShowSubtitles().getValue() && !ButtonBinding.SWAP_HANDS.isNotBound()) {
|
||||
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
||||
currentX -= this.useButtonWidth;
|
||||
this.drawButton(matrices, currentX, y, ButtonBinding.USE, true);
|
||||
this.drawButton(context, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
||||
currentX = x;
|
||||
y -= 20;
|
||||
}
|
||||
if (!this.placeAction.isEmpty() && (!ButtonBinding.USE.isNotBound()) ) {
|
||||
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
||||
currentX -= this.useButtonWidth;
|
||||
this.drawButton(context, currentX, y, ButtonBinding.USE, true);
|
||||
offset = 2 + this.useWidth + 4;
|
||||
if (this.client.options.showSubtitles && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||
currentX -= offset;
|
||||
} else {
|
||||
currentX = x;
|
||||
y -= 24;
|
||||
y -= 20;
|
||||
}
|
||||
}
|
||||
|
||||
if (MidnightControlsConfig.hudSide == HudSide.LEFT)
|
||||
currentX -= this.attackButtonWidth;
|
||||
|
||||
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;
|
||||
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
|
||||
: -this.swapHandsWidth - 2 - this.swapHandsButtonWidth - 4;
|
||||
this.drawTip(matrices, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
||||
if (this.client.options.showSubtitles && MidnightControlsConfig.hudSide == HudSide.RIGHT) {
|
||||
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) {
|
||||
currentX += -this.dropItemWidth - 2 - this.dropItemButtonWidth - 4;
|
||||
} else {
|
||||
y -= 24;
|
||||
y -= 20;
|
||||
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x + this.dropItemButtonWidth + 2 : x - this.dropItemButtonWidth - 2 - this.dropItemWidth;
|
||||
}
|
||||
this.drawTip(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
||||
if (!ButtonBinding.DROP_ITEM.isNotBound()) 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;
|
||||
|
||||
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;
|
||||
|
||||
this.drawTip(context, currentX, y, ButtonBinding.SWAP_HANDS, true);
|
||||
|
||||
currentX = x;
|
||||
y -= 20;
|
||||
}
|
||||
if (!this.placeAction.isEmpty()) {
|
||||
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.showSubtitles && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||
if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||
currentX -= 4;
|
||||
} else {
|
||||
currentX = x;
|
||||
y -= 24;
|
||||
y -= 20;
|
||||
}
|
||||
}
|
||||
|
||||
currentX += MidnightControlsConfig.hudSide == HudSide.RIGHT ? this.attackButtonWidth + 2 : -this.attackButtonWidth - 2 - this.attackWidth;
|
||||
|
||||
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
|
||||
public void tick() {
|
||||
if (this.client == null) return;
|
||||
super.tick();
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||
if (this.client.crosshairTarget == null)
|
||||
@@ -231,6 +254,7 @@ public class MidnightControlsHud extends Hud {
|
||||
placeAction = customUseAction;
|
||||
|
||||
this.placeAction = placeAction;
|
||||
this.showSwapHandsAction = !this.client.player.getMainHandStack().isEmpty() || !this.client.player.getOffHandStack().isEmpty();
|
||||
|
||||
// Cache the "Use" tip width.
|
||||
if (this.placeAction.isEmpty())
|
||||
@@ -246,7 +270,7 @@ public class MidnightControlsHud extends Hud {
|
||||
}
|
||||
|
||||
private int bottom(int y) {
|
||||
return this.client.getWindow().getScaledHeight() - y - MidnightControlsRenderer.ICON_SIZE;
|
||||
return (this.client.getWindow().getScaledHeight() - y - MidnightControlsRenderer.ICON_SIZE);
|
||||
}
|
||||
|
||||
private int width(@NotNull ButtonBinding binding) {
|
||||
@@ -259,20 +283,20 @@ public class MidnightControlsHud extends Hud {
|
||||
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)
|
||||
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) {
|
||||
this.drawTip(matrices, x, y, button.getTranslationKey(), display);
|
||||
private void drawTip(DrawContext context, int x, int y, @NotNull ButtonBinding button, boolean 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)
|
||||
return;
|
||||
var translatedAction = I18n.translate(action);
|
||||
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,6 +10,7 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
@@ -18,9 +19,8 @@ import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -75,17 +75,17 @@ public class MidnightControlsRenderer {
|
||||
return width;
|
||||
}
|
||||
|
||||
public static ButtonSize drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client) {
|
||||
return drawButton(matrices, x, y, button.getButton(), client);
|
||||
public static ButtonSize drawButton(DrawContext context, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient 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 length = 0;
|
||||
int currentX = x;
|
||||
for (int i = 0; i < buttons.length; i++) {
|
||||
int btn = buttons[i];
|
||||
int size = drawButton(matrices, currentX, y, btn, client);
|
||||
int size = drawButton(context, currentX, y, btn, client);
|
||||
if (size > height)
|
||||
height = size;
|
||||
length += size;
|
||||
@@ -97,7 +97,7 @@ public class MidnightControlsRenderer {
|
||||
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;
|
||||
if (button == -1)
|
||||
return 0;
|
||||
@@ -106,7 +106,7 @@ public class MidnightControlsRenderer {
|
||||
second = true;
|
||||
}
|
||||
|
||||
int controllerType = MidnightControlsConfig.controllerType.getId();
|
||||
int controllerType = MidnightControlsConfig.controllerType == ControllerType.DEFAULT ? MidnightControlsConfig.matchControllerToType().getId() : MidnightControlsConfig.controllerType.getId();
|
||||
boolean axis = false;
|
||||
int buttonOffset = button * 15;
|
||||
switch (button) {
|
||||
@@ -157,13 +157,13 @@ public class MidnightControlsRenderer {
|
||||
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;
|
||||
|
||||
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(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),
|
||||
assetSize, assetSize,
|
||||
256, 256);
|
||||
@@ -172,18 +172,18 @@ public class MidnightControlsRenderer {
|
||||
return ICON_SIZE;
|
||||
}
|
||||
|
||||
public static int drawButtonTip(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display, @NotNull MinecraftClient client) {
|
||||
return drawButtonTip(matrices, x, y, button.getButton(), button.getTranslationKey(), display, client);
|
||||
public static int drawButtonTip(DrawContext context, int x, int y, @NotNull ButtonBinding button, boolean display, @NotNull MinecraftClient 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) {
|
||||
int buttonWidth = drawButton(matrices, x, y, button, client).length();
|
||||
int buttonWidth = drawButton(context, x, y, button, client).length();
|
||||
|
||||
var translatedAction = I18n.translate(action);
|
||||
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;
|
||||
@@ -193,7 +193,7 @@ public class MidnightControlsRenderer {
|
||||
return 15 + 5 + textRenderer.getWidth(action);
|
||||
}
|
||||
|
||||
public static void renderVirtualCursor(@NotNull MatrixStack matrices, @NotNull MinecraftClient client) {
|
||||
public static void renderVirtualCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
|
||||
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|
||||
|| MidnightInput.isScreenInteractive(client.currentScreen)))
|
||||
return;
|
||||
@@ -231,27 +231,32 @@ public class MidnightControlsRenderer {
|
||||
mouseY -= 8;
|
||||
}
|
||||
|
||||
drawCursor(matrices, mouseX, mouseY, hoverSlot, client);
|
||||
//context.getMatrices().push();
|
||||
context.getMatrices().translate(0f, 0f, 999f);
|
||||
drawCursor(context, mouseX, mouseY, hoverSlot, client);
|
||||
//context.getMatrices().pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the virtual cursor.
|
||||
*
|
||||
* @param matrices the matrix stack
|
||||
* @param context the context
|
||||
* @param x x coordinate
|
||||
* @param y y coordinate
|
||||
* @param hoverSlot true if hovering a slot, else false
|
||||
* @param client the client instance
|
||||
*/
|
||||
public static void drawCursor(@NotNull MatrixStack matrices, int x, int y, boolean hoverSlot, @NotNull MinecraftClient client) {
|
||||
RenderSystem.disableDepthTest();
|
||||
|
||||
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
|
||||
RenderSystem.setShaderTexture(0, MidnightControlsClient.CURSOR_TEXTURE);
|
||||
DrawableHelper.drawTexture(matrices, x, y,
|
||||
public static void drawCursor(@NotNull DrawContext context, int x, int y, boolean hoverSlot, @NotNull MinecraftClient client) {
|
||||
//RenderSystem.disableDepthTest();
|
||||
//RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
|
||||
//RenderSystem.disableBlend();
|
||||
//RenderSystem.setShaderTexture(0, MidnightControlsClient.CURSOR_TEXTURE);
|
||||
context.drawTexture(MidnightControlsClient.CURSOR_TEXTURE, x, y,
|
||||
hoverSlot ? 16.f : 0.f, MidnightControlsConfig.virtualMouseSkin.ordinal() * 16.f,
|
||||
16, 16, 32, 64);
|
||||
RenderSystem.enableDepthTest();
|
||||
context.fill(1, 1, x, y, 0xFFFFFF);
|
||||
context.draw();
|
||||
//RenderSystem.enableDepthTest();
|
||||
}
|
||||
|
||||
public record ButtonSize(int length, int height) {
|
||||
|
||||
@@ -10,37 +10,37 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dev.lambdaurora.spruceui.background.Background;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceWidget;
|
||||
import org.thinkingstudio.obsidianui.background.Background;
|
||||
import org.thinkingstudio.obsidianui.widget.SpruceWidget;
|
||||
import eu.midnightdust.lib.util.MidnightColorUtil;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
||||
import dev.lambdaurora.spruceui.Position;
|
||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||
import dev.lambdaurora.spruceui.option.*;
|
||||
import dev.lambdaurora.spruceui.screen.SpruceScreen;
|
||||
import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceOptionListWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.tabbed.SpruceTabbedWidget;
|
||||
import org.thinkingstudio.obsidianui.Position;
|
||||
import org.thinkingstudio.obsidianui.SpruceTexts;
|
||||
import org.thinkingstudio.obsidianui.option.*;
|
||||
import org.thinkingstudio.obsidianui.screen.SpruceScreen;
|
||||
import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget;
|
||||
import org.thinkingstudio.obsidianui.widget.SpruceLabelWidget;
|
||||
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
||||
import org.thinkingstudio.obsidianui.widget.container.SpruceOptionListWidget;
|
||||
import org.thinkingstudio.obsidianui.widget.container.tabbed.SpruceTabbedWidget;
|
||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePacket;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -49,7 +49,7 @@ import java.awt.*;
|
||||
* Represents the midnightcontrols settings screen.
|
||||
*/
|
||||
public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
private static final Text SDL2_GAMEPAD_TOOL = new LiteralText("SDL2 Gamepad Tool").formatted(Formatting.GREEN);
|
||||
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/";
|
||||
final MidnightControlsClient mod = MidnightControlsClient.get();
|
||||
private final Screen parent;
|
||||
@@ -57,12 +57,21 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
private final SpruceOption inputModeOption;
|
||||
private final SpruceOption autoSwitchModeOption;
|
||||
private final SpruceOption rotationSpeedOption;
|
||||
private final SpruceOption yAxisRotationSpeedOption;
|
||||
private final SpruceOption mouseSpeedOption;
|
||||
private final SpruceOption joystickAsMouseOption;
|
||||
private final SpruceOption eyeTrackingAsMouseOption;
|
||||
private final SpruceOption eyeTrackingDeadzone;
|
||||
private final SpruceOption virtualMouseOption;
|
||||
private final SpruceOption hideCursorOption;
|
||||
private final SpruceOption resetOption;
|
||||
private final SpruceOption advancedConfigOption;
|
||||
// Gameplay options
|
||||
private final SpruceOption analogMovementOption;
|
||||
private final SpruceOption doubleTapToSprintOption;
|
||||
private final SpruceOption autoJumpOption;
|
||||
private final SpruceOption controllerToggleSneakOption;
|
||||
private final SpruceOption controllerToggleSprintOption;
|
||||
private final SpruceOption fastBlockPlacingOption;
|
||||
private final SpruceOption frontBlockPlacingOption;
|
||||
private final SpruceOption verticalReacharoundOption;
|
||||
@@ -73,6 +82,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
private final SpruceOption virtualMouseSkinOption;
|
||||
private final SpruceOption hudEnableOption;
|
||||
private final SpruceOption hudSideOption;
|
||||
private final SpruceOption moveChatOption;
|
||||
// Controller options
|
||||
private final SpruceOption controllerOption =
|
||||
new SpruceCyclingOption("midnightcontrols.menu.controller",
|
||||
@@ -83,16 +93,17 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
id = GLFW.GLFW_JOYSTICK_1;
|
||||
id = searchNextAvailableController(id, false);
|
||||
MidnightControlsConfig.setController(Controller.byId(id));
|
||||
if (MidnightControlsConfig.debug) System.out.println(Controller.byId(id).getName() + "'s Controller GUID: " + Controller.byId(id).getGuid());
|
||||
},
|
||||
option -> {
|
||||
var controller = MidnightControlsConfig.getController();
|
||||
var controllerName = controller.getName();
|
||||
if (!controller.isConnected())
|
||||
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.RED));
|
||||
return option.getDisplayText(Text.literal(controllerName).formatted(Formatting.RED));
|
||||
else if (!controller.isGamepad())
|
||||
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.GOLD));
|
||||
return option.getDisplayText(Text.literal(controllerName).formatted(Formatting.GOLD));
|
||||
else
|
||||
return option.getDisplayText(new LiteralText(controllerName));
|
||||
return option.getDisplayText(Text.literal(controllerName));
|
||||
}, null);
|
||||
private final SpruceOption secondControllerOption = new SpruceCyclingOption("midnightcontrols.menu.controller2",
|
||||
amount -> {
|
||||
@@ -106,16 +117,18 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
option -> MidnightControlsConfig.getSecondController().map(controller -> {
|
||||
var controllerName = controller.getName();
|
||||
if (!controller.isConnected())
|
||||
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.RED));
|
||||
return option.getDisplayText(Text.literal(controllerName).formatted(Formatting.RED));
|
||||
else if (!controller.isGamepad())
|
||||
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.GOLD));
|
||||
return option.getDisplayText(Text.literal(controllerName).formatted(Formatting.GOLD));
|
||||
else
|
||||
return option.getDisplayText(new LiteralText(controllerName));
|
||||
}).orElse(option.getDisplayText(SpruceTexts.OPTIONS_OFF.shallowCopy().formatted(Formatting.RED))),
|
||||
new TranslatableText("midnightcontrols.tooltip.controller2"));
|
||||
return option.getDisplayText(Text.literal(controllerName));
|
||||
}).orElse(option.getDisplayText(SpruceTexts.OPTIONS_OFF.copyContentOnly().formatted(Formatting.RED))),
|
||||
Text.translatable("midnightcontrols.menu.controller2.tooltip"));
|
||||
private final SpruceOption unfocusedInputOption;
|
||||
private final SpruceOption invertsRightXAxis;
|
||||
private final SpruceOption invertsRightYAxis;
|
||||
private final SpruceOption cameraModeOption;
|
||||
private final SpruceOption toggleControllerProfileOption;
|
||||
private final SpruceOption rightDeadZoneOption;
|
||||
private final SpruceOption leftDeadZoneOption;
|
||||
private final SpruceOption[] maxAnalogValueOptions = new SpruceOption[]{
|
||||
@@ -129,13 +142,20 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
return new SpruceDoubleOption(key, .25f, 1.f, 0.05f,
|
||||
() -> MidnightControlsConfig.getAxisMaxValue(axis),
|
||||
newValue -> MidnightControlsConfig.setAxisMaxValue(axis, newValue),
|
||||
option -> option.getDisplayText(new LiteralText(String.format("%.2f", option.get()))),
|
||||
new TranslatableText(key.replace("menu", "tooltip"))
|
||||
option -> option.getDisplayText(Text.literal(String.format("%.2f", option.get()))),
|
||||
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 = new LiteralText("(")
|
||||
.append(new LiteralText(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
|
||||
private final MutableText controllerMappingsUrlText = Text.literal("(")
|
||||
.append(Text.literal(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
|
||||
.append("),");
|
||||
|
||||
private static int searchNextAvailableController(int newId, boolean allowNone) {
|
||||
@@ -153,7 +173,8 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
}
|
||||
|
||||
public MidnightControlsSettingsScreen(Screen parent, boolean hideControls) {
|
||||
super(new TranslatableText("midnightcontrols.title.settings"));
|
||||
super(Text.translatable("midnightcontrols.title.settings"));
|
||||
MidnightControlsConfig.isEditing = true;
|
||||
this.parent = parent;
|
||||
// General options
|
||||
this.inputModeOption = new SpruceCyclingOption("midnightcontrols.menu.controls_mode",
|
||||
@@ -162,93 +183,156 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
MidnightControlsConfig.controlsMode = next;
|
||||
MidnightControlsConfig.save();
|
||||
|
||||
if (this.client.player != null) {
|
||||
ClientPlayNetworking.getSender().sendPacket(MidnightControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next));
|
||||
if (this.client != null && this.client.player != null) {
|
||||
ClientPlayNetworking.getSender().sendPacket(new ControlsModePacket(next.getName()));
|
||||
}
|
||||
}, option -> option.getDisplayText(new TranslatableText(MidnightControlsConfig.controlsMode.getTranslationKey())),
|
||||
new TranslatableText("midnightcontrols.tooltip.controlsMidnightColorUtil.radialRainbow(1f,1f);_mode"));
|
||||
}, option -> option.getDisplayText(Text.translatable(MidnightControlsConfig.controlsMode.getTranslationKey())),
|
||||
Text.translatable("midnightcontrols.menu.controls_mode.tooltip"));
|
||||
this.autoSwitchModeOption = new SpruceToggleBooleanOption("midnightcontrols.menu.auto_switch_mode", () -> MidnightControlsConfig.autoSwitchMode,
|
||||
value -> MidnightControlsConfig.autoSwitchMode = value, new TranslatableText("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,
|
||||
() -> MidnightControlsConfig.rotationSpeed,
|
||||
value -> MidnightControlsConfig.rotationSpeed = value, option -> option.getDisplayText(new LiteralText(String.valueOf(option.get()))),
|
||||
new TranslatableText("midnightcontrols.tooltip.rotation_speed"));
|
||||
value -> MidnightControlsConfig.rotationSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||
Text.translatable("midnightcontrols.menu.rotation_speed.tooltip"));
|
||||
this.yAxisRotationSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.y_axis_rotation_speed", 0.0, 100.0, .5f,
|
||||
() -> MidnightControlsConfig.yAxisRotationSpeed,
|
||||
value -> MidnightControlsConfig.yAxisRotationSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||
Text.translatable("midnightcontrols.menu.y_axis_rotation_speed.tooltip"));
|
||||
this.mouseSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.mouse_speed", 0.0, 150.0, .5f,
|
||||
() -> MidnightControlsConfig.mouseSpeed,
|
||||
value -> MidnightControlsConfig.mouseSpeed = value, option -> option.getDisplayText(new LiteralText(String.valueOf(option.get()))),
|
||||
new TranslatableText("midnightcontrols.tooltip.mouse_speed"));
|
||||
value -> MidnightControlsConfig.mouseSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
|
||||
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 -> {
|
||||
// TODO
|
||||
MidnightControlsConfig.init("midnightcontrols", MidnightControlsConfig.class);
|
||||
MidnightControlsConfig.reset();
|
||||
var client = MinecraftClient.getInstance();
|
||||
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||
});
|
||||
this.advancedConfigOption = SpruceSimpleActionOption.of("midnightcontrols.midnightconfig.title", button -> client.setScreen(MidnightControlsConfig.getScreen(this, "midnightcontrols")));
|
||||
// Gameplay options
|
||||
this.analogMovementOption = new SpruceToggleBooleanOption("midnightcontrols.menu.analog_movement",
|
||||
() -> MidnightControlsConfig.analogMovement, value -> MidnightControlsConfig.analogMovement = value,
|
||||
new TranslatableText("midnightcontrols.tooltip.analog_movement"));
|
||||
Text.translatable("midnightcontrols.menu.analog_movement.tooltip"));
|
||||
this.doubleTapToSprintOption = new SpruceToggleBooleanOption("midnightcontrols.menu.double_tap_to_sprint",
|
||||
() -> MidnightControlsConfig.doubleTapToSprint, value -> MidnightControlsConfig.doubleTapToSprint = value,
|
||||
Text.translatable("midnightcontrols.menu.double_tap_to_sprint.tooltip"));
|
||||
this.autoJumpOption = new SpruceToggleBooleanOption("options.autoJump",
|
||||
() -> this.client.options.autoJump,
|
||||
newValue -> this.client.options.autoJump = newValue,
|
||||
() -> this.client.options.getAutoJump().getValue(),
|
||||
newValue -> this.client.options.getAutoJump().setValue(newValue),
|
||||
null);
|
||||
this.controllerToggleSneakOption = new SpruceToggleBooleanOption("midnightcontrols.menu.controller_toggle_sneak",
|
||||
() -> MidnightControlsConfig.controllerToggleSneak, value -> MidnightControlsConfig.controllerToggleSneak = value,
|
||||
null);
|
||||
this.controllerToggleSprintOption = new SpruceToggleBooleanOption("midnightcontrols.menu.controller_toggle_sprint",
|
||||
() -> MidnightControlsConfig.controllerToggleSprint, value -> MidnightControlsConfig.controllerToggleSprint = value,
|
||||
null);
|
||||
this.fastBlockPlacingOption = new SpruceToggleBooleanOption("midnightcontrols.menu.fast_block_placing", () -> MidnightControlsConfig.fastBlockPlacing,
|
||||
value -> MidnightControlsConfig.fastBlockPlacing = value, new TranslatableText("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,
|
||||
value -> MidnightControlsConfig.horizontalReacharound = value, new TranslatableText("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,
|
||||
value -> MidnightControlsConfig.verticalReacharound = value, new TranslatableText("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,
|
||||
value -> MidnightControlsConfig.flyDrifting = value, new TranslatableText("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,
|
||||
value -> MidnightControlsConfig.verticalFlyDrifting = value, new TranslatableText("midnightcontrols.tooltip.fly_drifting_vertical"));
|
||||
value -> MidnightControlsConfig.verticalFlyDrifting = value, Text.translatable("midnightcontrols.menu.fly_drifting_vertical.tooltip"));
|
||||
// Appearance options
|
||||
this.controllerTypeOption = new SpruceCyclingOption("midnightcontrols.menu.controller_type",
|
||||
amount -> MidnightControlsConfig.controllerType = MidnightControlsConfig.controllerType.next(),
|
||||
option -> option.getDisplayText(MidnightControlsConfig.controllerType.getTranslatedText()),
|
||||
new TranslatableText("midnightcontrols.tooltip.controller_type"));
|
||||
Text.translatable("midnightcontrols.menu.controller_type.tooltip"));
|
||||
this.virtualMouseSkinOption = new SpruceCyclingOption("midnightcontrols.menu.virtual_mouse.skin",
|
||||
amount -> MidnightControlsConfig.virtualMouseSkin = MidnightControlsConfig.virtualMouseSkin.next(),
|
||||
option -> option.getDisplayText(MidnightControlsConfig.virtualMouseSkin.getTranslatedText()),
|
||||
null);
|
||||
this.hudEnableOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hud_enable", () -> MidnightControlsConfig.hudEnable,
|
||||
this.mod::setHudEnabled, new TranslatableText("midnightcontrols.tooltip.hud_enable"));
|
||||
this.mod::setHudEnabled, Text.translatable("midnightcontrols.menu.hud_enable.tooltip"));
|
||||
this.hudSideOption = new SpruceCyclingOption("midnightcontrols.menu.hud_side",
|
||||
amount -> MidnightControlsConfig.hudSide = MidnightControlsConfig.hudSide.next(),
|
||||
option -> option.getDisplayText(MidnightControlsConfig.hudSide.getTranslatedText()),
|
||||
new TranslatableText("midnightcontrols.tooltip.hud_side"));
|
||||
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
|
||||
this.toggleControllerProfileOption = new SpruceToggleBooleanOption("midnightcontrols.menu.separate_controller_profile", () -> MidnightControlsConfig.controllerBindingProfiles.containsKey(MidnightControlsConfig.getController().getGuid()), value -> {
|
||||
if (value) {
|
||||
MidnightControlsConfig.controllerBindingProfiles.put(MidnightControlsConfig.getController().getGuid(), MidnightControlsConfig.getBindingsForController());
|
||||
MidnightControlsConfig.updateBindingsForController(MidnightControlsConfig.getController());
|
||||
} else {
|
||||
MidnightControlsConfig.controllerBindingProfiles.remove(MidnightControlsConfig.getController().getGuid());
|
||||
MidnightControlsConfig.updateBindingsForController(MidnightControlsConfig.getController());
|
||||
}
|
||||
|
||||
}, Text.translatable(""));
|
||||
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,
|
||||
() -> MidnightControlsConfig.rightDeadZone,
|
||||
value -> MidnightControlsConfig.rightDeadZone = value, option -> {
|
||||
var value = String.valueOf(option.get());
|
||||
return option.getDisplayText(new LiteralText(value.substring(0, Math.min(value.length(), 5))));
|
||||
}, new TranslatableText("midnightcontrols.tooltip.right_dead_zone"));
|
||||
return option.getDisplayText(Text.literal(value.substring(0, Math.min(value.length(), 5))));
|
||||
}, Text.translatable("midnightcontrols.menu.right_dead_zone.tooltip"));
|
||||
this.leftDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.left_dead_zone", 0.05, 1.0, .05f,
|
||||
() -> MidnightControlsConfig.leftDeadZone,
|
||||
value -> MidnightControlsConfig.leftDeadZone = value, option -> {
|
||||
var value = String.valueOf(option.get());
|
||||
return option.getDisplayText(new LiteralText(value.substring(0, Math.min(value.length(), 5))));
|
||||
}, new TranslatableText("midnightcontrols.tooltip.left_dead_zone"));
|
||||
return option.getDisplayText(Text.literal(value.substring(0, Math.min(value.length(), 5))));
|
||||
}, Text.translatable("midnightcontrols.menu.left_dead_zone.tooltip"));
|
||||
this.invertsRightXAxis = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_right_x_axis", () -> MidnightControlsConfig.invertRightXAxis,
|
||||
value -> MidnightControlsConfig.invertRightXAxis = value, null);
|
||||
this.invertsRightYAxis = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_right_y_axis", () -> MidnightControlsConfig.invertRightYAxis,
|
||||
value -> MidnightControlsConfig.invertRightYAxis = value, null);
|
||||
this.unfocusedInputOption = new SpruceToggleBooleanOption("midnightcontrols.menu.unfocused_input", () -> MidnightControlsConfig.unfocusedInput,
|
||||
value -> MidnightControlsConfig.unfocusedInput = value, new TranslatableText("midnightcontrols.tooltip.unfocused_input"));
|
||||
value -> MidnightControlsConfig.unfocusedInput = value, Text.translatable("midnightcontrols.menu.unfocused_input.tooltip"));
|
||||
this.virtualMouseOption = new SpruceToggleBooleanOption("midnightcontrols.menu.virtual_mouse", () -> MidnightControlsConfig.virtualMouse,
|
||||
value -> MidnightControlsConfig.virtualMouse = value, new TranslatableText("midnightcontrols.tooltip.virtual_mouse"));
|
||||
value -> MidnightControlsConfig.virtualMouse = value, Text.translatable("midnightcontrols.menu.virtual_mouse.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
|
||||
public void removed() {
|
||||
MidnightControlsConfig.isEditing = false;
|
||||
MidnightControlsConfig.save();
|
||||
super.removed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
public void close() {
|
||||
MidnightControlsConfig.isEditing = false;
|
||||
MidnightControlsConfig.save();
|
||||
super.onClose();
|
||||
super.close();
|
||||
}
|
||||
|
||||
private int getTextHeight() {
|
||||
@@ -262,8 +346,8 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
this.buildTabs();
|
||||
|
||||
this.addDrawableChild(this.resetOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 150));
|
||||
this.addDrawableChild(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, 20, SpruceTexts.GUI_DONE,
|
||||
btn -> this.client.setScreen(this.parent)));
|
||||
this.addDrawableChild(ButtonWidget.builder(SpruceTexts.GUI_DONE, btn -> this.client.setScreen(this.parent))
|
||||
.dimensions(this.width / 2 - 155 + 160, this.height - 29, 150, 20).build());
|
||||
}
|
||||
|
||||
public void buildTabs() {
|
||||
@@ -273,54 +357,68 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
tabs.getList().setBackground(new MidnightControlsBackground());
|
||||
this.addDrawableChild(tabs);
|
||||
|
||||
tabs.addSeparatorEntry(new TranslatableText("midnightcontrols.menu.separator.general"));
|
||||
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.general"), null,
|
||||
tabs.addSeparatorEntry(Text.translatable("midnightcontrols.menu.separator.general"));
|
||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.general"), null,
|
||||
this::buildGeneralTab);
|
||||
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.gameplay"), null,
|
||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.gameplay"), null,
|
||||
this::buildGameplayTab);
|
||||
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.visual"), null,
|
||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.visual"), null,
|
||||
this::buildVisualTab);
|
||||
|
||||
tabs.addSeparatorEntry(new TranslatableText("options.controls"));
|
||||
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.controller_controls"), null,
|
||||
tabs.addSeparatorEntry(Text.translatable("options.controls"));
|
||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.controller_controls"), null,
|
||||
this::buildControllerControlsTab);
|
||||
|
||||
tabs.addSeparatorEntry(new TranslatableText("midnightcontrols.menu.separator.controller"));
|
||||
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.controller"), null,
|
||||
tabs.addSeparatorEntry(Text.translatable("midnightcontrols.menu.separator.controller"));
|
||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.controller"), null,
|
||||
this::buildControllerTab);
|
||||
tabs.addTabEntry(new TranslatableText("midnightcontrols.menu.title.mappings.string"), null,
|
||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.touch"), null,
|
||||
this::buildTouchTab);
|
||||
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.mappings.string"), null,
|
||||
this::buildMappingsStringEditorTab);
|
||||
}
|
||||
|
||||
public SpruceOptionListWidget buildGeneralTab(int width, int height) {
|
||||
var list = new SpruceOptionListWidget(Position.origin(), width, height);
|
||||
list.setBackground(new MidnightControlsBackground(130));
|
||||
list.addSingleOptionEntry(this.inputModeOption);
|
||||
list.addSingleOptionEntry(this.autoSwitchModeOption);
|
||||
list.addSingleOptionEntry(this.rotationSpeedOption);
|
||||
list.addSingleOptionEntry(this.yAxisRotationSpeedOption);
|
||||
list.addSingleOptionEntry(this.mouseSpeedOption);
|
||||
list.addSingleOptionEntry(this.virtualMouseOption);
|
||||
list.addSingleOptionEntry(this.hideCursorOption);
|
||||
list.addSingleOptionEntry(this.joystickAsMouseOption);
|
||||
list.addSingleOptionEntry(this.eyeTrackingAsMouseOption);
|
||||
list.addSingleOptionEntry(this.advancedConfigOption);
|
||||
return list;
|
||||
}
|
||||
|
||||
public SpruceOptionListWidget buildGameplayTab(int width, int height) {
|
||||
var list = new SpruceOptionListWidget(Position.origin(), width, height);
|
||||
list.setBackground(new MidnightControlsBackground(130));
|
||||
list.addSingleOptionEntry(this.analogMovementOption);
|
||||
list.addSingleOptionEntry(this.fastBlockPlacingOption);
|
||||
list.addSingleOptionEntry(this.frontBlockPlacingOption);
|
||||
list.addSingleOptionEntry(this.verticalReacharoundOption);
|
||||
list.addSingleOptionEntry(this.flyDriftingOption);
|
||||
list.addSingleOptionEntry(this.flyVerticalDriftingOption);
|
||||
list.addSingleOptionEntry(this.doubleTapToSprintOption);
|
||||
list.addSingleOptionEntry(this.controllerToggleSneakOption);
|
||||
list.addSingleOptionEntry(this.controllerToggleSprintOption);
|
||||
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.fastBlockPlacingOption);
|
||||
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.frontBlockPlacingOption);
|
||||
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.verticalReacharoundOption);
|
||||
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.flyDriftingOption);
|
||||
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.flyVerticalDriftingOption);
|
||||
list.addSingleOptionEntry(this.autoJumpOption);
|
||||
return list;
|
||||
}
|
||||
|
||||
public SpruceOptionListWidget buildVisualTab(int width, int height) {
|
||||
var list = new SpruceOptionListWidget(Position.origin(), width, height);
|
||||
list.setBackground(new MidnightControlsBackground(130));
|
||||
list.addSingleOptionEntry(this.controllerTypeOption);
|
||||
list.addSingleOptionEntry(this.virtualMouseSkinOption);
|
||||
list.addSingleOptionEntry(new SpruceSeparatorOption("midnightcontrols.menu.title.hud", true, null));
|
||||
list.addSingleOptionEntry(this.hudEnableOption);
|
||||
list.addSingleOptionEntry(this.hudSideOption);
|
||||
list.addSingleOptionEntry(this.moveChatOption);
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -332,17 +430,17 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
var root = new SpruceContainerWidget(Position.origin(), width, height);
|
||||
|
||||
var aboutMappings1 = new SpruceLabelWidget(Position.of(0, 2),
|
||||
new TranslatableText("midnightcontrols.controller.mappings.1", SDL2_GAMEPAD_TOOL),
|
||||
Text.translatable("midnightcontrols.controller.mappings.1", SDL2_GAMEPAD_TOOL),
|
||||
width, true);
|
||||
|
||||
var gamepadToolUrlLabel = new SpruceLabelWidget(Position.of(0, aboutMappings1.getHeight() + 4),
|
||||
this.controllerMappingsUrlText, width,
|
||||
label -> Util.getOperatingSystem().open(GAMEPAD_TOOL_URL), true);
|
||||
gamepadToolUrlLabel.setTooltip(new TranslatableText("chat.link.open"));
|
||||
gamepadToolUrlLabel.setTooltip(Text.translatable("chat.link.open"));
|
||||
|
||||
var aboutMappings3 = new SpruceLabelWidget(Position.of(0,
|
||||
aboutMappings1.getHeight() + gamepadToolUrlLabel.getHeight() + 6),
|
||||
new TranslatableText("midnightcontrols.controller.mappings.3", Formatting.GREEN.toString(), Formatting.RESET.toString()),
|
||||
Text.translatable("midnightcontrols.controller.mappings.3", Formatting.GREEN.toString(), Formatting.RESET.toString()),
|
||||
width, true);
|
||||
|
||||
int listHeight = height - 8 - aboutMappings1.getHeight() - aboutMappings3.getHeight() - gamepadToolUrlLabel.getHeight();
|
||||
@@ -354,9 +452,12 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
labels.addChild(aboutMappings3);
|
||||
|
||||
var list = new SpruceOptionListWidget(Position.origin(), width, listHeight);
|
||||
list.setBackground(new MidnightControlsBackground(130));
|
||||
list.addSingleOptionEntry(this.controllerOption);
|
||||
list.addSingleOptionEntry(this.secondControllerOption);
|
||||
list.addSingleOptionEntry(this.toggleControllerProfileOption);
|
||||
list.addSingleOptionEntry(this.unfocusedInputOption);
|
||||
list.addSingleOptionEntry(this.cameraModeOption);
|
||||
list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
|
||||
list.addSingleOptionEntry(this.rightDeadZoneOption);
|
||||
list.addSingleOptionEntry(this.leftDeadZoneOption);
|
||||
@@ -368,42 +469,55 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||
root.addChild(labels);
|
||||
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) {
|
||||
return new MappingsStringInputWidget(Position.origin(), width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderTitle(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
drawCenteredText(matrices, this.textRenderer, I18n.translate("midnightcontrols.menu.title"), this.width / 2, 8, 16777215);
|
||||
public void renderTitle(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
context.drawCenteredTextWithShadow(this.textRenderer, I18n.translate("midnightcontrols.menu.title"), this.width / 2, 8, 16777215);
|
||||
}
|
||||
|
||||
public static class MidnightControlsBackground implements Background {
|
||||
@Override
|
||||
public void render(MatrixStack matrixStack, SpruceWidget widget, int vOffset, int mouseX, int mouseY, float delta) {
|
||||
fill(matrixStack, widget.getX(), widget.getY(), widget.getX() + widget.getWidth(), widget.getY() + widget.getHeight(), MidnightColorUtil.hex2Rgb("#000000"));
|
||||
private static int transparency = 160;
|
||||
public MidnightControlsBackground() {}
|
||||
public MidnightControlsBackground(int transparency) {
|
||||
MidnightControlsBackground.transparency = transparency;
|
||||
}
|
||||
private void fill(MatrixStack matrixStack, int x2, int y2, int x1, int y1, Color color) {
|
||||
@Override
|
||||
public void render(DrawContext context, SpruceWidget widget, int vOffset, int mouseX, int mouseY, float delta) {
|
||||
fill(context.getMatrices(), widget.getX(), widget.getY(), widget.getX() + widget.getWidth(), widget.getY() + widget.getHeight(), MidnightColorUtil.hex2Rgb("#000000"));
|
||||
}
|
||||
private static void fill(MatrixStack matrixStack, int x2, int y2, int x1, int y1, Color color) {
|
||||
matrixStack.push();
|
||||
|
||||
Matrix4f matrix = matrixStack.peek().getPositionMatrix();
|
||||
float r = (float)(color.getRed()) / 255.0F;
|
||||
float g = (float)(color.getGreen()) / 255.0F;
|
||||
float b = (float)(color.getBlue()) / 255.0F;
|
||||
float t = (float)(160) / 255.0F;
|
||||
BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
|
||||
float t = (float)(transparency) / 255.0F;
|
||||
BufferBuilder bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.disableTexture();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
|
||||
bufferBuilder.vertex(matrix, (float)x1, (float)y2, 0.0F).color(r, g, b, t).next();
|
||||
bufferBuilder.vertex(matrix, (float)x2, (float)y2, 0.0F).color(r, g, b, t).next();
|
||||
bufferBuilder.vertex(matrix, (float)x2, (float)y1, 0.0F).color(r, g, b, t).next();
|
||||
bufferBuilder.vertex(matrix, (float)x1, (float)y1, 0.0F).color(r, g, b, t).next();
|
||||
bufferBuilder.end();
|
||||
BufferRenderer.draw(bufferBuilder);
|
||||
RenderSystem.enableTexture();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorProgram);
|
||||
bufferBuilder.vertex(matrix, (float)x1, (float)y2, 0.0F).color(r, g, b, t);
|
||||
bufferBuilder.vertex(matrix, (float)x2, (float)y2, 0.0F).color(r, g, b, t);
|
||||
bufferBuilder.vertex(matrix, (float)x2, (float)y1, 0.0F).color(r, g, b, t);
|
||||
bufferBuilder.vertex(matrix, (float)x1, (float)y1, 0.0F).color(r, g, b, t);
|
||||
BufferRenderer.drawWithGlobalProgram(bufferBuilder.end());
|
||||
RenderSystem.disableBlend();
|
||||
matrixStack.pop();
|
||||
}
|
||||
|
||||
@@ -10,12 +10,11 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||
import dev.lambdaurora.spruceui.option.SpruceSimpleActionOption;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||
import org.thinkingstudio.obsidianui.option.SpruceSimpleActionOption;
|
||||
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.toast.SystemToast;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@@ -34,8 +33,8 @@ public class ReloadControllerMappingsOption {
|
||||
Controller.updateMappings();
|
||||
if (client.currentScreen instanceof MidnightControlsSettingsScreen)
|
||||
client.currentScreen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
|
||||
new TranslatableText("midnightcontrols.controller.mappings.updated"), LiteralText.EMPTY));
|
||||
}, new TranslatableText("midnightcontrols.tooltip.reload_controller_mappings"));
|
||||
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
|
||||
Text.translatable("midnightcontrols.controller.mappings.updated"), Text.empty()));
|
||||
}, Text.translatable("midnightcontrols.tooltip.reload_controller_mappings"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
package eu.midnightdust.midnightcontrols.client.gui;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.RingButtonMode;
|
||||
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
/**
|
||||
* Represents the controls ring screen.
|
||||
@@ -26,30 +28,62 @@ public class RingScreen extends Screen {
|
||||
protected final MidnightControlsClient mod;
|
||||
|
||||
public RingScreen() {
|
||||
super(new TranslatableText("midnightcontrols.menu.title.ring"));
|
||||
super(Text.literal("midnightcontrols.menu.title.ring"));
|
||||
this.mod = MidnightControlsClient.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
if (mod.ring.getMaxPages() > 1) {
|
||||
this.addDrawableChild(ButtonWidget.builder(Text.of("◀"), button -> this.mod.ring.cyclePage(false)).dimensions(5, 5, 20, 20).build());
|
||||
this.addDrawableChild(ButtonWidget.builder(Text.of("▶"), button -> this.mod.ring.cyclePage(true)).dimensions(width - 25, 5, 20, 20).build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPause() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
super.render(matrices, mouseX, mouseY, delta);
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
super.render(context, mouseX, mouseY, delta);
|
||||
|
||||
RingPage page = this.mod.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
|
||||
public void close() {
|
||||
super.close();
|
||||
assert client != null;
|
||||
client.currentScreen = null;
|
||||
RingPage page = this.mod.ring.getCurrentPage();
|
||||
if (RingPage.selected >= 0 && page.actions[RingPage.selected] != null)
|
||||
page.actions[RingPage.selected].activate(RingButtonMode.PRESS);
|
||||
RingPage.selected = -1;
|
||||
this.removed();
|
||||
}
|
||||
// @Override
|
||||
// public boolean changeFocus(boolean lookForwards) {
|
||||
// if (lookForwards) {
|
||||
// if (RingPage.selected < 7) ++RingPage.selected;
|
||||
// else RingPage.selected = -1;
|
||||
// }
|
||||
// else {
|
||||
// if (RingPage.selected > -1) --RingPage.selected;
|
||||
// else RingPage.selected = 7;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||
/*if (midnightcontrolsClient.BINDING_RING.matchesMouse(button)) {
|
||||
this.onClose();
|
||||
if (mod.ring.getCurrentPage().onClick(width, height, (int) mouseX, (int) mouseY)) {
|
||||
this.close();
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,27 +9,41 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.gui;
|
||||
|
||||
import dev.lambdaurora.spruceui.widget.SpruceTexturedButtonWidget;
|
||||
import eu.midnightdust.midnightcontrols.client.HudSide;
|
||||
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.MidnightControlsClient;
|
||||
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.gui.ItemUseButtonWidget;
|
||||
import eu.midnightdust.midnightcontrols.client.touch.gui.SilentTexturedButtonWidget;
|
||||
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
|
||||
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||
import net.minecraft.client.gui.screen.ChatScreen;
|
||||
import net.minecraft.client.gui.screen.GameMenuScreen;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.*;
|
||||
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.TexturedButtonWidget;
|
||||
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.item.*;
|
||||
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.util.Arm;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
|
||||
|
||||
@@ -37,265 +51,329 @@ import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
|
||||
* Represents the touchscreen overlay
|
||||
*/
|
||||
public class TouchscreenOverlay extends Screen {
|
||||
public static final Identifier WIDGETS_LOCATION = new Identifier("midnightcontrols", "textures/gui/widgets.png");
|
||||
private MidnightControlsClient mod;
|
||||
private SpruceTexturedButtonWidget jumpButton;
|
||||
private SpruceTexturedButtonWidget flyButton;
|
||||
private SpruceTexturedButtonWidget flyUpButton;
|
||||
private SpruceTexturedButtonWidget flyDownButton;
|
||||
private int flyButtonEnableTicks = 0;
|
||||
private int forwardButtonTick = 0;
|
||||
private SpruceTexturedButtonWidget forwardLeftButton;
|
||||
private SpruceTexturedButtonWidget forwardRightButton;
|
||||
private SpruceTexturedButtonWidget startSneakButton;
|
||||
private SpruceTexturedButtonWidget endSneakButton;
|
||||
public static final Identifier WIDGETS_LOCATION = Identifier.of("midnightcontrols", "textures/gui/widgets.png");
|
||||
private final MidnightControlsClient mod;
|
||||
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 static TouchscreenOverlay instance;
|
||||
|
||||
public TouchscreenOverlay(@NotNull MidnightControlsClient mod)
|
||||
{
|
||||
super(new LiteralText("Touchscreen overlay"));
|
||||
public TouchscreenOverlay(@NotNull MidnightControlsClient mod) {
|
||||
super(Text.literal("Touchscreen overlay"));
|
||||
this.mod = mod;
|
||||
this.passEvents = true;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean shouldPause()
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean keyPressed(int keyCode, int scanCode, int modifiers)
|
||||
// {
|
||||
// super.keyPressed(keyCode,scanCode,modifiers);
|
||||
// //return false;
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private void pauseGame(boolean bl)
|
||||
// {
|
||||
// if (this.client == null)
|
||||
// return;
|
||||
// boolean bl2 = this.client.isIntegratedServerRunning() && !this.client.getServer().isRemote();
|
||||
// if (bl2) {
|
||||
// this.client.setScreen(new GameMenuScreen(!bl));
|
||||
// this.client.getSoundManager().pauseAll();
|
||||
// } else {
|
||||
// this.client.setScreen(new GameMenuScreen(true));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Updates the forward button ticks cooldown.
|
||||
// *
|
||||
// * @param state The button state.
|
||||
// *
|
||||
// */
|
||||
// private void updateForwardButtonsState(boolean state)
|
||||
// {
|
||||
// if (state)
|
||||
// this.forwardButtonTick = -1;
|
||||
// else
|
||||
// this.forwardButtonTick = 20;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Updates the jump buttons.
|
||||
// */
|
||||
// private void updateJumpButtons()
|
||||
// {
|
||||
// if (this.client == null)
|
||||
// return;
|
||||
// if (!this.client.interactionManager.isFlyingLocked()) {
|
||||
// boolean oldStateFly = this.flyButton.visible;
|
||||
// this.jumpButton.visible = false;
|
||||
// this.flyButton.visible = true;
|
||||
// this.flyUpButton.visible = true;
|
||||
// this.flyDownButton.visible = true;
|
||||
// if (oldStateFly != this.flyButton.visible) {
|
||||
// this.flyButtonEnableTicks = 5;
|
||||
// this.handleJump(null, false);
|
||||
// } else if (this.flyButtonEnableTicks > 0)
|
||||
// this.flyButtonEnableTicks--;
|
||||
// } else {
|
||||
// this.jumpButton.visible = true;
|
||||
// this.flyButton.visible = false;
|
||||
// this.flyUpButton.visible = false;
|
||||
// this.flyDownButton.visible = false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Handles the jump button.
|
||||
// *
|
||||
// * @param btn The pressed button.
|
||||
// * @param state The state of the jump button.
|
||||
// */
|
||||
// private void handleJump(ButtonWidget btn, boolean state)
|
||||
// {
|
||||
// ((KeyBindingAccessor) this.client.options.keyJump).midnightcontrols$handlePressState(state);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void tick()
|
||||
// {
|
||||
// if (this.forwardButtonTick > 0) {
|
||||
// this.forwardButtonTick--;
|
||||
// } else if (this.forwardButtonTick == 0) {
|
||||
// if (this.forwardLeftButton.visible)
|
||||
// this.forwardLeftButton.visible = false;
|
||||
// if (this.forwardRightButton.visible)
|
||||
// this.forwardRightButton.visible = false;
|
||||
// }
|
||||
// this.updateJumpButtons();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void init()
|
||||
// {
|
||||
// super.init();
|
||||
// int scaledWidth = this.client.getWindow().getScaledWidth();
|
||||
// int scaledHeight = this.client.getWindow().getScaledHeight();
|
||||
// this.addDrawableChild(new TexturedButtonWidget(scaledWidth / 2 - 20, 0, 20, 20, 0, 106, 20, ButtonWidget.WIDGETS_LOCATION, 256, 256,
|
||||
// btn -> this.client.setScreen(new ChatScreen("")), LiteralText.EMPTY));
|
||||
// this.addDrawableChild(new TexturedButtonWidget(scaledWidth / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256,
|
||||
// btn -> this.pauseGame(false)));
|
||||
// // Inventory buttons.
|
||||
// int inventoryButtonX = scaledWidth / 2;
|
||||
// int inventoryButtonY = scaledHeight - 16 - 5;
|
||||
// if (this.client.options.mainArm == Arm.LEFT) {
|
||||
// inventoryButtonX = inventoryButtonX - 91 - 24;
|
||||
// } else {
|
||||
// inventoryButtonX = inventoryButtonX + 91 + 4;
|
||||
// }
|
||||
// this.addDrawableChild(new TexturedButtonWidget(inventoryButtonX, inventoryButtonY, 20, 20, 20, 0, 20, WIDGETS_LOCATION, 256, 256,
|
||||
// btn -> {
|
||||
// if (this.client.interactionManager.hasRidingInventory()) {
|
||||
// this.client.player.openRidingInventory();
|
||||
// } else {
|
||||
// this.client.getTutorialManager().onInventoryOpened();
|
||||
// this.client.openScreen(new InventoryScreen(this.client.player));
|
||||
// }
|
||||
// }));
|
||||
// int jumpButtonX, swapHandsX, sneakButtonX;
|
||||
// int sneakButtonY = scaledHeight - 10 - 40 - 5;
|
||||
// if (MidnightControlsConfig.hudSide == HudSide.LEFT) {
|
||||
// jumpButtonX = scaledWidth - 20 - 20;
|
||||
// swapHandsX = jumpButtonX - 5 - 40;
|
||||
// sneakButtonX = 10 + 20 + 5;
|
||||
// } else {
|
||||
// jumpButtonX = 20;
|
||||
// swapHandsX = jumpButtonX + 5 + 40;
|
||||
// sneakButtonX = scaledWidth - 10 - 40 - 5;
|
||||
// }
|
||||
// // Swap items hand.
|
||||
// this.addDrawableChild(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY, 20, 20, 0, 160, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> {
|
||||
// if (state) {
|
||||
// if (!this.client.player.isSpectator()) {
|
||||
// this.client.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN));
|
||||
// }
|
||||
// }
|
||||
// }));
|
||||
// // Drop
|
||||
// this.addDrawableChild(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY + 5 + 20, 20, 20, 20, 160, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> ((KeyBindingAccessor) this.client.options.keyDrop).midnightcontrols$handlePressState(state)));
|
||||
// // Jump keys
|
||||
// this.addDrawableChild(this.jumpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 0, 40, 20, WIDGETS_LOCATION,
|
||||
// this::handleJump));
|
||||
// this.addDrawableChild(this.flyButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 20, 40, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> {
|
||||
// if (this.flyButtonEnableTicks == 0) this.client..abilities.flying = false;
|
||||
// }));
|
||||
// this.addDrawableChild(this.flyUpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY - 5 - 20, 20, 20, 40, 40, 20, WIDGETS_LOCATION,
|
||||
// this::handleJump));
|
||||
// this.addDrawableChild(this.flyDownButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY + 20 + 5, 20, 20, 60, 40, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> ((KeyBindingAccessor) this.client.options.keySneak).midnightcontrols$handlePressState(state)));
|
||||
// this.updateJumpButtons();
|
||||
// // Movements keys
|
||||
// this.addDrawableChild((this.startSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 0, 120, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> {
|
||||
// if (state) {
|
||||
// ((KeyBindingAccessor) this.client.options.keySneak).midnightcontrols$handlePressState(true);
|
||||
// this.startSneakButton.setVisible(false);
|
||||
// this.endSneakButton.setVisible(true);
|
||||
// }
|
||||
// })));
|
||||
// this.addDrawableChild((this.endSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 20, 120, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> {
|
||||
// if (state) {
|
||||
// ((KeyBindingAccessor) this.client.options.keySneak).midnightcontrols$handlePressState(false);
|
||||
// this.endSneakButton.setVisible(false);
|
||||
// this.startSneakButton.setVisible(true);
|
||||
// }
|
||||
// })));
|
||||
// this.endSneakButton.setVisible(false);
|
||||
// this.addDrawableChild(this.forwardLeftButton = new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20, 20, 20, 80, 80, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> {
|
||||
// ((KeyBindingAccessor) this.client.options.keyForward).midnightcontrols$handlePressState(state);
|
||||
// ((KeyBindingAccessor) this.client.options.keyLeft).midnightcontrols$handlePressState(state);
|
||||
// this.updateForwardButtonsState(state);
|
||||
// }));
|
||||
// this.forwardLeftButton.setVisible(false);
|
||||
// this.addDrawableChild(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY - 5 - 20, 20, 20, 0, 80, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> {
|
||||
// ((KeyBindingAccessor) this.client.options.keyForward).midnightcontrols$handlePressState(state);
|
||||
// this.updateForwardButtonsState(state);
|
||||
// this.forwardLeftButton.setVisible(true);
|
||||
// this.forwardRightButton.setVisible(true);
|
||||
// }));
|
||||
// this.addDrawableChild(this.forwardRightButton = new SpruceTexturedButtonWidget(sneakButtonX + 20 + 5, sneakButtonY - 5 - 20, 20, 20, 100, 80, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> {
|
||||
// ((KeyBindingAccessor) this.client.options.keyForward).midnightcontrols$handlePressState(state);
|
||||
// ((KeyBindingAccessor) this.client.options.keyRight).midnightcontrols$handlePressState(state);
|
||||
// this.updateForwardButtonsState(state);
|
||||
// }));
|
||||
// this.forwardRightButton.setVisible(true);
|
||||
// this.addDrawableChild(new SpruceTexturedButtonWidget(sneakButtonX + 20 + 5, sneakButtonY, 20, 20, 20, 80, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> ((KeyBindingAccessor) this.client.options.keyRight).midnightcontrols$handlePressState(state)));
|
||||
// this.addDrawableChild(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY + 20 + 5, 20, 20, 40, 80, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> ((KeyBindingAccessor) this.client.options.keyBack).midnightcontrols$handlePressState(state)));
|
||||
// this.addDrawableChild(new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY, 20, 20, 60, 80, 20, WIDGETS_LOCATION,
|
||||
// (btn, state) -> ((KeyBindingAccessor) this.client.options.keyLeft).midnightcontrols$handlePressState(state)));
|
||||
//
|
||||
// this.children().forEach(button -> {
|
||||
// if (button instanceof SpruceTexturedButtonWidget) {
|
||||
// ((SpruceTexturedButtonWidget) button).setSilent(true);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean mouseClicked(double mouseX, double mouseY, int button)
|
||||
// {
|
||||
// if (mouseY >= (double) (this.height - 22) && this.client != null && this.client.player != null) {
|
||||
// int centerX = this.width / 2;
|
||||
// if (mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) {
|
||||
// for (int slot = 0; slot < 9; ++slot) {
|
||||
// int slotX = centerX - 90 + slot * 20 + 2;
|
||||
// if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) {
|
||||
// this.client.player.getInventory().selectedSlot = slot;
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return super.mouseClicked(mouseX, mouseY, button);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY)
|
||||
// {
|
||||
// if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) {
|
||||
// if (deltaY > 0.01)
|
||||
// this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 2);
|
||||
// else if (deltaY < 0.01)
|
||||
// this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 1);
|
||||
//
|
||||
// if (deltaX > 0.01)
|
||||
// this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 2);
|
||||
// else if (deltaX < 0.01)
|
||||
// this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 1);
|
||||
// }
|
||||
// return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||
// }
|
||||
@Override
|
||||
public boolean shouldPause() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderInGameBackground(DrawContext context) {}
|
||||
|
||||
@Override
|
||||
protected void applyBlur(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(Identifier.of(MidnightControlsConstants.NAMESPACE, "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(Identifier.of(MidnightControlsConstants.NAMESPACE, "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(Identifier.of(MidnightControlsConstants.NAMESPACE, "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);
|
||||
TouchscreenOverlay.instance = this;
|
||||
}
|
||||
private void initCustomButtons(boolean left) {
|
||||
assert client != null;
|
||||
Identifier emptySprite = Identifier.of(MidnightControlsConstants.NAMESPACE, "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(Identifier.of(MidnightControlsConstants.NAMESPACE, "binding/"+bindName)) != missingSprite;
|
||||
if (MidnightControlsConfig.debug) System.out.println(left +" "+Identifier.of(MidnightControlsConstants.NAMESPACE, "binding/"+bindName)+" "+ hasTexture);
|
||||
var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> binding.handle(client, 1, ButtonState.PRESS), hasTexture)
|
||||
.texture(hasTexture ? Identifier.of(MidnightControlsConstants.NAMESPACE, "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().getItem() instanceof ArmorItem) && !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 (!MidnightControlsConfig.invertTouch) {
|
||||
deltaX = -deltaX;
|
||||
deltaY = -deltaY;
|
||||
}
|
||||
if (deltaY > 0.01)
|
||||
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs((deltaY / 3.0)*MidnightControlsConfig.touchSpeed/100), 2);
|
||||
else this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs((deltaY / 3.0)*MidnightControlsConfig.touchSpeed/100), 1);
|
||||
|
||||
if (deltaX > 0.01)
|
||||
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs((deltaX / 3.0)*MidnightControlsConfig.touchSpeed/100), 2);
|
||||
else this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs((deltaX / 3.0)*MidnightControlsConfig.touchSpeed/100), 1);
|
||||
}
|
||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||
}
|
||||
@Override
|
||||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||
KeyBinding.onKeyPressed(InputUtil.fromKeyCode(keyCode, scanCode));
|
||||
super.keyPressed(keyCode,scanCode,modifiers);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
super.render(context, mouseX, mouseY, delta);
|
||||
context.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
context.fill(mouseX-10, mouseY-10, mouseX+10, mouseY+10, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,11 @@ package eu.midnightdust.midnightcontrols.client.gui.widget;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||
import dev.lambdaurora.spruceui.Position;
|
||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||
import dev.lambdaurora.spruceui.widget.AbstractSpruceIconButtonWidget;
|
||||
import org.thinkingstudio.obsidianui.Position;
|
||||
import org.thinkingstudio.obsidianui.SpruceTexts;
|
||||
import org.thinkingstudio.obsidianui.widget.AbstractSpruceIconButtonWidget;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -35,23 +34,23 @@ public class ControllerButtonWidget extends AbstractSpruceIconButtonWidget {
|
||||
public void update() {
|
||||
int length = binding.getButton().length;
|
||||
this.setMessage(this.binding.isNotBound() ? SpruceTexts.NOT_BOUND.copy() :
|
||||
(length > 0 ? ButtonBinding.getLocalizedButtonName(binding.getButton()[0]) : new LiteralText("<>")));
|
||||
(length > 0 ? ButtonBinding.getLocalizedButtonName(binding.getButton()[0]) : Text.literal("<>")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getMessage() {
|
||||
if (this.binding.getButton().length > 1)
|
||||
return LiteralText.EMPTY;
|
||||
return Text.empty();
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
@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();
|
||||
if (this.binding.getButton().length > 1) {
|
||||
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();
|
||||
return size.height();
|
||||
}
|
||||
|
||||
@@ -13,13 +13,14 @@ import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import dev.lambdaurora.spruceui.Position;
|
||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||
import org.thinkingstudio.obsidianui.Position;
|
||||
import org.thinkingstudio.obsidianui.SpruceTexts;
|
||||
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
||||
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
||||
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.util.math.MatrixStack;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.text.Text;
|
||||
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -46,9 +47,10 @@ public class ControllerControlsWidget extends SpruceContainerWidget {
|
||||
|
||||
protected void init() {
|
||||
this.addChild(new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, 18), 310, 20,
|
||||
new TranslatableText("midnightcontrols.menu.keyboard_controls"),
|
||||
Text.translatable("midnightcontrols.menu.keyboard_controls"),
|
||||
btn -> this.client.setScreen(new ControlsOptionsScreen(null, this.client.options))));
|
||||
this.bindingsListWidget = new ControlsListWidget(Position.of(this, 0, 43), this.width, this.height - 43 - 35, this);
|
||||
this.bindingsListWidget.setBackground(new MidnightControlsSettingsScreen.MidnightControlsBackground(130));
|
||||
this.addChild(this.bindingsListWidget);
|
||||
this.addChild(this.resetButton = new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, this.height - 29), 150, 20,
|
||||
SpruceTexts.CONTROLS_RESET_ALL,
|
||||
@@ -56,11 +58,11 @@ public class ControllerControlsWidget extends SpruceContainerWidget {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
drawCenteredText(matrices, this.client.textRenderer, new TranslatableText("midnightcontrols.menu.title.controller_controls"),
|
||||
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
context.drawCenteredTextWithShadow(this.client.textRenderer, Text.translatable("midnightcontrols.menu.title.controller_controls"),
|
||||
this.getX() + this.width / 2, this.getY() + 4, 16777215);
|
||||
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) {
|
||||
|
||||
@@ -14,22 +14,20 @@ import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import dev.lambdaurora.spruceui.Position;
|
||||
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||
import dev.lambdaurora.spruceui.navigation.NavigationDirection;
|
||||
import dev.lambdaurora.spruceui.navigation.NavigationUtils;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceSeparatorWidget;
|
||||
import dev.lambdaurora.spruceui.widget.SpruceWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceEntryListWidget;
|
||||
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
|
||||
import org.thinkingstudio.obsidianui.Position;
|
||||
import org.thinkingstudio.obsidianui.SpruceTexts;
|
||||
import org.thinkingstudio.obsidianui.navigation.NavigationDirection;
|
||||
import org.thinkingstudio.obsidianui.navigation.NavigationUtils;
|
||||
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
||||
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.Environment;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Formatting;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -93,17 +91,17 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
||||
MidnightControlsClient.get().input.beginControlsInput(gui);
|
||||
}) {
|
||||
protected Text getNarrationMessage() {
|
||||
return binding.isNotBound() ? new TranslatableText("narrator.controls.unbound", bindingName)
|
||||
: new TranslatableText("narrator.controls.bound", bindingName, super.getNarrationMessage());
|
||||
return binding.isNotBound() ? Text.translatable("narrator.controls.unbound", bindingName)
|
||||
: Text.translatable("narrator.controls.bound", bindingName, super.getNarrationMessage());
|
||||
}
|
||||
};
|
||||
this.children.add(editButton);
|
||||
this.resetButton = new SpruceButtonWidget(Position.of(this,
|
||||
this.editButton.getPosition().getRelativeX() + this.editButton.getWidth() + 2, 0),
|
||||
44, 20, new TranslatableText("controls.reset"),
|
||||
44, 20, Text.translatable("controls.reset"),
|
||||
btn -> MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton())) {
|
||||
protected Text getNarrationMessage() {
|
||||
return new TranslatableText("narrator.controls.reset", bindingName);
|
||||
return Text.translatable("narrator.controls.reset", bindingName);
|
||||
}
|
||||
};
|
||||
this.children.add(this.resetButton);
|
||||
@@ -116,7 +114,7 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
||||
MidnightControlsClient.get().input.beginControlsInput(null);
|
||||
}) {
|
||||
protected Text getNarrationMessage() {
|
||||
return new TranslatableText("midnightcontrols.narrator.unbound", bindingName);
|
||||
return Text.translatable("midnightcontrols.narrator.unbound", bindingName);
|
||||
}
|
||||
};
|
||||
this.children.add(this.unbindButton);
|
||||
@@ -228,14 +226,14 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
||||
/* Rendering */
|
||||
|
||||
@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;
|
||||
|
||||
var textRenderer = ControlsListWidget.this.client.textRenderer;
|
||||
int height = this.getHeight();
|
||||
//float textX = (float) (this.getX() + 70 - ControlsListWidget.this.maxTextLength);
|
||||
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.unbindButton.setVisible(focused);
|
||||
@@ -243,9 +241,9 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
||||
|
||||
this.editButton.update();
|
||||
if (focused) {
|
||||
var text = new LiteralText("> ").formatted(Formatting.WHITE);
|
||||
var text = Text.literal("> ").formatted(Formatting.WHITE);
|
||||
text.append(this.editButton.getMessage().copy().formatted(Formatting.YELLOW));
|
||||
this.editButton.setMessage(text.append(new LiteralText(" <").formatted(Formatting.WHITE)));
|
||||
this.editButton.setMessage(text.append(Text.literal(" <").formatted(Formatting.WHITE)));
|
||||
} else if (!this.binding.isNotBound() && InputManager.hasDuplicatedBindings(this.binding)) {
|
||||
var text = this.editButton.getMessage().copy();
|
||||
this.editButton.setMessage(text.formatted(Formatting.RED));
|
||||
@@ -254,7 +252,7 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +262,7 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
||||
protected CategoryEntry(ControlsListWidget parent, ButtonCategory category) {
|
||||
super(parent);
|
||||
this.separatorWidget = new SpruceSeparatorWidget(Position.of(this, 2, 0), this.getWidth() - 4,
|
||||
new LiteralText(category.getTranslatedName())) {
|
||||
Text.literal(category.getTranslatedName())) {
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return CategoryEntry.this.getWidth() - 4;
|
||||
@@ -291,8 +289,8 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
|
||||
/* Rendering */
|
||||
|
||||
@Override
|
||||
protected void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
this.separatorWidget.render(matrices, mouseX, mouseY, delta);
|
||||
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||
this.separatorWidget.render(context, mouseX, mouseY, delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -17,4 +17,6 @@ import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
public interface ClickableWidgetAccessor {
|
||||
@Accessor("height")
|
||||
int getHeight();
|
||||
@Accessor("focused")
|
||||
void setFocused(boolean value);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.MovementHandler;
|
||||
@@ -19,12 +20,15 @@ import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.entity.MovementType;
|
||||
import net.minecraft.network.encryption.PlayerPublicKey;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
@@ -34,6 +38,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity {
|
||||
private boolean midnightcontrols$driftingPrevented = false;
|
||||
|
||||
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
|
||||
super(world, profile);
|
||||
}
|
||||
|
||||
@Shadow
|
||||
protected abstract boolean hasMovementInput();
|
||||
|
||||
@@ -47,13 +55,13 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
|
||||
@Shadow
|
||||
protected abstract boolean isCamera();
|
||||
|
||||
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
|
||||
super(world, profile);
|
||||
}
|
||||
@Shadow protected int ticksLeftToDoubleTapSprint;
|
||||
|
||||
|
||||
@Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
|
||||
public void onMove(MovementType type, Vec3d movement, CallbackInfo ci) {
|
||||
var mod = MidnightControlsClient.get();
|
||||
if (!MidnightControlsConfig.doubleTapToSprint) ticksLeftToDoubleTapSprint = 0;
|
||||
if (!MidnightControls.isExtrasLoaded) return;
|
||||
if (type == MovementType.SELF) {
|
||||
if (this.getAbilities().flying && (!MidnightControlsConfig.flyDrifting || !MidnightControlsConfig.verticalFlyDrifting)) {
|
||||
if (!this.hasMovementInput()) {
|
||||
@@ -68,7 +76,7 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick(Z)V", shift = At.Shift.AFTER))
|
||||
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick(ZF)V", shift = At.Shift.AFTER))
|
||||
public void onInputUpdate(CallbackInfo ci) {
|
||||
MovementHandler.HANDLER.applyMovement((ClientPlayerEntity) (Object) this);
|
||||
}
|
||||
@@ -76,7 +84,7 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
|
||||
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z"))
|
||||
public void onTickMovement(CallbackInfo ci) {
|
||||
if (this.getAbilities().flying && this.isCamera()) {
|
||||
if (MidnightControlsConfig.verticalFlyDrifting)
|
||||
if (MidnightControlsConfig.verticalFlyDrifting || !MidnightControls.isExtrasLoaded)
|
||||
return;
|
||||
int moving = 0;
|
||||
if (this.input.sneaking) {
|
||||
|
||||
@@ -10,14 +10,16 @@
|
||||
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.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
||||
import net.minecraft.client.option.GameOptions;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@@ -26,17 +28,29 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
* Injects the new controls settings button.
|
||||
*/
|
||||
@Mixin(ControlsOptionsScreen.class)
|
||||
public class ControlsOptionsScreenMixin extends GameOptionsScreen {
|
||||
public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text text) {
|
||||
super(parent, gameOptions, text);
|
||||
public abstract class ControlsOptionsScreenMixin extends GameOptionsScreen {
|
||||
|
||||
public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text title) {
|
||||
super(parent, gameOptions, title);
|
||||
}
|
||||
@Inject(method = "init", at = @At(value = "INVOKE", ordinal = 4, shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;"))
|
||||
private void addControllerButton(CallbackInfo ci) {
|
||||
int i = this.width / 2 - 155;
|
||||
int j = i + 160;
|
||||
int k = this.height / 6 - 12 + 48;;
|
||||
this.addDrawableChild(new ButtonWidget(j, k, 150, 20, new TranslatableText("midnightcontrols.menu.title.controller").append("..."), (button) -> {
|
||||
this.client.setScreen(new MidnightControlsSettingsScreen(this, false));
|
||||
}));
|
||||
@Unique TextIconButtonWidget button = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"), (button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true)
|
||||
.dimension(20,20).texture(Identifier.of("midnightcontrols", "icon/controller"), 20, 20).build();
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
this.midnightcontrols$setupButton();
|
||||
this.addDrawableChild(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(MinecraftClient client, int width, int height) {
|
||||
super.resize(client, width, height);
|
||||
this.midnightcontrols$setupButton();
|
||||
}
|
||||
@Unique
|
||||
public void midnightcontrols$setupButton() {
|
||||
assert body != null;
|
||||
button.setPosition(body.getWidth() / 2 + 158, body.getY() + 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemGroups;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -29,7 +30,9 @@ public interface CreativeInventoryScreenAccessor {
|
||||
* @return the selected tab index
|
||||
*/
|
||||
@Accessor("selectedTab")
|
||||
int getSelectedTab();
|
||||
static ItemGroup getSelectedTab() {
|
||||
return ItemGroups.getDefaultTab();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selected tab.
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* 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.widget.EntryListWidget;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(EntryListWidget.class)
|
||||
public interface EntryListWidgetAccessor {
|
||||
@Invoker("moveSelection")
|
||||
void midnightcontrols$moveSelection(EntryListWidget.MoveDirection direction);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.option.GameOptions;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Represents a mixin to GameOptions.
|
||||
* <p>
|
||||
* Sets the default of the Auto-Jump option to false.
|
||||
*/
|
||||
@Mixin(GameOptions.class)
|
||||
public class GameOptionsMixin {
|
||||
@Shadow
|
||||
public boolean autoJump;
|
||||
|
||||
@Inject(method = "load", at = @At("HEAD"))
|
||||
public void onInit(CallbackInfo ci) {
|
||||
// Set default value of the Auto-Jump option to false.
|
||||
this.autoJump = false;
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,18 @@
|
||||
|
||||
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;
|
||||
@@ -22,14 +29,26 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class GameRendererMixin {
|
||||
public abstract class GameRendererMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private MinecraftClient client;
|
||||
MinecraftClient client;
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getX()D"))
|
||||
private void onRender(float tickDelta, long startTime, boolean fullRender, CallbackInfo ci) {
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getX()D", shift = At.Shift.BEFORE))
|
||||
private void onRender(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) {
|
||||
if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER)
|
||||
MidnightControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen);
|
||||
}
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;draw()V", shift = At.Shift.BEFORE))
|
||||
private void renderVirtualCursor(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) {
|
||||
MidnightControlsRenderer.renderVirtualCursor(drawContext, client);
|
||||
drawContext.draw();
|
||||
}
|
||||
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z"), method = "renderWorld")
|
||||
private void captureProjAndModMatrix(RenderTickCounter tickCounter, CallbackInfo ci, @Local(ordinal = 1) Matrix4f matrices) {
|
||||
TouchUtils.lastProjMat.set(RenderSystem.getProjectionMatrix());
|
||||
TouchUtils.lastModMat.set(RenderSystem.getModelViewMatrix());
|
||||
TouchUtils.lastWorldSpaceMatrix.set(matrices);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,17 +12,22 @@ package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.EMICompat;
|
||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.screen.slot.SlotActionType;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -34,7 +39,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
*/
|
||||
@Mixin(HandledScreen.class)
|
||||
public abstract class HandledScreenMixin implements HandledScreenAccessor {
|
||||
|
||||
@Accessor("x")
|
||||
public abstract int getX();
|
||||
|
||||
@@ -52,19 +56,26 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor {
|
||||
public abstract void midnightcontrols$onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
|
||||
|
||||
@Inject(method = "render", at = @At("RETURN"))
|
||||
public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||
public void onRender(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.hudEnable) {
|
||||
var client = MinecraftClient.getInstance();
|
||||
int x = 2, y = client.getWindow().getScaledHeight() - 2 - MidnightControlsRenderer.ICON_SIZE;
|
||||
|
||||
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "midnightcontrols.action.pickup_all", true, client) + 2;
|
||||
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_B}, "midnightcontrols.action.exit", true, client) + 2;
|
||||
if (MidnightControlsCompat.isEMIPresent() && EMICompat.isEMIEnabled()) {
|
||||
x += 42;
|
||||
}
|
||||
if (!ButtonBinding.TAKE_ALL.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(context, x, y, ButtonBinding.TAKE_ALL,true, client) + 2;
|
||||
if (!ButtonBinding.EXIT.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(context, x, y, ButtonBinding.EXIT, true, client) + 2;
|
||||
if (MidnightControlsCompat.isReiPresent()) {
|
||||
x = 2;
|
||||
y -= 24;
|
||||
}
|
||||
x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, "midnightcontrols.action.pickup", true, client) + 2;
|
||||
MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, "midnightcontrols.action.quick_move", true, client);
|
||||
if (MidnightControlsCompat.isEMIPresent() && EMICompat.isEMIEnabled() && EMICompat.isSearchBarCentered()) {
|
||||
x = client.getWindow().getScaledWidth() - 55 - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.pickup"))
|
||||
- client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.quick_move"))
|
||||
- MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.TAKE) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.QUICK_MOVE);
|
||||
}
|
||||
if (!ButtonBinding.TAKE.isNotBound()) x = MidnightControlsRenderer.drawButtonTip(context, x, y, ButtonBinding.TAKE, true, client);
|
||||
if (!ButtonBinding.QUICK_MOVE.isNotBound()) MidnightControlsRenderer.drawButtonTip(context, x, y, ButtonBinding.QUICK_MOVE, true, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(KeyBinding.class)
|
||||
public interface KeyBindingIDAccessor {
|
||||
@Accessor @Final
|
||||
static Map<String, KeyBinding> getKEYS_BY_ID() {return null;};
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(KeyBinding.class)
|
||||
public class KeyBindingMixin implements KeyBindingAccessor {
|
||||
public abstract class KeyBindingMixin implements KeyBindingAccessor {
|
||||
@Shadow
|
||||
private int timesPressed;
|
||||
|
||||
@@ -28,7 +28,7 @@ public class KeyBindingMixin implements KeyBindingAccessor {
|
||||
if (!this.pressed)
|
||||
this.pressed = true;
|
||||
++this.timesPressed;
|
||||
return oldPressed != this.pressed;
|
||||
return !oldPressed;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.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,15 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.client.network.ClientPlayerInteractionManager;
|
||||
import net.minecraft.client.render.BufferBuilderStorage;
|
||||
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.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
@@ -31,7 +28,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
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.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -42,28 +39,17 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(MinecraftClient.class)
|
||||
public abstract class MinecraftClientMixin {
|
||||
@Shadow
|
||||
@Nullable
|
||||
public HitResult crosshairTarget;
|
||||
@Shadow @Nullable public HitResult crosshairTarget;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public ClientPlayerEntity player;
|
||||
@Shadow @Nullable public ClientPlayerEntity player;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public ClientPlayerInteractionManager interactionManager;
|
||||
@Shadow @Nullable public ClientPlayerInteractionManager interactionManager;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public ClientWorld world;
|
||||
@Shadow @Final public GameRenderer gameRenderer;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
public GameRenderer gameRenderer;
|
||||
@Shadow private int itemUseCooldown;
|
||||
|
||||
@Shadow
|
||||
private int itemUseCooldown;
|
||||
@Shadow public abstract BufferBuilderStorage getBufferBuilders();
|
||||
|
||||
private BlockPos midnightcontrols$lastTargetPos;
|
||||
private Vec3d midnightcontrols$lastPos;
|
||||
@@ -104,24 +90,22 @@ public abstract class MinecraftClientMixin {
|
||||
this.midnightcontrols$lastTargetSide = side;
|
||||
}
|
||||
// Removed front placing sprinting as way too cheaty.
|
||||
/*else if (this.player.isSprinting()) {
|
||||
hitResult = midnightcontrolsClient.get().reacharound.getLastReacharoundResult();
|
||||
if (hitResult != null) {
|
||||
if (cooldown > 0)
|
||||
this.itemUseCooldown = 0;
|
||||
}
|
||||
}*/
|
||||
// else if (this.player.isSprinting()) {
|
||||
// hitResult = MidnightControlsClient.get().reacharound.getLastReacharoundResult();
|
||||
// if (hitResult != null) {
|
||||
// if (cooldown > 0)
|
||||
// this.itemUseCooldown = 0;
|
||||
// }
|
||||
// }
|
||||
this.midnightcontrols$lastPos = this.player.getPos();
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At("HEAD"))
|
||||
private void onRender(boolean fullRender, CallbackInfo ci) {
|
||||
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.AFTER))
|
||||
private void renderVirtualCursor(boolean fullRender, CallbackInfo ci) {
|
||||
MidnightControlsRenderer.renderVirtualCursor(new MatrixStack(), (MinecraftClient) (Object) this);
|
||||
@Inject(at = @At("TAIL"), method = "setScreen")
|
||||
private void setScreen(Screen screen, CallbackInfo info) {
|
||||
if (MidnightControlsConfig.hideNormalMouse){
|
||||
if (screen != null) GLFW.glfwSetInputMode(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_HIDDEN);
|
||||
else GLFW.glfwSetInputMode(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
@@ -138,7 +122,7 @@ public abstract class MinecraftClientMixin {
|
||||
hitResult = mod.reacharound.withSideForReacharound(hitResult, stackInHand);
|
||||
|
||||
int previousStackCount = stackInHand.getCount();
|
||||
var result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult);
|
||||
var result = this.interactionManager.interactBlock(this.player, hand, hitResult);
|
||||
if (result.isAccepted()) {
|
||||
if (result.shouldSwingHand()) {
|
||||
this.player.swingHand(hand);
|
||||
@@ -157,4 +141,10 @@ public abstract class MinecraftClientMixin {
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is always supposed to be located at before the line 'this.profiler.swap("Keybindings");'
|
||||
// @Redirect(method = "tick", at = @At(value = "FIELD",target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", ordinal = 6))
|
||||
// private Screen midnightcontrols$ignoreTouchOverlay(MinecraftClient instance) {
|
||||
// if (instance.currentScreen instanceof TouchscreenOverlay) return null;
|
||||
// return instance.currentScreen;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import net.minecraft.client.Mouse;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(Mouse.class)
|
||||
public interface MouseAccessor {
|
||||
@Invoker("onCursorPos")
|
||||
void midnightcontrols$onCursorPos(long window, double x, double y);
|
||||
@Accessor
|
||||
void setLeftButtonClicked(boolean value);
|
||||
|
||||
}
|
||||
@@ -12,43 +12,90 @@ package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
|
||||
import eu.midnightdust.midnightcontrols.client.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.gui.screen.Screen;
|
||||
import net.minecraft.client.util.GlfwUtil;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ThrowablePotionItem;
|
||||
import net.minecraft.util.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.gen.Invoker;
|
||||
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 @Final private MinecraftClient client;
|
||||
|
||||
@Invoker("onCursorPos")
|
||||
public abstract void midnightcontrols$onCursorPos(long window, double x, double y);
|
||||
@Shadow private double y;
|
||||
|
||||
@Inject(method = "onMouseButton", at = @At(value = "TAIL"))
|
||||
private void onMouseBackButton(long window, int button, int action, int mods, CallbackInfo ci) {
|
||||
if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && MinecraftClient.getInstance().currentScreen != null) {
|
||||
if (MidnightControlsClient.get().input.tryGoBack(MinecraftClient.getInstance().currentScreen)) {
|
||||
action = 0;
|
||||
@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.get().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().selectedSlot = slot;
|
||||
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.getTargettedObject(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 isCursorLocked(CallbackInfoReturnable<Boolean> ci) {
|
||||
private void midnightcontrols$isCursorLocked(CallbackInfoReturnable<Boolean> ci) {
|
||||
if (this.client.currentScreen == null) {
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse) {
|
||||
ci.setReturnValue(true);
|
||||
@@ -58,9 +105,49 @@ public abstract class MouseMixin implements MouseAccessor {
|
||||
}
|
||||
|
||||
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
|
||||
private void onCursorLocked(CallbackInfo ci) {
|
||||
if (/*config.getControlsMode() == ControlsMode.TOUCHSCREEN
|
||||
||*/ (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse))
|
||||
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, isUsingLongRangedTool(), cursorXSmoother, cursorYSmoother);
|
||||
glfwTime = GlfwUtil.getTime();
|
||||
cursorDeltaX = 0.0;
|
||||
cursorDeltaY = 0.0;
|
||||
ci.cancel();
|
||||
}
|
||||
if (doMixedInput() && client.isWindowFocused()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private boolean 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,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.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();
|
||||
}
|
||||
@@ -9,8 +9,14 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.mixin;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import eu.midnightdust.lib.util.MidnightColorUtil;
|
||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
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.*;
|
||||
@@ -20,16 +26,21 @@ 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.Matrix4f;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
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.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.*;
|
||||
|
||||
/**
|
||||
* Represents a mixin to WorldRenderer.
|
||||
* <p>
|
||||
@@ -49,7 +60,15 @@ public abstract class WorldRendererMixin {
|
||||
private BufferBuilderStorage bufferBuilders;
|
||||
|
||||
@Shadow
|
||||
private static void drawShapeOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, VoxelShape voxelShape, double d, double e, double f, float g, float h, float i, float j) {
|
||||
private static void drawCuboidShapeOutline(MatrixStack matrices, VertexConsumer vertexConsumer, VoxelShape shape, double offsetX, double offsetY, double offsetZ, float red, float green, float blue, float alpha) {
|
||||
}
|
||||
|
||||
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"))
|
||||
private HitResult.Type dontRenderOutline(HitResult instance) {
|
||||
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
|
||||
return HitResult.Type.MISS;
|
||||
}
|
||||
return instance.getType();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -61,15 +80,40 @@ public abstract class WorldRendererMixin {
|
||||
shift = At.Shift.AFTER
|
||||
)
|
||||
)
|
||||
private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer,
|
||||
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
||||
private void onOutlineRender(RenderTickCounter tickCounter, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, Matrix4f matrix4f2, CallbackInfo ci, @Local MatrixStack matrices) {
|
||||
if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN)
|
||||
&& MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
|
||||
this.renderFingerOutline(matrices, camera);
|
||||
}
|
||||
this.renderReacharoundOutline(matrices, camera);
|
||||
}
|
||||
@Unique
|
||||
private void 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());
|
||||
drawCuboidShapeOutline(matrices, vertexConsumer, outlineShape, blockPos.getX() - pos.getX(), blockPos.getY() - pos.getY(), blockPos.getZ() - pos.getZ(),
|
||||
rgb.getRed() / 255.f, rgb.getGreen() / 255.f, rgb.getBlue() / 255.f, MidnightControlsConfig.touchOutlineColorAlpha / 255.f);
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
||||
@Unique
|
||||
private void renderReacharoundOutline(MatrixStack matrices, Camera camera) {
|
||||
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !MidnightControlsConfig.shouldRenderReacharoundOutline)
|
||||
return;
|
||||
var result = MidnightControlsClient.get().reacharound.getLastReacharoundResult();
|
||||
if (result == null)
|
||||
return;
|
||||
var blockPos = result.getBlockPos();
|
||||
if (this.world.getWorldBorder().contains(blockPos)) {
|
||||
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;
|
||||
@@ -86,12 +130,14 @@ public abstract class WorldRendererMixin {
|
||||
var pos = camera.getPos();
|
||||
|
||||
var outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
|
||||
int[] color = MidnightControlsConfig.reacharoundOutlineColor;
|
||||
|
||||
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());
|
||||
drawShapeOutline(matrices, vertexConsumer, outlineShape,
|
||||
drawCuboidShapeOutline(matrices, vertexConsumer, outlineShape,
|
||||
(double) blockPos.getX() - pos.getX(), (double) blockPos.getY() - pos.getY(), (double) blockPos.getZ() - pos.getZ(),
|
||||
color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
|
||||
rgb.getRed() / 255.f, rgb.getGreen() / 255.f, rgb.getBlue() / 255.f, MidnightControlsConfig.reacharoundOutlineColorAlpha / 255.f);
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
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
|
||||
) {
|
||||
// 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 timestamp = GlfwUtil.getTime();
|
||||
double deltaTime = timestamp - 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||
*
|
||||
* This file is part of midnightcontrols.
|
||||
*
|
||||
* Licensed under the MIT license. For more information,
|
||||
* see the LICENSE file.
|
||||
*/
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.text.OrderedText;
|
||||
import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ButtonBindingRingAction extends RingAction {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public final ButtonBinding binding;
|
||||
|
||||
public ButtonBindingRingAction(@NotNull ButtonBinding binding) {
|
||||
super();
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
return this.binding.getTranslationKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAction(@NotNull RingButtonMode mode) {
|
||||
binding.handle(MinecraftClient.getInstance(), 1.0f, ButtonState.PRESS);
|
||||
if (binding.asKeyBinding().isPresent()) {
|
||||
binding.asKeyBinding().get().setPressed(true);
|
||||
((KeyBindingAccessor)binding.asKeyBinding().get()).midnightcontrols$press();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
for (int i = 0; i < lines.size(); ++i) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class Factory implements RingAction.Factory {
|
||||
@Override
|
||||
public @NotNull Supplier<RingAction> newFromGui(@NotNull Screen screen) {
|
||||
return () -> null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable RingAction parse(@NotNull Config config) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* 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.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DummyRingAction extends RingAction {
|
||||
public DummyRingAction(@NotNull Config config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
return "dummy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAction(@NotNull RingButtonMode mode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
||||
drawCenteredText(matrices, textRenderer, this.getName(), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.option.KeyBinding;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class KeyBindingRingAction extends RingAction {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public final KeyBinding binding;
|
||||
|
||||
public KeyBindingRingAction(@NotNull Config config, @NotNull KeyBinding binding) {
|
||||
super(config);
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
return this.binding.getTranslationKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAction(@NotNull RingButtonMode mode) {
|
||||
KeyBindingAccessor accessor = (KeyBindingAccessor) this.binding;
|
||||
switch (mode) {
|
||||
case PRESS, HOLD -> accessor.midnightcontrols$handlePressState(this.activated);
|
||||
case TOGGLE -> {
|
||||
accessor.midnightcontrols$handlePressState(!this.binding.isPressed());
|
||||
this.activated = !this.binding.isPressed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
||||
drawCenteredText(matrices, textRenderer, new TranslatableText(this.getName()), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff);
|
||||
}
|
||||
|
||||
protected static class Factory implements RingAction.Factory {
|
||||
@Override
|
||||
public @NotNull Supplier<RingAction> newFromGui(@NotNull Screen screen) {
|
||||
return () -> null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable RingAction parse(@NotNull Config config) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,12 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -28,7 +30,7 @@ import java.util.Map;
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public final class MidnightRing {
|
||||
public static final int ELEMENT_SIZE = 50;
|
||||
public static final int ELEMENT_SIZE = 75;
|
||||
|
||||
private final Map<String, RingAction.Factory> actionFactories = new Object2ObjectOpenHashMap<>();
|
||||
private final List<RingPage> pages = new ArrayList<>(Collections.singletonList(RingPage.DEFAULT));
|
||||
@@ -41,7 +43,7 @@ public final class MidnightRing {
|
||||
|
||||
public void registerAction(@NotNull String name, @NotNull RingAction.Factory factory) {
|
||||
if (this.actionFactories.containsKey(name)) {
|
||||
this.mod.warn("Tried to register twice a ring action: \"" + name + "\".");
|
||||
this.mod.warn("Tried to register a ring action twice: \"" + name + "\".");
|
||||
return;
|
||||
}
|
||||
this.actionFactories.put(name, factory);
|
||||
@@ -50,17 +52,54 @@ public final class MidnightRing {
|
||||
/**
|
||||
* Loads the ring from configuration.
|
||||
*/
|
||||
public void load() {
|
||||
// List<Config> configPages = MidnightControlsConfig.ringPages;
|
||||
// if (configPages != null) {
|
||||
// this.pages.clear();
|
||||
// for (var configPage : configPages) {
|
||||
// RingPage.parseRingPage(configPage).ifPresent(this.pages::add);
|
||||
// }
|
||||
// }
|
||||
// if (this.pages.isEmpty()) {
|
||||
// this.pages.add(RingPage.DEFAULT);
|
||||
// }
|
||||
public void loadFromConfig() {
|
||||
List<String> configBindings = MidnightControlsConfig.ringBindings;
|
||||
if (configBindings != null) {
|
||||
this.pages.clear();
|
||||
int bindingIndex = 0;
|
||||
for (int i = 0; i < MathHelper.ceil(configBindings.size() / 8f); ++i) {
|
||||
this.pages.add(new RingPage(i+1 + " / " + MathHelper.ceil(configBindings.size() / 8f)));
|
||||
}
|
||||
|
||||
for (String binding : configBindings) {
|
||||
ButtonBinding buttonBinding = InputManager.getBinding(binding);
|
||||
if (buttonBinding != null) {
|
||||
RingPage page = this.pages.get(MathHelper.floor(bindingIndex / 8f));
|
||||
page.actions[bindingIndex - 8 * (MathHelper.floor(bindingIndex / 8f))] = (new ButtonBindingRingAction(buttonBinding));
|
||||
++bindingIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.pages.isEmpty()) {
|
||||
this.pages.add(RingPage.DEFAULT);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Loads the ring from all unbound keys.
|
||||
*/
|
||||
public void loadFromUnbound() {
|
||||
List<ButtonBinding> unboundBindings = InputManager.getUnboundBindings();
|
||||
if (unboundBindings != null) {
|
||||
this.pages.clear();
|
||||
int bindingIndex = 0;
|
||||
for (int i = 0; i < MathHelper.ceil(unboundBindings.size() / 8f); ++i) {
|
||||
this.pages.add(new RingPage(i+1 + " / " + MathHelper.ceil(unboundBindings.size() / 8f)));
|
||||
}
|
||||
|
||||
for (ButtonBinding buttonBinding : unboundBindings) {
|
||||
if (buttonBinding != null) {
|
||||
RingPage page = this.pages.get(MathHelper.floor(bindingIndex / 8f));
|
||||
page.actions[bindingIndex - 8 * (MathHelper.floor(bindingIndex / 8f))] = (new ButtonBindingRingAction(buttonBinding));
|
||||
++bindingIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.pages.isEmpty()) {
|
||||
this.pages.add(RingPage.DEFAULT);
|
||||
}
|
||||
}
|
||||
public int getMaxPages() {
|
||||
return this.pages.size();
|
||||
}
|
||||
|
||||
public @NotNull RingPage getCurrentPage() {
|
||||
@@ -70,4 +109,13 @@ public final class MidnightRing {
|
||||
this.currentPage = 0;
|
||||
return this.pages.get(this.currentPage);
|
||||
}
|
||||
public void cyclePage(boolean forwards) {
|
||||
if (forwards) {
|
||||
if (currentPage < pages.size()-1) ++currentPage;
|
||||
else currentPage = 0;
|
||||
} else {
|
||||
if (currentPage > 0) --currentPage;
|
||||
else currentPage = pages.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,9 @@ package eu.midnightdust.midnightcontrols.client.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
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.util.math.MatrixStack;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -29,12 +27,10 @@ import java.util.function.Supplier;
|
||||
* @version 1.5.0
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public abstract class RingAction extends DrawableHelper implements Nameable {
|
||||
protected Config config;
|
||||
public abstract class RingAction implements Nameable {
|
||||
protected boolean activated = false;
|
||||
|
||||
public RingAction(@NotNull Config config) {
|
||||
this.config = config;
|
||||
public RingAction() {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,7 +39,7 @@ public abstract class RingAction extends DrawableHelper implements Nameable {
|
||||
* @return the text name
|
||||
*/
|
||||
public Text getTextName() {
|
||||
return new TranslatableText(this.getName());
|
||||
return Text.translatable(this.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,12 +59,12 @@ public abstract class RingAction extends DrawableHelper implements Nameable {
|
||||
|
||||
public abstract void onAction(@NotNull RingButtonMode mode);
|
||||
|
||||
public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
|
||||
fill(matrices, x, y, x + MidnightRing.ELEMENT_SIZE, y + MidnightRing.ELEMENT_SIZE, hovered ? 0xbb777777 : 0xbb000000);
|
||||
drawIcon(matrices, textRenderer, x, y, hovered);
|
||||
public void render(@NotNull DrawContext context, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered, int index) {
|
||||
context.fill(x, y, x + MidnightRing.ELEMENT_SIZE, y + MidnightRing.ELEMENT_SIZE, hovered || RingPage.selected == index ? 0xbb777777 : 0xbb000000);
|
||||
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}.
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
package eu.midnightdust.midnightcontrols.client.ring;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -31,7 +30,7 @@ public enum RingButtonMode implements Nameable {
|
||||
|
||||
RingButtonMode(@NotNull String name) {
|
||||
this.name = name;
|
||||
this.text = new TranslatableText(this.getTranslationKey());
|
||||
this.text = Text.translatable(this.getTranslationKey());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,15 +9,12 @@
|
||||
|
||||
package eu.midnightdust.midnightcontrols.client.ring;
|
||||
|
||||
import com.electronwill.nightconfig.core.Config;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Represents a ring page.
|
||||
*
|
||||
@@ -25,11 +22,12 @@ import java.util.Optional;
|
||||
* @version 1.5.0
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class RingPage extends DrawableHelper {
|
||||
public class RingPage {
|
||||
public static final RingPage DEFAULT = new RingPage("Default");
|
||||
|
||||
public final String name;
|
||||
private RingAction[] actions = new RingAction[8];
|
||||
public static int selected = -1;
|
||||
public RingAction[] actions = new RingAction[8];
|
||||
|
||||
public RingPage(@NotNull String name) {
|
||||
this.name = name;
|
||||
@@ -41,14 +39,58 @@ public class RingPage extends DrawableHelper {
|
||||
/**
|
||||
* Renders the ring page.
|
||||
*
|
||||
* @param matrices the matrices
|
||||
* @param context the context
|
||||
* @param width the screen width
|
||||
* @param height the screen height
|
||||
* @param mouseX the mouse X-coordinate
|
||||
* @param mouseY the mouse Y-coordinate
|
||||
* @param tickDelta the tick delta
|
||||
*/
|
||||
public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int width, int height, int mouseX, int mouseY, float tickDelta) {
|
||||
public void render(@NotNull DrawContext context, @NotNull TextRenderer textRenderer, int width, int height, int mouseX, int mouseY, float tickDelta) {
|
||||
int centerX = width / 2;
|
||||
int centerY = height / 2;
|
||||
if (MidnightControlsClient.get().ring.getMaxPages() > 1) context.drawCenteredTextWithShadow(textRenderer, name, centerX, 5, 0xffffff);
|
||||
|
||||
int offset = MidnightRing.ELEMENT_SIZE + (MidnightRing.ELEMENT_SIZE / 2) + 5;
|
||||
|
||||
int y = centerY - offset;
|
||||
int x = centerX - offset;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
var ringAction = this.actions[i];
|
||||
if (ringAction != null)
|
||||
ringAction.render(context, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
||||
x += MidnightRing.ELEMENT_SIZE + 5;
|
||||
}
|
||||
y += MidnightRing.ELEMENT_SIZE + 5;
|
||||
x = centerX - offset;
|
||||
for (int i = 3; i < 5; i++) {
|
||||
var ringAction = this.actions[i];
|
||||
if (ringAction != null)
|
||||
ringAction.render(context, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
||||
x += (MidnightRing.ELEMENT_SIZE + 5) * 2;
|
||||
}
|
||||
y += MidnightRing.ELEMENT_SIZE + 5;
|
||||
x = centerX - offset;
|
||||
for (int i = 5; i < 8; i++) {
|
||||
var ringAction = this.actions[i];
|
||||
if (ringAction != null)
|
||||
ringAction.render(context, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i);
|
||||
x += MidnightRing.ELEMENT_SIZE + 5;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isHovered(int x, int y, int mouseX, int mouseY) {
|
||||
return mouseX >= x && mouseY >= y && mouseX <= x + MidnightRing.ELEMENT_SIZE && mouseY <= y + MidnightRing.ELEMENT_SIZE && selected < 0;
|
||||
}
|
||||
/**
|
||||
* Renders the ring page.
|
||||
*
|
||||
* @param width the screen width
|
||||
* @param height the screen height
|
||||
* @param mouseX the mouse X-coordinate
|
||||
* @param mouseY the mouse Y-coordinate
|
||||
*/
|
||||
public boolean onClick(int width, int height, int mouseX, int mouseY) {
|
||||
int centerX = width / 2;
|
||||
int centerY = height / 2;
|
||||
|
||||
@@ -58,48 +100,32 @@ public class RingPage extends DrawableHelper {
|
||||
int x = centerX - offset;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
var ringAction = this.actions[i];
|
||||
if (ringAction != null)
|
||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
|
||||
x += 55;
|
||||
if (ringAction != null && isHovered(x,y,mouseX,mouseY)) {
|
||||
ringAction.activate(RingButtonMode.PRESS);
|
||||
return true;
|
||||
}
|
||||
x += MidnightRing.ELEMENT_SIZE + 5;
|
||||
}
|
||||
y += 55;
|
||||
y += MidnightRing.ELEMENT_SIZE + 5;
|
||||
x = centerX - offset;
|
||||
for (int i = 3; i < 5; i++) {
|
||||
var ringAction = this.actions[i];
|
||||
if (ringAction != null)
|
||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
|
||||
x += 55 * 2;
|
||||
if (ringAction != null && isHovered(x,y,mouseX,mouseY)) {
|
||||
ringAction.activate(RingButtonMode.PRESS);
|
||||
return true;
|
||||
}
|
||||
x += (MidnightRing.ELEMENT_SIZE + 5) * 2;
|
||||
}
|
||||
y += 55;
|
||||
y += MidnightRing.ELEMENT_SIZE + 5;
|
||||
x = centerX - offset;
|
||||
for (int i = 5; i < 8; i++) {
|
||||
var ringAction = this.actions[i];
|
||||
if (ringAction != null)
|
||||
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
|
||||
x += 55;
|
||||
if (ringAction != null && isHovered(x,y,mouseX,mouseY)) {
|
||||
ringAction.activate(RingButtonMode.PRESS);
|
||||
return true;
|
||||
}
|
||||
x += MidnightRing.ELEMENT_SIZE + 5;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isHovered(int x, int y, int mouseX, int mouseY) {
|
||||
return mouseX >= x && mouseY >= y && mouseX <= x + MidnightRing.ELEMENT_SIZE && mouseY <= y + MidnightRing.ELEMENT_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to parse a ring page configuration.
|
||||
*
|
||||
* @param config the configuration
|
||||
* @return an optional ring page
|
||||
*/
|
||||
public static @NotNull Optional<RingPage> parseRingPage(@NotNull Config config) {
|
||||
String name = config.get("name");
|
||||
if (name == null)
|
||||
return Optional.empty();
|
||||
|
||||
var page = new RingPage(name);
|
||||
|
||||
List<Config> actionConfigs = config.get("actions");
|
||||
|
||||
|
||||
return Optional.of(page);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package eu.midnightdust.midnightcontrols.client.touch;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import eu.midnightdust.midnightcontrols.client.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 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.getTargettedObject(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.getTargettedObject(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.getTargettedObject(mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
public static boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||
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.getTargettedObject(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.interactionManager.hasCreativeInventory())) {
|
||||
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,68 @@
|
||||
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.util.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 getTargettedObject(double mouseX, double mouseY) {
|
||||
if (MidnightControlsConfig.touchMode == TouchMode.CROSSHAIR || PlatformFunctions.isModLoaded("vulkanmod")) {
|
||||
return client.crosshairTarget;
|
||||
}
|
||||
Vec3d near = screenSpaceToWorldSpace(mouseX, mouseY, 0);
|
||||
Vec3d far = screenSpaceToWorldSpace(mouseX, mouseY, 1);
|
||||
EntityHitResult entityCast = ProjectileUtil.raycast(client.player, near, far, Box.from(client.player.getPos()).expand(getPlayerRange(client)), entity -> (!entity.isSpectator() && entity.isAttackable()), getPlayerRange(client) * getPlayerRange(client));
|
||||
|
||||
if (entityCast != null && entityCast.getType() == HitResult.Type.ENTITY) return entityCast;
|
||||
|
||||
BlockHitResult result = client.world.raycast(new RaycastContext(near, far, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.ANY, client.player));
|
||||
|
||||
if (client.player.getPos().distanceTo(result.getPos()) > getPlayerRange(client)) 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 org.thinkingstudio.obsidianui.Position;
|
||||
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import net.minecraft.item.ArmorItem;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.UseAction;
|
||||
|
||||
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().getItem() instanceof ArmorItem) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package eu.midnightdust.midnightcontrols.client.touch.gui;
|
||||
|
||||
import org.thinkingstudio.obsidianui.Position;
|
||||
import org.thinkingstudio.obsidianui.widget.SpruceTexturedButtonWidget;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class SilentTexturedButtonWidget extends SpruceTexturedButtonWidget {
|
||||
public SilentTexturedButtonWidget(Position position, int width, int height, Text message, PressAction action, int u, int v, int hoveredVOffset, Identifier texture) {
|
||||
super(position, width, height, message, action, u, v, hoveredVOffset, texture);
|
||||
}
|
||||
|
||||
public SilentTexturedButtonWidget(Position position, int width, int height, Text message, boolean showMessage, PressAction action, int u, int v, int hoveredVOffset, Identifier texture) {
|
||||
super(position, width, height, message, showMessage, action, u, v, hoveredVOffset, texture);
|
||||
}
|
||||
|
||||
public SilentTexturedButtonWidget(Position position, int width, int height, Text message, PressAction action, int u, int v, int hoveredVOffset, Identifier texture, int textureWidth, int textureHeight) {
|
||||
super(position, width, height, message, action, u, v, hoveredVOffset, texture, textureWidth, textureHeight);
|
||||
}
|
||||
|
||||
public SilentTexturedButtonWidget(Position position, int width, int height, Text message, boolean showMessage, PressAction action, int u, int v, int hoveredVOffset, Identifier texture, int textureWidth, int textureHeight) {
|
||||
super(position, width, height, message, showMessage, action, u, v, hoveredVOffset, texture, textureWidth, textureHeight);
|
||||
}
|
||||
@Override
|
||||
public void playDownSound() {}
|
||||
@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);
|
||||
this.setActive(false);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
/**
|
||||
* Represents mouse's extra access.
|
||||
*/
|
||||
public interface MouseAccessor {
|
||||
void midnightcontrols$onCursorPos(long window, double x, double y);
|
||||
}
|
||||
@@ -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,33 @@
|
||||
package eu.midnightdust.midnightcontrols.packet;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public record ControlsModePacket(String controlsMode) implements CustomPayload {
|
||||
public static final Id<ControlsModePacket> PACKET_ID = new Id<>(MidnightControlsConstants.CONTROLS_MODE_CHANNEL);
|
||||
public static final PacketCodec<RegistryByteBuf, ControlsModePacket> codec = PacketCodec.of(ControlsModePacket::write, ControlsModePacket::read);
|
||||
|
||||
public static ControlsModePacket read(RegistryByteBuf buf) {
|
||||
return new ControlsModePacket(buf.readString(32));
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buf) {
|
||||
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
|
||||
buf.writeString(controlsMode, 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return PACKET_ID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package eu.midnightdust.midnightcontrols.packet;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
|
||||
public record FeaturePacket(MidnightControlsFeature... features) implements CustomPayload {
|
||||
public static final Id<FeaturePacket> PACKET_ID = new Id<>(MidnightControlsConstants.FEATURE_CHANNEL);
|
||||
public static final PacketCodec<RegistryByteBuf, FeaturePacket> codec = PacketCodec.of(FeaturePacket::write, FeaturePacket::read);
|
||||
|
||||
public static FeaturePacket read(RegistryByteBuf buf) {
|
||||
int featureLength = buf.readVarInt();
|
||||
MidnightControlsFeature[] receivedFeatures = new MidnightControlsFeature[featureLength];
|
||||
for (int i = 0; i < featureLength; i++) {
|
||||
var name = buf.readString(64);
|
||||
boolean allowed = buf.readBoolean();
|
||||
var feature = MidnightControlsFeature.fromName(name);
|
||||
if (feature.isPresent()) {
|
||||
feature.get().setAllowed(allowed);
|
||||
receivedFeatures[i] = feature.get();
|
||||
}
|
||||
}
|
||||
return new FeaturePacket(receivedFeatures);
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buf) {
|
||||
if (features.length == 0)
|
||||
throw new IllegalArgumentException("At least one feature must be provided.");
|
||||
|
||||
buf.writeVarInt(features.length);
|
||||
for (var feature : features) {
|
||||
buf.writeString(feature.getName(), 64);
|
||||
buf.writeBoolean(feature.isAllowed());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return PACKET_ID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package eu.midnightdust.midnightcontrols.packet;
|
||||
|
||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.packet.CustomPayload;
|
||||
|
||||
public record HelloPacket(String version, String controlsMode) implements CustomPayload {
|
||||
public static final CustomPayload.Id<HelloPacket> PACKET_ID = new CustomPayload.Id<>(MidnightControlsConstants.HELLO_CHANNEL);
|
||||
public static final PacketCodec<RegistryByteBuf, HelloPacket> codec = PacketCodec.of(HelloPacket::write, HelloPacket::read);
|
||||
|
||||
public static HelloPacket read(RegistryByteBuf buf) {
|
||||
return new HelloPacket(buf.readString(32), buf.readString(32));
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buf) {
|
||||
buf.writeString(version, 32).writeString(controlsMode, 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Id<? extends CustomPayload> getId() {
|
||||
return PACKET_ID;
|
||||
}
|
||||
}
|
||||