Compare commits
4 Commits
architectu
...
1.20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aabb728303 | ||
|
|
3b93a52568 | ||
|
|
797ab519de | ||
|
|
18df94c4e4 |
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve
|
||||||
title: 'Bug: TITLE HERE'
|
title: ''
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
@@ -21,17 +21,15 @@ Steps to reproduce the behavior:
|
|||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
If applicable, add screenshots or videos to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
**Desktop (please complete the following information):**
|
||||||
- OS: [e.g. Windows / Linux / MacOS]
|
- OS: [e.g. Linux]
|
||||||
- Minecraft [e.g. 1.20.4]
|
- Minecraft [e.g. 1.14.4]
|
||||||
- Modloader [e.g. Fabric Loader 0.15.6]
|
- Fabric [e.g. fabric 0.7.2+build.174]
|
||||||
- Fabric/Quilt Libraries [e.g. Fabric Api 0.96.1+1.20.4]
|
- Mods [e.g. aurora_keystrokes v1.0.0, modmenu v1.7.15]
|
||||||
- Mods [e.g. Puzzle v1.6.1, LilTaterReloaded v1.1.15]
|
|
||||||
- Version [e.g. 1.0.0]
|
- Version [e.g. 1.0.0]
|
||||||
- Remove this line if you actually completed it
|
- Branch [e.g. dev]
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
In case of a crash, please provide the crash log.
|
|
||||||
|
|||||||
40
.github/ISSUE_TEMPLATE/controller_support.md
vendored
@@ -1,40 +0,0 @@
|
|||||||
---
|
|
||||||
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
|
name: Feature request
|
||||||
about: Suggest an idea for this project
|
about: Suggest an idea for this project
|
||||||
title: 'Feature: TITLE HERE'
|
title: ''
|
||||||
labels: enhancement
|
labels: enhancement
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
@@ -17,4 +17,4 @@ A clear and concise description of what you want to happen.
|
|||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context or screenshots/videos about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|||||||
20
.github/ISSUE_TEMPLATE/mod_support.md
vendored
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
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.
|
|
||||||
25
.github/workflows/build.yml
vendored
@@ -1,25 +0,0 @@
|
|||||||
name: Build with Gradle
|
|
||||||
|
|
||||||
on: [ push, pull_request ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Validate Gradle Wrapper
|
|
||||||
uses: gradle/actions/wrapper-validation@v3
|
|
||||||
- name: Set up JDK 21
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: 21
|
|
||||||
check-latest: true
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: ./gradlew build
|
|
||||||
- name: Upload artifacts to GitHub
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: MidnightControls-Artifacts
|
|
||||||
path: /build/libs/
|
|
||||||
23
.github/workflows/gradlebuild.yml
vendored
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
name: Gradle Build
|
||||||
|
|
||||||
|
on: [ push, pull_request ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK 16
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 16
|
||||||
|
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
|
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew build
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Artifacts
|
||||||
|
path: ./build/libs/
|
||||||
40
.github/workflows/publish.yml → .github/workflows/gradlepublish.yml
vendored
Normal file → Executable file
@@ -1,24 +1,30 @@
|
|||||||
name: Publish to Modrinth
|
name: Gradle Package
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
push:
|
||||||
types:
|
tags:
|
||||||
- published
|
- '*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
build:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Repository
|
- uses: actions/checkout@v2
|
||||||
uses: actions/checkout@v4
|
- name: Set up JDK 16
|
||||||
- name: Validate Gradle Wrapper
|
uses: actions/setup-java@v1
|
||||||
uses: gradle/actions/wrapper-validation@v3
|
|
||||||
- name: Set up JDK 21
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
java-version: 16
|
||||||
java-version: 21
|
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
check-latest: true
|
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew build
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Artifacts
|
||||||
|
path: ./build/libs/
|
||||||
|
|
||||||
# The USERNAME and PASSWORD need to correspond to the credentials environment variables used in
|
# The USERNAME and PASSWORD need to correspond to the credentials environment variables used in
|
||||||
# the publishing section of your build.gradle
|
# the publishing section of your build.gradle
|
||||||
- name: Publish to GitHub Packages and other Mavens
|
- name: Publish to GitHub Packages and other Mavens
|
||||||
@@ -32,7 +38,3 @@ jobs:
|
|||||||
midnightcontrols_MAVEN: ${{ secrets.MAVEN_URL }}
|
midnightcontrols_MAVEN: ${{ secrets.MAVEN_URL }}
|
||||||
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||||
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||||
- name: Publish to Modrinth
|
|
||||||
env:
|
|
||||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
|
||||||
run: ./gradlew publishModrinth
|
|
||||||
23
.github/workflows/modrinth_update.yml
vendored
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
name: Gradle Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK 16
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 16
|
||||||
|
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
|
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
env:
|
||||||
|
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||||
|
run: ./gradlew publishModrinth
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
[](https://github.com/TeamMidnightDust/MidnightControls/releases)
|
[](https://github.com/TeamMidnightDust/MidnightControls/releases)
|
||||||

|

|
||||||
[![Mod loader: Quilt/Fabric]][Quilt]
|
[![Mod loader: Quilt/Fabric]][Quilt]
|
||||||
[](https://www.oracle.com/java/technologies/downloads/#java21)
|
[](https://www.oracle.com/java/technologies/downloads/#java17)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
A Fabric Minecraft mod which adds better controls, reach-around and controller support.
|
A Fabric Minecraft mod which adds better controls, reach-around and controller support.
|
||||||
@@ -64,7 +64,11 @@ After this is done, everything should be built just fine!
|
|||||||
|
|
||||||
## FAQ:
|
## FAQ:
|
||||||
### The controller does not work, and it's name appears in orange, what can I do?
|
### 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/)
|
Orange controller names indicate a missing controller mapping.
|
||||||
|
Download [GamepadTool](https://generalarcade.com/gamepadtool/), create and copy a mapping, go to MidnightControls' Mappings File Editor and paste the string.
|
||||||
|
Alternatively, you can use [AntiMicroX](https://github.com/AntiMicroX/antimicroX) to create the mappings, in case the Gamepad Tool is not working for you.
|
||||||
|
If that works, you might as well consider submitting the mapping by opening a PR in this repo: https://github.com/gabomdq/SDL_GameControllerDB
|
||||||
|
That will make sure other people using the same controller as you don't have to use gamepad-tool anymore.
|
||||||
|
|
||||||
[Quilt]: https://quiltmc.org
|
[Quilt]: https://quiltmc.org
|
||||||
|
|
||||||
|
|||||||
232
build.gradle
@@ -1,88 +1,186 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "architectury-plugin" version "3.4-SNAPSHOT"
|
id 'fabric-loom' version '1.1-SNAPSHOT'
|
||||||
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false
|
id 'java-library'
|
||||||
id "me.shedaniel.unified-publishing" version "0.1.+" apply false
|
id 'maven-publish'
|
||||||
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
||||||
|
id 'com.modrinth.minotaur' version '2.+'
|
||||||
|
id 'net.darkhax.curseforgegradle' version '1.+'
|
||||||
}
|
}
|
||||||
|
|
||||||
architectury {
|
import net.darkhax.curseforgegradle.TaskPublishCurseForge
|
||||||
minecraft = rootProject.minecraft_version
|
|
||||||
|
group = project.maven_group
|
||||||
|
version = "${project.mod_version}+${getMCVersionString()}"
|
||||||
|
|
||||||
|
// This field defines the Java version your mod target.
|
||||||
|
def targetJavaVersion = 17
|
||||||
|
|
||||||
|
boolean isMCVersionNonRelease() {
|
||||||
|
return project.minecraft_version.matches('^\\d\\dw\\d\\d[a-z]$')
|
||||||
|
|| project.minecraft_version.matches('\\d+\\.\\d+-(pre|rc)(\\d+)')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getMCVersionString() {
|
||||||
|
if (isMCVersionNonRelease() || project.minecraft_version == "1.20.4") {
|
||||||
|
return project.minecraft_version
|
||||||
|
}
|
||||||
|
def version = project.minecraft_version.split('\\.')
|
||||||
|
return version[0] + '.' + version[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean pingUrl(String address) {
|
||||||
|
try {
|
||||||
|
def conn = (HttpURLConnection) new URL(address).openConnection()
|
||||||
|
int responseCode = conn.getResponseCode()
|
||||||
|
return (200 <= responseCode && responseCode <= 399)
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String parseReadme() {
|
||||||
|
def excludeRegex = /(?m)<!-- modrinth_exclude\.start -->(.|\n)*?<!-- modrinth_exclude\.end -->/
|
||||||
|
def linkRegex = /!\[([A-z_ ]+)]\((images\/[A-z.\/_]+)\)/
|
||||||
|
|
||||||
|
def readme = (String) file('README.md').text
|
||||||
|
readme = readme.replaceAll(excludeRegex, '')
|
||||||
|
return readme
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
maven { url 'https://aperlambda.github.io/maven' }
|
||||||
maven {
|
maven {
|
||||||
url = "https://api.modrinth.com/maven"
|
name 'Gegy'
|
||||||
|
url 'https://maven.gegy.dev'
|
||||||
}
|
}
|
||||||
flatDir {
|
maven {
|
||||||
dirs("localMaven")
|
name = "CottonMC"
|
||||||
|
url = "https://server.bbkr.space/artifactory/libs-release"
|
||||||
}
|
}
|
||||||
|
maven { url "https://maven.terraformersmc.com/releases/" }
|
||||||
|
maven { url 'https://maven.kosmx.dev' }
|
||||||
|
maven { url 'https://maven.isxander.dev/releases' }
|
||||||
|
maven { url 'https://maven.shedaniel.me/' }
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
maven { url "https://api.modrinth.com/maven" }
|
||||||
|
maven { url 'https://maven.quiltmc.org/repository/release'}
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
configurations {
|
||||||
apply plugin: "dev.architectury.loom"
|
shadow
|
||||||
repositories {
|
api.extendsFrom shadow
|
||||||
maven {
|
|
||||||
url = "https://api.modrinth.com/maven"
|
|
||||||
}
|
|
||||||
maven { url 'https://jitpack.io' }
|
|
||||||
flatDir {
|
|
||||||
dirs("../localMaven")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
|
|
||||||
// The following line declares the mojmap mappings, you may use other mappings as well
|
|
||||||
//mappings loom.officialMojangMappings()
|
|
||||||
// The following line declares the yarn mappings you may select this one as well.
|
|
||||||
mappings loom.layered {
|
|
||||||
it.mappings("net.fabricmc:yarn:$rootProject.yarn_mappings:v2")
|
|
||||||
it.mappings("dev.architectury:yarn-mappings-patch-neoforge:$rootProject.yarn_mappings_patch_neoforge_version")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
//to change the versions see the gradle.properties file
|
||||||
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
|
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||||
|
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
|
|
||||||
allprojects {
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
apply plugin: "java"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||||
apply plugin: "architectury-plugin"
|
|
||||||
apply plugin: "maven-publish"
|
|
||||||
|
|
||||||
archivesBaseName = rootProject.archives_base_name
|
modImplementation ("dev.lambdaurora:spruceui:${project.spruceui_version}") {
|
||||||
version = rootProject.mod_version
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
group = rootProject.maven_group
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven { url 'https://aperlambda.github.io/maven' }
|
|
||||||
}
|
}
|
||||||
dependencies {
|
include "dev.lambdaurora:spruceui:${project.spruceui_version}"
|
||||||
implementation('org.aperlambda:lambdajcommon:1.8.1') {
|
api('org.aperlambda:lambdajcommon:1.8.1') {
|
||||||
exclude group: 'com.google.code.gson'
|
exclude group: 'com.google.code.gson'
|
||||||
exclude group: 'com.google.guava'
|
exclude group: 'com.google.guava'
|
||||||
}
|
}
|
||||||
|
include 'org.aperlambda:lambdajcommon:1.8.1'
|
||||||
|
|
||||||
|
modCompileOnlyApi ("com.terraformersmc:modmenu:${project.modmenu_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
// Compatibility mods
|
||||||
options.encoding = "UTF-8"
|
|
||||||
options.release = 21
|
// 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}")
|
||||||
ext {
|
// modImplementation "io.github.ennuil:LibZoomer:${project.libzoomer_version}"
|
||||||
releaseChangelog = {
|
|
||||||
def changes = new StringBuilder()
|
modCompileOnlyApi "io.github.cottonmc:LibGui:${project.libgui_version}"
|
||||||
changes << "## MidnightControls v$project.version for $project.minecraft_version\n[View the changelog](https://www.github.com/TeamMidnightDust/MidnightControls/commits/)"
|
modCompileOnlyApi "org.quiltmc:quilt-json5:1.0.0"
|
||||||
def proc = "git log --max-count=1 --pretty=format:%s".execute()
|
modCompileOnly "maven.modrinth:sodium:${project.sodium_version}"
|
||||||
proc.in.eachLine { line ->
|
modCompileOnlyApi "maven.modrinth:emi:${project.emi_version}"
|
||||||
def processedLine = line.toString()
|
modCompileOnlyApi "maven.modrinth:emotecraft:${project.emotecraft_version}"
|
||||||
if (!processedLine.contains("New translations") && !processedLine.contains("Merge") && !processedLine.contains("branch")) {
|
modCompileOnlyApi "io.github.kosmx:bendy-lib:${project.bendylib_version}"
|
||||||
changes << "\n- ${processedLine.capitalize()}"
|
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}"
|
||||||
proc.waitFor()
|
// Required for Inventory Tabs
|
||||||
return changes.toString()
|
modCompileOnlyApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") {
|
||||||
}
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}"
|
||||||
withSourcesJar()
|
include "maven.modrinth:midnightlib:${project.midnightlib_version}"
|
||||||
|
|
||||||
|
shadow 'com.electronwill.night-config:core:3.6.3'
|
||||||
|
shadow 'com.electronwill.night-config:toml:3.6.3'
|
||||||
|
apply plugin: 'java-library'
|
||||||
|
}
|
||||||
|
loom {
|
||||||
|
accessWidenerPath = file("src/main/resources/midnightcontrols.accesswidener")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.toVersion(targetJavaVersion)
|
||||||
|
targetCompatibility = JavaVersion.toVersion(targetJavaVersion)
|
||||||
|
|
||||||
|
withSourcesJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
it.options.encoding = 'UTF-8'
|
||||||
|
|
||||||
|
it.options.release.set(targetJavaVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
inputs.property 'version', project.version
|
||||||
|
|
||||||
|
filesMatching('fabric.mod.json') {
|
||||||
|
expand 'version': project.version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
modrinth {
|
||||||
|
token = System.getenv("MODRINTH_TOKEN") // Remember to have the MODRINTH_TOKEN environment variable set or else this will fail - just make sure it stays private!
|
||||||
|
projectId = project.archives_base_name // This can be the project ID or the slug. Either will work!
|
||||||
|
versionNumber = project.version // You don't need to set this manually. Will fail if Modrinth has this version already
|
||||||
|
versionName = "MidnightControls " + project.mod_version + " - " + project.minecraft_version
|
||||||
|
versionType = isMCVersionNonRelease() ? "beta" : "release" // Can also be `beta` or `alpha`
|
||||||
|
uploadFile = remapJar // With Loom, this MUST be set to `remapJar` instead of `jar`!
|
||||||
|
gameVersions = [(String) project.minecraft_version] // Must be an array, even with only one version
|
||||||
|
loaders = ["fabric","quilt"] // Must also be an array - no need to specify this if you're using Loom or ForgeGradle
|
||||||
|
dependencies { // A special DSL for creating dependencies
|
||||||
|
// scope.type
|
||||||
|
// The scope can be `required`, `optional`, `incompatible`, or `embedded`
|
||||||
|
// The type can either be `project` or `version`
|
||||||
|
required.project "midnightlib" // Creates a new required dependency on MidnightLib
|
||||||
|
}
|
||||||
|
changelog = project.changelog
|
||||||
|
}
|
||||||
|
tasks.register('publishCurseForge', TaskPublishCurseForge) {
|
||||||
|
|
||||||
|
// This token is used to authenticate with CurseForge. It should be handled
|
||||||
|
// with the same level of care and security as your actual password. You
|
||||||
|
// should never share your token with an untrusted source or publish it
|
||||||
|
// publicly to GitHub or embed it within a project. The best practice is to
|
||||||
|
// store this token in an environment variable or a build secret.
|
||||||
|
apiToken = System.getenv("CURSEFORGE_TOKEN")
|
||||||
|
|
||||||
|
// Tells CurseForgeGradle to publish the output of the jar task. This will
|
||||||
|
// return a UploadArtifact object that can be used to further configure the
|
||||||
|
// file.
|
||||||
|
def mainFile = upload(project.curseforge_id, remapJar)
|
||||||
|
mainFile.changelog = project.changelog
|
||||||
|
mainFile.displayName = "MidnightControls " + project.mod_version + " - " + project.minecraft_version
|
||||||
|
mainFile.addModLoader("Fabric", "Quilt")
|
||||||
|
mainFile.addRequirement("midnightlib")
|
||||||
|
mainFile.releaseType = "release"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
architectury {
|
|
||||||
common(rootProject.enabled_platforms.split(","))
|
|
||||||
}
|
|
||||||
loom {
|
|
||||||
accessWidenerPath = file("src/main/resources/midnightcontrols.accesswidener")
|
|
||||||
}
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
name 'Gegy'
|
|
||||||
url 'https://maven.gegy.dev'
|
|
||||||
}
|
|
||||||
maven {
|
|
||||||
name = "CottonMC"
|
|
||||||
url = "https://server.bbkr.space/artifactory/libs-release"
|
|
||||||
}
|
|
||||||
maven { url "https://maven.terraformersmc.com/releases/" }
|
|
||||||
maven { url 'https://maven.kosmx.dev' }
|
|
||||||
maven { url 'https://maven.isxander.dev/releases' }
|
|
||||||
maven { url 'https://maven.shedaniel.me/' }
|
|
||||||
maven { url 'https://jitpack.io' }
|
|
||||||
maven { url "https://api.modrinth.com/maven" }
|
|
||||||
maven { url 'https://maven.quiltmc.org/repository/release'}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
|
|
||||||
// Do NOT use other classes from fabric loader
|
|
||||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
|
||||||
// Using the Fabric version of midnightlib here to create a common config and get useful utilities
|
|
||||||
// Just make sure NOT to use classes from the .fabric classpath
|
|
||||||
modCompileOnlyApi "maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric"
|
|
||||||
modCompileOnlyApi "maven.modrinth:obsidianui:${rootProject.obsidianui_version}-fabric"
|
|
||||||
modCompileOnlyApi ("com.terraformersmc:modmenu:${project.modmenu_version}") {
|
|
||||||
exclude(group: "net.fabricmc.fabric-api")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compatibility mods
|
|
||||||
modCompileOnlyApi "io.github.cottonmc:LibGui:${project.libgui_version}"
|
|
||||||
modCompileOnlyApi "org.quiltmc:quilt-json5:1.0.0"
|
|
||||||
modImplementation "maven.modrinth:sodium:${project.sodium_version}-fabric"
|
|
||||||
modCompileOnlyApi "maven.modrinth:emi:${project.emi_version}"
|
|
||||||
modImplementation "maven.modrinth:emotecraft:${project.emotecraft_version}"
|
|
||||||
modCompileOnlyApi "io.github.kosmx:bendy-lib:${project.bendylib_version}"
|
|
||||||
modCompileOnlyApi "dev.isxander:yet-another-config-lib:${project.yacl_version}"
|
|
||||||
modCompileOnlyApi "maven.modrinth:inventory-tabs-updated:${project.inventorytabs_version}"
|
|
||||||
modCompileOnlyApi "maven.modrinth:bedrockify:${project.bedrockify_version}"
|
|
||||||
// Required for Inventory Tabs
|
|
||||||
modCompileOnlyApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") {
|
|
||||||
exclude(group: "net.fabricmc.fabric-api")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
mavenCommon(MavenPublication) {
|
|
||||||
artifactId = rootProject.archives_base_name
|
|
||||||
from components.java
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
|
||||||
repositories {
|
|
||||||
// Add repositories to publish to here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +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;
|
|
||||||
|
|
||||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the MidnightControls mod.
|
|
||||||
*
|
|
||||||
* @author LambdAurora & Motschen
|
|
||||||
* @version 1.8.0
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public class MidnightControls {
|
|
||||||
public static boolean isExtrasLoaded;
|
|
||||||
|
|
||||||
public static final Logger logger = LogManager.getLogger("MidnightControls");
|
|
||||||
|
|
||||||
public static void init() {
|
|
||||||
isExtrasLoaded = PlatformFunctions.isModLoaded("midnightcontrols-extra");
|
|
||||||
log("Initializing MidnightControls...");
|
|
||||||
}
|
|
||||||
public static Identifier id(String path) {
|
|
||||||
return Identifier.of(MidnightControlsConstants.NAMESPACE, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a message to the terminal.
|
|
||||||
*
|
|
||||||
* @param info the message to print
|
|
||||||
*/
|
|
||||||
public static void log(String info) {
|
|
||||||
logger.info("[MidnightControls] {}", info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints a warning to the terminal.
|
|
||||||
*
|
|
||||||
* @param warning the warning to print
|
|
||||||
*/
|
|
||||||
public static void warn(String warning) {
|
|
||||||
logger.warn("[MidnightControls] {}", warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,819 +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;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.LibGuiCompat;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.YACLCompat;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.util.InventoryUtil;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.util.storage.ButtonStorage;
|
|
||||||
import net.minecraft.client.gui.screen.option.KeybindsScreen;
|
|
||||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
|
||||||
import net.minecraft.client.gui.widget.PressableWidget;
|
|
||||||
import net.minecraft.client.gui.widget.SliderWidget;
|
|
||||||
import net.minecraft.entity.vehicle.BoatEntity;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.container.SpruceEntryListWidget;
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
|
|
||||||
import org.thinkingstudio.obsidianui.navigation.NavigationDirection;
|
|
||||||
import org.thinkingstudio.obsidianui.screen.SpruceScreen;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.AbstractSprucePressableButtonWidget;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.SpruceElement;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.SpruceLabelWidget;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.container.SpruceParentWidget;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.gui.Element;
|
|
||||||
import net.minecraft.client.gui.ParentElement;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
|
||||||
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.MerchantScreen;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.StonecutterScreen;
|
|
||||||
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
|
|
||||||
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
|
|
||||||
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
|
||||||
import net.minecraft.text.TranslatableTextContent;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
import org.lwjgl.glfw.GLFWGamepadState;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the midnightcontrols' input handler.
|
|
||||||
*
|
|
||||||
* @author Motschen, LambdAurora
|
|
||||||
* @version 1.10.0
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
public class MidnightInput {
|
|
||||||
public static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
|
||||||
// Cooldowns
|
|
||||||
public int actionGuiCooldown = 0;
|
|
||||||
public int joystickCooldown = 0;
|
|
||||||
public boolean ignoreNextARelease = false;
|
|
||||||
public boolean ignoreNextXRelease = false;
|
|
||||||
private double targetYaw = 0.0;
|
|
||||||
private double targetPitch = 0.0;
|
|
||||||
private float prevXAxis = 0.f;
|
|
||||||
private float prevYAxis = 0.f;
|
|
||||||
public float mouseSpeedX = 0.f;
|
|
||||||
public float mouseSpeedY = 0.f;
|
|
||||||
public int inventoryInteractionCooldown = 0;
|
|
||||||
public int screenCloseCooldown = 0;
|
|
||||||
|
|
||||||
private ControllerControlsWidget controlsInput = null;
|
|
||||||
|
|
||||||
public MidnightInput() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called every Minecraft tick.
|
|
||||||
*/
|
|
||||||
public void tick() {
|
|
||||||
this.targetYaw = 0.F;
|
|
||||||
this.targetPitch = 0.F;
|
|
||||||
|
|
||||||
// Handles the key bindings.
|
|
||||||
if (MidnightControlsClient.BINDING_LOOK_UP.isPressed()) {
|
|
||||||
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_Y, -0.8F, 0d));
|
|
||||||
} else if (MidnightControlsClient.BINDING_LOOK_DOWN.isPressed()) {
|
|
||||||
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 0d));
|
|
||||||
}
|
|
||||||
if (MidnightControlsClient.BINDING_LOOK_LEFT.isPressed()) {
|
|
||||||
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_X, -0.8F, 0d));
|
|
||||||
} else if (MidnightControlsClient.BINDING_LOOK_RIGHT.isPressed()) {
|
|
||||||
this.handleFlatLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 0d));
|
|
||||||
}
|
|
||||||
|
|
||||||
InputManager.INPUT_MANAGER.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called every Minecraft tick for controller input update.
|
|
||||||
*/
|
|
||||||
public void tickController() {
|
|
||||||
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0)
|
|
||||||
.forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
|
|
||||||
// Decreases the cooldown for GUI actions.
|
|
||||||
if (this.actionGuiCooldown > 0)
|
|
||||||
--this.actionGuiCooldown;
|
|
||||||
if (this.screenCloseCooldown > 0)
|
|
||||||
--this.screenCloseCooldown;
|
|
||||||
if (this.joystickCooldown > 0)
|
|
||||||
--this.joystickCooldown;
|
|
||||||
|
|
||||||
InputManager.updateStates();
|
|
||||||
|
|
||||||
var controller = MidnightControlsConfig.getController();
|
|
||||||
|
|
||||||
if (controller.isConnected()) {
|
|
||||||
var state = controller.getState();
|
|
||||||
this.fetchButtonInput(state, false);
|
|
||||||
this.fetchTriggerInput(state, false);
|
|
||||||
this.fetchJoystickInput(state, false, false);
|
|
||||||
}
|
|
||||||
MidnightControlsConfig.getSecondController().filter(Controller::isConnected)
|
|
||||||
.ifPresent(joycon -> {
|
|
||||||
var state = joycon.getState();
|
|
||||||
this.fetchButtonInput(state, true);
|
|
||||||
this.fetchTriggerInput(state, true);
|
|
||||||
this.fetchJoystickInput(state, true, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
boolean allowInput = this.controlsInput == null || this.controlsInput.focusedBinding == null;
|
|
||||||
|
|
||||||
if (allowInput)
|
|
||||||
InputManager.updateBindings();
|
|
||||||
|
|
||||||
if (this.controlsInput != null) {
|
|
||||||
InputManager.STATES.forEach((num, button) -> {
|
|
||||||
if (button.isPressed()) System.out.println(num);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
|
|
||||||
if (MidnightControlsConfig.debug) MidnightControls.log("Starting MidnightInput Button Edit");
|
|
||||||
if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) {
|
|
||||||
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
|
||||||
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
|
||||||
buttons[i] = this.controlsInput.currentButtons.get(i);
|
|
||||||
this.controlsInput.finishBindingEdit(buttons);
|
|
||||||
this.controlsInput = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.inventoryInteractionCooldown > 0)
|
|
||||||
this.inventoryInteractionCooldown--;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* This method is called 1000 times a second for smooth camera input
|
|
||||||
*/
|
|
||||||
public void tickCameraStick() {
|
|
||||||
var controller = MidnightControlsConfig.getController();
|
|
||||||
|
|
||||||
if (controller.isConnected()) {
|
|
||||||
this.fetchJoystickInput(controller.getState(), false, true);
|
|
||||||
}
|
|
||||||
MidnightControlsConfig.getSecondController().filter(Controller::isConnected)
|
|
||||||
.ifPresent(joycon -> this.fetchJoystickInput(joycon.getState(), true, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called before the screen is rendered.
|
|
||||||
*
|
|
||||||
* @param screen the screen to render
|
|
||||||
*/
|
|
||||||
public void onPreRenderScreen(@NotNull Screen screen) {
|
|
||||||
if (!isScreenInteractive(screen)) {
|
|
||||||
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called to update the camera
|
|
||||||
*/
|
|
||||||
public void updateCamera() {
|
|
||||||
if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var player = client.player;
|
|
||||||
if (player == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this.targetYaw != 0.f || this.targetPitch != 0.f) {
|
|
||||||
float rotationYaw = (float) (client.player.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() && client.player.getVehicle() != null) {
|
|
||||||
client.player.getVehicle().onPassengerLookAround(client.player);
|
|
||||||
}
|
|
||||||
client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called when a Screen is opened.
|
|
||||||
*
|
|
||||||
* @param windowWidth the window width
|
|
||||||
* @param windowHeight the window height
|
|
||||||
*/
|
|
||||||
public void onScreenOpen(int windowWidth, int windowHeight) {
|
|
||||||
if (client.currentScreen == null) {
|
|
||||||
this.mouseSpeedX = this.mouseSpeedY = 0.0F;
|
|
||||||
InputManager.INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight);
|
|
||||||
} else if (isScreenInteractive(client.currentScreen) && MidnightControlsConfig.virtualMouse) {
|
|
||||||
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), 0, 0);
|
|
||||||
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
|
||||||
}
|
|
||||||
this.inventoryInteractionCooldown = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void beginControlsInput(ControllerControlsWidget widget) {
|
|
||||||
this.controlsInput = widget;
|
|
||||||
if (widget != null) {
|
|
||||||
this.controlsInput.currentButtons.clear();
|
|
||||||
this.controlsInput.waiting = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fetchButtonInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
|
||||||
var buffer = gamepadState.buttons();
|
|
||||||
for (int i = 0; i < buffer.limit(); i++) {
|
|
||||||
int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
|
||||||
boolean pressed = buffer.get() == (byte) 1;
|
|
||||||
var state = ButtonState.NONE;
|
|
||||||
var previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
|
|
||||||
|
|
||||||
if (pressed != previousState.isPressed()) {
|
|
||||||
state = pressed ? ButtonState.PRESS : ButtonState.RELEASE;
|
|
||||||
this.handleButton(ButtonStorage.of(btn, state));
|
|
||||||
if (pressed)
|
|
||||||
BUTTON_COOLDOWNS.put(btn, 5);
|
|
||||||
} else if (pressed) {
|
|
||||||
state = ButtonState.REPEAT;
|
|
||||||
if (BUTTON_COOLDOWNS.getOrDefault(btn, 0) == 0) {
|
|
||||||
BUTTON_COOLDOWNS.put(btn, 5);
|
|
||||||
this.handleButton(ButtonStorage.of(btn, state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InputManager.STATES.put(btn, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil();
|
|
||||||
|
|
||||||
private void fetchJoystickInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon, boolean cameraTick) {
|
|
||||||
var buffer = gamepadState.axes();
|
|
||||||
|
|
||||||
polarUtil.calculate(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X), buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y), 1, MidnightControlsConfig.leftDeadZone);
|
|
||||||
float leftX = polarUtil.polarX;
|
|
||||||
float leftY = polarUtil.polarY;
|
|
||||||
polarUtil.calculate(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X), buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y), 1, MidnightControlsConfig.rightDeadZone);
|
|
||||||
float rightX = polarUtil.polarX;
|
|
||||||
float rightY = polarUtil.polarY;
|
|
||||||
|
|
||||||
boolean isRadialMenu = client.currentScreen instanceof RingScreen || (PlatformFunctions.isModLoaded("emotecraft") && EmotecraftCompat.isEmotecraftScreen(client.currentScreen));
|
|
||||||
|
|
||||||
if (!isRadialMenu) {
|
|
||||||
for (int i = cameraTick ? GLFW_GAMEPAD_AXIS_RIGHT_X : 0; i < (cameraTick ? GLFW_GAMEPAD_AXIS_LEFT_TRIGGER : GLFW_GAMEPAD_AXIS_RIGHT_X); i++) {
|
|
||||||
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
|
||||||
float value = buffer.get(i);
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case GLFW_GAMEPAD_AXIS_LEFT_X -> {
|
|
||||||
if (MidnightControlsConfig.analogMovement) value = leftX;
|
|
||||||
}
|
|
||||||
case GLFW_GAMEPAD_AXIS_LEFT_Y -> {
|
|
||||||
if (MidnightControlsConfig.analogMovement) value = leftY;
|
|
||||||
}
|
|
||||||
case GLFW_GAMEPAD_AXIS_RIGHT_X -> value = rightX;
|
|
||||||
case GLFW_GAMEPAD_AXIS_RIGHT_Y -> value = rightY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y)
|
|
||||||
value *= -1.0F;
|
|
||||||
|
|
||||||
this.handleJoystickAxis(AxisStorage.of(axis, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
boolean leftStickActive = leftX != 0 || leftY != 0;
|
|
||||||
handleRadialMenu(leftStickActive ? leftX : rightX, leftStickActive ? leftY : rightY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fetchTriggerInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
|
||||||
var buffer = gamepadState.axes();
|
|
||||||
|
|
||||||
for (int i = GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; i <= GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER; i++) {
|
|
||||||
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
|
||||||
float value = buffer.get(i);
|
|
||||||
|
|
||||||
this.handleTriggerAxis(AxisStorage.of(axis, value, MidnightControlsConfig.triggerDeadZone));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleButton(ButtonStorage storage) {
|
|
||||||
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
|
||||||
if (storage.state == ButtonState.PRESS && !this.controlsInput.currentButtons.contains(storage.button)) {
|
|
||||||
this.controlsInput.currentButtons.add(storage.button);
|
|
||||||
|
|
||||||
var buttons = new int[this.controlsInput.currentButtons.size()];
|
|
||||||
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
|
||||||
buttons[i] = this.controlsInput.currentButtons.get(i);
|
|
||||||
this.controlsInput.focusedBinding.setButton(buttons);
|
|
||||||
|
|
||||||
this.controlsInput.waiting = false;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client.currentScreen != null && storage.state.isPressed() && storage.button == GLFW_GAMEPAD_BUTTON_Y &&
|
|
||||||
MidnightControlsConfig.arrowScreens.contains(client.currentScreen.getClass().getCanonicalName())) {
|
|
||||||
pressKeyboardKey(client, GLFW.GLFW_KEY_ENTER);
|
|
||||||
this.screenCloseCooldown = 5;
|
|
||||||
}
|
|
||||||
else if (storage.state.isPressed()) {
|
|
||||||
if (client.currentScreen != null && storage.isDpad() && this.actionGuiCooldown == 0) {
|
|
||||||
switch (storage.button) {
|
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> this.handleLeftRight(client.currentScreen, false);
|
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> this.handleLeftRight(client.currentScreen, true);
|
|
||||||
}
|
|
||||||
if (MidnightControlsConfig.wasdScreens.contains(client.currentScreen.getClass().getCanonicalName())) {
|
|
||||||
switch (storage.button) {
|
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> pressKeyboardKey(client, GLFW.GLFW_KEY_W);
|
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> pressKeyboardKey(client, GLFW.GLFW_KEY_S);
|
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> pressKeyboardKey(client, GLFW.GLFW_KEY_A);
|
|
||||||
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> pressKeyboardKey(client, GLFW.GLFW_KEY_D);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
|
|
||||||
if (this.actionGuiCooldown == 0) {
|
|
||||||
var focused = client.currentScreen.getFocused();
|
|
||||||
if (focused != null && isScreenInteractive(client.currentScreen)) {
|
|
||||||
if (this.handleAButton(client.currentScreen, focused)) {
|
|
||||||
this.actionGuiCooldown = 5; // Set the cooldown to 5 ticks to avoid unintended button presses.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (PlatformFunctions.isModLoaded("libgui")) LibGuiCompat.handlePress(client.currentScreen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen)
|
|
||||||
&& this.actionGuiCooldown == 0) {
|
|
||||||
if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt(
|
|
||||||
client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(),
|
|
||||||
client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()) != null) return;
|
|
||||||
if (!this.ignoreNextARelease && client.currentScreen != null) {
|
|
||||||
var accessor = (MouseAccessor) client.mouse;
|
|
||||||
accessor.midnightcontrols$onCursorPos(client.getWindow().getHandle(), client.mouse.getX(), client.mouse.getY());
|
|
||||||
switch (storage.state) {
|
|
||||||
// Button pressed
|
|
||||||
case PRESS -> accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 1, 0);
|
|
||||||
case RELEASE -> { // Button released
|
|
||||||
accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 0, 0);
|
|
||||||
client.currentScreen.setDragging(false);
|
|
||||||
}
|
|
||||||
case REPEAT -> client.currentScreen.setDragging(true); // Button held down / dragging
|
|
||||||
}
|
|
||||||
this.screenCloseCooldown = 5;
|
|
||||||
} else {
|
|
||||||
this.ignoreNextARelease = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_X && client.currentScreen != null && !isScreenInteractive(client.currentScreen)
|
|
||||||
&& this.actionGuiCooldown == 0) {
|
|
||||||
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
|
||||||
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
|
||||||
if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt(
|
|
||||||
mouseX, mouseY) != null) return;
|
|
||||||
if (!this.ignoreNextXRelease && client.currentScreen != null) {
|
|
||||||
if (storage.state == ButtonState.PRESS) client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2);
|
|
||||||
else if (storage.state == ButtonState.RELEASE) client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2);
|
|
||||||
this.screenCloseCooldown = 5;
|
|
||||||
} else {
|
|
||||||
this.ignoreNextXRelease = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void handleTriggerAxis(AxisStorage storage) {
|
|
||||||
storage.setupButtonStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleJoystickAxis(AxisStorage storage) {
|
|
||||||
storage.setupButtonStates();
|
|
||||||
|
|
||||||
this.handleJoystickMovement(storage);
|
|
||||||
|
|
||||||
if (this.handleScreenScrolling(client.currentScreen, storage)) return;
|
|
||||||
|
|
||||||
storage.absValue = (float) MathHelper.clamp(storage.absValue / MidnightControlsConfig.getAxisMaxValue(storage.axis), 0.f, 1.f);
|
|
||||||
if (client.currentScreen == null) {
|
|
||||||
// Handles the look direction.
|
|
||||||
this.handleLook(storage);
|
|
||||||
} else {
|
|
||||||
boolean allowMouseControl = true;
|
|
||||||
|
|
||||||
if (this.actionGuiCooldown == 0 && MidnightControlsConfig.isMovementAxis(storage.axis) && isScreenInteractive(client.currentScreen)) {
|
|
||||||
if (MidnightControlsConfig.isForwardButton(storage.axis, false, storage.buttonState)) {
|
|
||||||
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
|
||||||
} else if (MidnightControlsConfig.isBackButton(storage.axis, false, storage.buttonState)) {
|
|
||||||
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
|
||||||
} else if (MidnightControlsConfig.isLeftButton(storage.axis, false, storage.buttonState)) {
|
|
||||||
allowMouseControl = this.handleLeftRight(client.currentScreen, false);
|
|
||||||
} else if (MidnightControlsConfig.isRightButton(storage.axis, false, storage.buttonState)) {
|
|
||||||
allowMouseControl = this.handleLeftRight(client.currentScreen, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float movementX = 0.f;
|
|
||||||
float movementY = 0.f;
|
|
||||||
|
|
||||||
if (MidnightControlsConfig.isBackButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
|
||||||
movementY = storage.absValue;
|
|
||||||
} else if (MidnightControlsConfig.isForwardButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
|
||||||
movementY = -storage.absValue;
|
|
||||||
} else if (MidnightControlsConfig.isLeftButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
|
||||||
movementX = -storage.absValue;
|
|
||||||
} else if (MidnightControlsConfig.isRightButton(storage.axis, false, (storage.value > 0 ? ButtonState.PRESS : ButtonState.RELEASE))) {
|
|
||||||
movementX = storage.absValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client.currentScreen != null && allowMouseControl) {
|
|
||||||
boolean moving = movementY != 0 || movementX != 0;
|
|
||||||
if (moving) {
|
|
||||||
/*
|
|
||||||
Updates the target mouse position when the initial movement stick movement is detected.
|
|
||||||
It prevents the cursor to jump to the old target mouse position if the user moves the cursor with the mouse.
|
|
||||||
*/
|
|
||||||
if (Math.abs(prevXAxis) < storage.deadZone && Math.abs(prevYAxis) < storage.deadZone) {
|
|
||||||
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mouseSpeedX = movementX;
|
|
||||||
this.mouseSpeedY = movementY;
|
|
||||||
} else {
|
|
||||||
this.mouseSpeedX = 0.f;
|
|
||||||
this.mouseSpeedY = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Math.abs(this.mouseSpeedX) >= .05f || Math.abs(this.mouseSpeedY) >= .05f) {
|
|
||||||
InputManager.queueMoveMousePosition(
|
|
||||||
this.mouseSpeedX * MidnightControlsConfig.mouseSpeed,
|
|
||||||
this.mouseSpeedY * MidnightControlsConfig.mouseSpeed
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
InventoryUtil.moveMouseToClosestSlot(client.currentScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.prevXAxis = movementX;
|
|
||||||
this.prevYAxis = movementY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleJoystickMovement(AxisStorage storage) {
|
|
||||||
float axisValue = storage.absValue;
|
|
||||||
if (!MidnightControlsConfig.analogMovement || (client.player != null && client.player.getVehicle() instanceof BoatEntity)) {
|
|
||||||
axisValue = (float) (storage.absValue - storage.deadZone);
|
|
||||||
axisValue /= (float) (1.0 - storage.deadZone);
|
|
||||||
axisValue *= (float) storage.deadZone;
|
|
||||||
}
|
|
||||||
axisValue = (float) Math.min(axisValue / MidnightControlsConfig.getAxisMaxValue(storage.axis), 1);
|
|
||||||
if (AxisStorage.isLeftAxis(storage.axis)) MidnightControlsCompat.handleMovement(storage, axisValue);
|
|
||||||
InputManager.BUTTON_VALUES.put(storage.getButtonId(true), storage.polarity == AxisStorage.Polarity.PLUS ? axisValue : 0.f);
|
|
||||||
InputManager.BUTTON_VALUES.put(storage.getButtonId(false), storage.polarity == AxisStorage.Polarity.MINUS ? axisValue : 0.f);
|
|
||||||
storage.absValue = axisValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean handleScreenScrolling(Screen screen, AxisStorage storage) {
|
|
||||||
if (screen == null) return false;
|
|
||||||
// @TODO allow rebinding to left stick
|
|
||||||
int preferredAxis = true ? GLFW_GAMEPAD_AXIS_RIGHT_Y : GLFW_GAMEPAD_AXIS_LEFT_Y;
|
|
||||||
|
|
||||||
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
|
||||||
if (storage.buttonState != ButtonState.NONE && !this.controlsInput.currentButtons.contains(storage.getButtonId(storage.buttonState == ButtonState.PRESS))) {
|
|
||||||
|
|
||||||
this.controlsInput.currentButtons.add(storage.getButtonId(storage.buttonState == ButtonState.PRESS));
|
|
||||||
|
|
||||||
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
|
||||||
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
|
||||||
buttons[i] = this.controlsInput.currentButtons.get(i);
|
|
||||||
this.controlsInput.focusedBinding.setButton(buttons);
|
|
||||||
|
|
||||||
this.controlsInput.waiting = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (storage.absValue >= storage.deadZone) {
|
|
||||||
if (screen instanceof CreativeInventoryScreen creativeInventoryScreen) {
|
|
||||||
if (storage.axis == preferredAxis) {
|
|
||||||
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
|
||||||
if (accessor.midnightcontrols$hasScrollbar() && storage.absValue >= storage.deadZone) {
|
|
||||||
creativeInventoryScreen.mouseScrolled(0.0, 0.0, 0, -(storage.value * 0.0175f));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (screen instanceof AdvancementsScreen advancementsScreen) {
|
|
||||||
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X || storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
|
||||||
var accessor = (AdvancementsScreenAccessor) advancementsScreen;
|
|
||||||
AdvancementTab tab = accessor.getSelectedTab();
|
|
||||||
tab.move(storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X ? -storage.value * 1.0 : 0.0, storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y ? -storage.value * 5.0 : 0.0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (screen != null) {
|
|
||||||
if (storage.axis == preferredAxis && !handleListWidgetScrolling(screen.children(), storage.value)) {
|
|
||||||
try {
|
|
||||||
screen.mouseScrolled(0.0, 0.0, 0, -(storage.value * 0.0175f));
|
|
||||||
} catch (NullPointerException ignored) {}
|
|
||||||
} else if (isScreenInteractive(screen)) {
|
|
||||||
if (joystickCooldown == 0) {
|
|
||||||
switch (storage.axis) {
|
|
||||||
case GLFW_GAMEPAD_AXIS_LEFT_Y -> {
|
|
||||||
this.changeFocus(screen, storage.value > 0 ? NavigationDirection.UP : NavigationDirection.DOWN);
|
|
||||||
joystickCooldown = 4;
|
|
||||||
}
|
|
||||||
case GLFW_GAMEPAD_AXIS_LEFT_X -> {
|
|
||||||
this.handleLeftRight(screen, storage.value > 0);
|
|
||||||
joystickCooldown = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public void handleRadialMenu(float x, float y) {
|
|
||||||
int index = -1;
|
|
||||||
float border = 0.3f;
|
|
||||||
if (x < -border) {
|
|
||||||
index = 3;
|
|
||||||
if (y < -border) index = 0;
|
|
||||||
else if (y > border) index = 5;
|
|
||||||
} else if (x > border) {
|
|
||||||
index = 4;
|
|
||||||
if (y < -border) index = 2;
|
|
||||||
else if (y > border) index = 7;
|
|
||||||
} else {
|
|
||||||
if (y < -border) index = 1;
|
|
||||||
else if (y > border) index = 6;
|
|
||||||
}
|
|
||||||
if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index;
|
|
||||||
if (PlatformFunctions.isModLoaded("emotecraft") && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean handleListWidgetScrolling(List<? extends Element> children, float value) {
|
|
||||||
return children.stream().filter(element -> element instanceof SpruceEntryListWidget)
|
|
||||||
.map(element -> (SpruceEntryListWidget<?>) element)
|
|
||||||
.filter(AbstractSpruceWidget::isFocusedOrHovered)
|
|
||||||
.anyMatch(element -> {
|
|
||||||
element.mouseScrolled(0.0, 0.0, 0, -value);
|
|
||||||
return true;
|
|
||||||
}) ||
|
|
||||||
children.stream().filter(element -> element instanceof EntryListWidget)
|
|
||||||
.map(element -> (EntryListWidget<?>) element)
|
|
||||||
.filter(element -> element.getType().isFocused())
|
|
||||||
.anyMatch(element -> {
|
|
||||||
element.mouseScrolled(0.0, 0.0, 0, -value);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
|
|
||||||
if (focused instanceof PressableWidget widget) {
|
|
||||||
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
|
|
||||||
widget.onPress();
|
|
||||||
return true;
|
|
||||||
} else if (focused instanceof AbstractSprucePressableButtonWidget widget) {
|
|
||||||
widget.playDownSound();
|
|
||||||
widget.onPress();
|
|
||||||
return true;
|
|
||||||
} else if (focused instanceof SpruceLabelWidget labelWidget) {
|
|
||||||
labelWidget.onPress();
|
|
||||||
return true;
|
|
||||||
} else if (focused instanceof WorldListWidget list) {
|
|
||||||
list.getSelectedAsOptional().ifPresent(WorldListWidget.WorldEntry::play);
|
|
||||||
return true;
|
|
||||||
} else if (focused instanceof MultiplayerServerListWidget list) {
|
|
||||||
var entry = list.getSelectedOrNull();
|
|
||||||
if (entry instanceof MultiplayerServerListWidget.LanServerEntry || entry instanceof MultiplayerServerListWidget.ServerEntry) {
|
|
||||||
((MultiplayerScreen) screen).select(entry);
|
|
||||||
((MultiplayerScreen) screen).connect();
|
|
||||||
}
|
|
||||||
} else if (focused instanceof SpruceParentWidget) {
|
|
||||||
var childFocused = ((SpruceParentWidget<?>) focused).getFocused();
|
|
||||||
if (childFocused != null)
|
|
||||||
return this.handleAButton(screen, childFocused);
|
|
||||||
} else if (focused instanceof ParentElement widget) {
|
|
||||||
var childFocused = widget.getFocused();
|
|
||||||
if (childFocused != null)
|
|
||||||
return this.handleAButton(screen, childFocused);
|
|
||||||
} else if (PlatformFunctions.isModLoaded("yet-another-config-lib") && YACLCompat.handleAButton(screen, focused)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else pressKeyboardKey(screen, GLFW_KEY_ENTER);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the left and right buttons.
|
|
||||||
*
|
|
||||||
* @param screen the current screen
|
|
||||||
* @param right true if the right button is pressed, else false
|
|
||||||
*/
|
|
||||||
private boolean handleLeftRight(@NotNull Screen screen, boolean right) {
|
|
||||||
if (screen instanceof SpruceScreen spruceScreen) {
|
|
||||||
spruceScreen.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
|
||||||
this.actionGuiCooldown = 5;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (PlatformFunctions.isModLoaded("yet-another-config-lib") && YACLCompat.handleLeftRight(screen, right)) {
|
|
||||||
this.actionGuiCooldown = 5;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var focused = screen.getFocused();
|
|
||||||
if (focused != null)
|
|
||||||
if (this.handleRightLeftElement(focused, right))
|
|
||||||
return this.changeFocus(screen, right ? NavigationDirection.RIGHT : NavigationDirection.LEFT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean handleRightLeftElement(@NotNull Element element, boolean right) {
|
|
||||||
switch (element) {
|
|
||||||
case SpruceElement spruceElement -> {
|
|
||||||
if (spruceElement.requiresCursor())
|
|
||||||
return true;
|
|
||||||
return !spruceElement.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
|
||||||
}
|
|
||||||
case SliderWidget slider -> {
|
|
||||||
if (slider.active) {
|
|
||||||
slider.keyPressed(right ? 262 : 263, 0, 0);
|
|
||||||
this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// case AlwaysSelectedEntryListWidget<?> alwaysSelectedEntryListWidget -> {
|
|
||||||
// //TODO ((EntryListWidgetAccessor) element).midnightcontrols$moveSelection(right ? EntryListWidget.MoveDirection.DOWN : EntryListWidget.MoveDirection.UP);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
case ParentElement entryList -> {
|
|
||||||
var focused = entryList.getFocused();
|
|
||||||
if (focused == null)
|
|
||||||
return true;
|
|
||||||
return this.handleRightLeftElement(focused, right);
|
|
||||||
}
|
|
||||||
default -> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
private double prevX = 0;
|
|
||||||
private double prevY = 0;
|
|
||||||
private double xValue;
|
|
||||||
private AxisStorage.Polarity xPolarity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the look direction input.
|
|
||||||
*
|
|
||||||
* @param storage the state of the provided axis
|
|
||||||
*/
|
|
||||||
public void handleLook(AxisStorage storage) {
|
|
||||||
if (client.player == null || !(storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y || storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X)) return;
|
|
||||||
// Handles the look direction.
|
|
||||||
if (MidnightControlsConfig.cameraMode == CameraMode.FLAT) handleFlatLook(storage);
|
|
||||||
else handleAdaptiveLook(storage);
|
|
||||||
MidnightControlsCompat.handleCamera(this.targetYaw, this.targetPitch);
|
|
||||||
}
|
|
||||||
private void handleFlatLook(AxisStorage storage) {
|
|
||||||
if (storage.polarity != AxisStorage.Polarity.ZERO) {
|
|
||||||
double rotation = Math.pow(storage.value, 2.0) * 0.11D * storage.polarity.multiplier;
|
|
||||||
|
|
||||||
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) this.targetPitch = rotation * MidnightControlsConfig.getRightYAxisSign() * MidnightControlsConfig.yAxisRotationSpeed / 2;
|
|
||||||
else this.targetYaw = rotation * MidnightControlsConfig.getRightXAxisSign() * MidnightControlsConfig.rotationSpeed / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void handleAdaptiveLook(AxisStorage storage) {
|
|
||||||
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
|
|
||||||
xValue = storage.value;
|
|
||||||
xPolarity = storage.polarity;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
double yStep = (MidnightControlsConfig.yAxisRotationSpeed / 50) * 0.6000000238418579 + 0.20000000298023224;
|
|
||||||
double xStep = (MidnightControlsConfig.rotationSpeed / 50) * 0.6000000238418579 + 0.20000000298023224;
|
|
||||||
float yValue = storage.value;
|
|
||||||
AxisStorage.Polarity yPolarity = storage.polarity;
|
|
||||||
|
|
||||||
double cursorDeltaX = 2 * xValue - this.prevX;
|
|
||||||
double cursorDeltaY = 2 * yValue - this.prevY;
|
|
||||||
boolean slowdown = client.options.getPerspective().isFirstPerson() && Objects.requireNonNull(client.player).isUsingSpyglass();
|
|
||||||
double x = cursorDeltaX * xStep * (slowdown ? xStep : 1);
|
|
||||||
double y = cursorDeltaY * yStep * (slowdown ? yStep : 1);
|
|
||||||
|
|
||||||
double powXValue = Math.pow(x, 2.0);
|
|
||||||
double powYValue = Math.pow(y, 2.0);
|
|
||||||
|
|
||||||
if (xPolarity != AxisStorage.Polarity.ZERO) {
|
|
||||||
double sign = MidnightControlsConfig.getRightXAxisSign() * MidnightControlsConfig.rotationSpeed;
|
|
||||||
this.targetYaw = sign * powXValue * 0.11D * xPolarity.multiplier;
|
|
||||||
}
|
|
||||||
if (yPolarity != AxisStorage.Polarity.ZERO) {
|
|
||||||
double sign = MidnightControlsConfig.getRightYAxisSign() * MidnightControlsConfig.yAxisRotationSpeed;
|
|
||||||
this.targetPitch = sign * powYValue * 0.11D * yPolarity.multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.prevY = yValue;
|
|
||||||
this.prevX = xValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void handleTouchscreenLook(AxisStorage storage) {
|
|
||||||
if (storage.polarity != AxisStorage.Polarity.ZERO) {
|
|
||||||
double rotation = storage.value * 0.11D * MidnightControlsConfig.touchSpeed/5;
|
|
||||||
|
|
||||||
if (storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) this.targetPitch = rotation;
|
|
||||||
else this.targetYaw = rotation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean changeFocus(@NotNull Screen screen, NavigationDirection direction) {
|
|
||||||
if (!isScreenInteractive(screen) && !screen.getClass().getCanonicalName().contains("me.jellysquid.mods.sodium.client.gui")) return false;
|
|
||||||
try {
|
|
||||||
if (screen instanceof SpruceScreen spruceScreen) {
|
|
||||||
if (spruceScreen.onNavigation(direction, false)) {
|
|
||||||
this.actionGuiCooldown = 5;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
switch (direction) {
|
|
||||||
case UP -> pressKeyboardKey(screen, GLFW.GLFW_KEY_UP);
|
|
||||||
case DOWN -> pressKeyboardKey(screen, GLFW.GLFW_KEY_DOWN);
|
|
||||||
case LEFT -> pressKeyboardKey(screen, GLFW.GLFW_KEY_LEFT);
|
|
||||||
case RIGHT -> pressKeyboardKey(screen, GLFW.GLFW_KEY_RIGHT);
|
|
||||||
}
|
|
||||||
this.actionGuiCooldown = 5;
|
|
||||||
return true;
|
|
||||||
} catch (Exception exception) {MidnightControls.warn("Unknown exception encountered while trying to change focus: "+exception);}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to go back.
|
|
||||||
*
|
|
||||||
* @param screen the current screen
|
|
||||||
* @return true if successful, else false
|
|
||||||
*/
|
|
||||||
public boolean tryGoBack(@NotNull Screen screen) {
|
|
||||||
var set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
|
|
||||||
if (screen instanceof KeybindsScreen) return false;
|
|
||||||
|
|
||||||
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
|
||||||
.map(element -> (PressableWidget) element)
|
|
||||||
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
|
|
||||||
.anyMatch(element -> {
|
|
||||||
if (element.getMessage().getContent() instanceof TranslatableTextContent translatableText) {
|
|
||||||
if (set.stream().anyMatch(key -> translatableText.getKey().equals(key))) {
|
|
||||||
element.onPress();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isScreenInteractive(@NotNull Screen screen) {
|
|
||||||
return !(screen instanceof HandledScreen || MidnightControlsConfig.joystickAsMouse || MidnightControlsConfig.mouseScreens.stream().anyMatch(a -> screen.getClass().toString().contains(a))
|
|
||||||
|| (screen instanceof SpruceScreen && ((SpruceScreen) screen).requiresCursor())
|
|
||||||
|| MidnightControlsCompat.requireMouseOnScreen(screen));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pressKeyboardKey(MinecraftClient client, int key) {
|
|
||||||
client.keyboard.onKey(client.getWindow().getHandle(), key, 0, 1, 0);
|
|
||||||
}
|
|
||||||
public void pressKeyboardKey(Screen screen, int key) {
|
|
||||||
screen.keyPressed(key, 0, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
|
|
||||||
import io.github.kosmx.emotes.arch.screen.ingame.FastMenuScreen;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import org.joml.Vector2i;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
|
|
||||||
public class EmotecraftCompat {
|
|
||||||
private static final MinecraftClient client = MinecraftClient.getInstance();
|
|
||||||
|
|
||||||
public static void openEmotecraftScreen(Screen parent) {
|
|
||||||
client.setScreen(new FastMenuScreen(parent));
|
|
||||||
}
|
|
||||||
public static boolean isEmotecraftScreen(Screen screen) {
|
|
||||||
return screen instanceof FastMenuScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int prevIndex = -1;
|
|
||||||
public static void handleEmoteSelector(int index) {
|
|
||||||
try {
|
|
||||||
if (client.currentScreen instanceof FastMenuScreen) {
|
|
||||||
boolean stickReleased = index == -1 && prevIndex != -1;
|
|
||||||
var pos = calcMousePos(stickReleased ? prevIndex : index);
|
|
||||||
InputManager.queueMousePosition(pos.x, pos.y);
|
|
||||||
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
|
||||||
|
|
||||||
if (stickReleased) {
|
|
||||||
((MouseAccessor) client.mouse).midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_PRESS, 0);
|
|
||||||
prevIndex = -1;
|
|
||||||
}
|
|
||||||
else prevIndex = index;
|
|
||||||
} else prevIndex = -1;
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
}
|
|
||||||
public static Vector2i calcMousePos(int index) {
|
|
||||||
int x = client.getWindow().getWidth() / 2;
|
|
||||||
int y = client.getWindow().getHeight() / 2;
|
|
||||||
switch (index) {
|
|
||||||
case 0, 3, 5 -> x -= 275;
|
|
||||||
case 2, 4, 7 -> x += 275;
|
|
||||||
}
|
|
||||||
switch (index) {
|
|
||||||
case 0, 1, 2 -> y -= 275;
|
|
||||||
case 5, 6, 7 -> y += 275;
|
|
||||||
}
|
|
||||||
return new Vector2i(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +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.DrawContext;
|
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
@Mixin(DrawContext.class)
|
|
||||||
public interface DrawContextAccessor {
|
|
||||||
@Accessor("vertexConsumers")
|
|
||||||
VertexConsumerProvider.Immediate getVertexConsumers();
|
|
||||||
}
|
|
||||||
@@ -1,68 +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 eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
|
||||||
import net.minecraft.client.gui.screen.option.GameOptionsScreen;
|
|
||||||
import net.minecraft.client.gui.widget.OptionListWidget;
|
|
||||||
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Injects the new controls settings button.
|
|
||||||
*/
|
|
||||||
@Mixin(GameOptionsScreen.class)
|
|
||||||
public abstract class GameOptionsScreenMixin extends Screen {
|
|
||||||
@Shadow @Nullable protected OptionListWidget body;
|
|
||||||
@Unique TextIconButtonWidget midnightcontrols$button = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"),
|
|
||||||
(button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true)
|
|
||||||
.dimension(20,20).texture(id("icon/controller"), 20, 20).build();
|
|
||||||
|
|
||||||
protected GameOptionsScreenMixin(Text title) {
|
|
||||||
super(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "initBody", at = @At("TAIL"))
|
|
||||||
public void midnightcontrols$addMCButton(CallbackInfo ci) {
|
|
||||||
if (this.getClass().toString().equals(ControlsOptionsScreen.class.toString())) {
|
|
||||||
this.midnightcontrols$setButtonPos();
|
|
||||||
this.addSelectableChild(midnightcontrols$button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Inject(method = "init", at = @At("TAIL"))
|
|
||||||
public void midnightcontrols$drawMCButton(CallbackInfo ci) {
|
|
||||||
if (this.getClass().toString().equals(ControlsOptionsScreen.class.toString())) {
|
|
||||||
this.addDrawableChild(midnightcontrols$button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "refreshWidgetPositions", at = @At("TAIL"))
|
|
||||||
public void midnightcontrols$onResize(CallbackInfo ci) {
|
|
||||||
this.midnightcontrols$setButtonPos();
|
|
||||||
}
|
|
||||||
@Unique
|
|
||||||
public void midnightcontrols$setButtonPos() {
|
|
||||||
if (body != null) {
|
|
||||||
midnightcontrols$button.setPosition(body.getWidth() / 2 + 158, body.getY() + 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +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.screen.ingame.RecipeBookScreen;
|
|
||||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
@Mixin(RecipeBookScreen.class)
|
|
||||||
public interface RecipeBookScreenAccessor {
|
|
||||||
@Accessor("recipeBook")
|
|
||||||
RecipeBookWidget<?> getRecipeBook();
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
|
||||||
import net.minecraft.screen.slot.Slot;
|
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.input;
|
|
||||||
|
|
||||||
public class InventoryUtil {
|
|
||||||
// Finds the closest slot in the GUI within 14 pixels.
|
|
||||||
public static Optional<Slot> findClosestSlot(HandledScreen<?> inventory, int direction) {
|
|
||||||
var accessor = (HandledScreenAccessor) inventory;
|
|
||||||
int guiLeft = accessor.getX();
|
|
||||||
int guiTop = accessor.getY();
|
|
||||||
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
|
||||||
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
|
||||||
// Finds the hovered slot.
|
|
||||||
var mouseSlot = accessor.midnightcontrols$getSlotAt(mouseX, mouseY);
|
|
||||||
return inventory.getScreenHandler().slots.parallelStream()
|
|
||||||
.filter(Predicate.isEqual(mouseSlot).negate())
|
|
||||||
.map(slot -> {
|
|
||||||
int posX = guiLeft + slot.x + 8;
|
|
||||||
int posY = guiTop + slot.y + 8;
|
|
||||||
|
|
||||||
int otherPosX = (int) mouseX;
|
|
||||||
int otherPosY = (int) mouseY;
|
|
||||||
if (mouseSlot != null) {
|
|
||||||
otherPosX = guiLeft + mouseSlot.x + 8;
|
|
||||||
otherPosY = guiTop + mouseSlot.y + 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Distance between the slot and the cursor.
|
|
||||||
double distance = Math.sqrt(Math.pow(posX - otherPosX, 2) + Math.pow(posY - otherPosY, 2));
|
|
||||||
return Pair.of(slot, distance);
|
|
||||||
}).filter(entry -> {
|
|
||||||
var slot = entry.key;
|
|
||||||
int posX = guiLeft + slot.x + 8;
|
|
||||||
int posY = guiTop + slot.y + 8;
|
|
||||||
int otherPosX = (int) mouseX;
|
|
||||||
int otherPosY = (int) mouseY;
|
|
||||||
if (mouseSlot != null) {
|
|
||||||
otherPosX = guiLeft + mouseSlot.x + 8;
|
|
||||||
otherPosY = guiTop + mouseSlot.y + 8;
|
|
||||||
}
|
|
||||||
if (direction == 0)
|
|
||||||
return posY < otherPosY;
|
|
||||||
else if (direction == 1)
|
|
||||||
return posY > otherPosY;
|
|
||||||
else if (direction == 2)
|
|
||||||
return posX > otherPosX;
|
|
||||||
else if (direction == 3)
|
|
||||||
return posX < otherPosX;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
.min(Comparator.comparingDouble(p -> p.value))
|
|
||||||
.map(p -> p.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int targetMouseX = 0;
|
|
||||||
private static int targetMouseY = 0;
|
|
||||||
|
|
||||||
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
|
|
||||||
public static void moveMouseToClosestSlot(@Nullable Screen screen) {
|
|
||||||
// Makes the mouse attracted to slots. This helps with selecting items when using a controller.
|
|
||||||
if (screen instanceof HandledScreen<?> inventoryScreen) {
|
|
||||||
var accessor = (HandledScreenAccessor) inventoryScreen;
|
|
||||||
int guiLeft = accessor.getX();
|
|
||||||
int guiTop = accessor.getY();
|
|
||||||
int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
|
||||||
int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
|
|
||||||
|
|
||||||
// Finds the closest slot in the GUI within 14 pixels.
|
|
||||||
Optional<net.minecraft.util.Pair<Slot, Double>> closestSlot = inventoryScreen.getScreenHandler().slots.parallelStream()
|
|
||||||
.map(slot -> {
|
|
||||||
int x = guiLeft + slot.x + 8;
|
|
||||||
int y = guiTop + slot.y + 8;
|
|
||||||
|
|
||||||
// Distance between the slot and the cursor.
|
|
||||||
double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2));
|
|
||||||
return new net.minecraft.util.Pair<>(slot, distance);
|
|
||||||
}).filter(entry -> entry.getRight() <= 14.0)
|
|
||||||
.min(Comparator.comparingDouble(net.minecraft.util.Pair::getRight));
|
|
||||||
|
|
||||||
if (closestSlot.isPresent() && client.player != null) {
|
|
||||||
var slot = closestSlot.get().getLeft();
|
|
||||||
if (slot.hasStack() || !client.player.getInventory().getMainHandStack().isEmpty()) {
|
|
||||||
int slotCenterXScaled = guiLeft + slot.x + 8;
|
|
||||||
int slotCenterYScaled = guiTop + slot.y + 8;
|
|
||||||
int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
|
|
||||||
int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()));
|
|
||||||
double deltaX = slotCenterX - targetMouseX;
|
|
||||||
double deltaY = slotCenterY - targetMouseY;
|
|
||||||
|
|
||||||
if (mouseX != slotCenterXScaled || mouseY != slotCenterYScaled) {
|
|
||||||
targetMouseX += (int) (deltaX * 0.75);
|
|
||||||
targetMouseY += (int) (deltaY * 0.75);
|
|
||||||
} else {
|
|
||||||
input.mouseSpeedX *= 0.3F;
|
|
||||||
input.mouseSpeedY *= 0.3F;
|
|
||||||
}
|
|
||||||
input.mouseSpeedX *= .75F;
|
|
||||||
input.mouseSpeedY *= .75F;
|
|
||||||
} else {
|
|
||||||
input.mouseSpeedX *= .1F;
|
|
||||||
input.mouseSpeedY *= .1F;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
input.mouseSpeedX *= .3F;
|
|
||||||
input.mouseSpeedY *= .3F;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
input.mouseSpeedX = 0.F;
|
|
||||||
input.mouseSpeedY = 0.F;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
|
|
||||||
public class ToggleSneakSprintUtil {
|
|
||||||
public static boolean toggleSneak(ButtonBinding button) {
|
|
||||||
if (client.player == null) return false;
|
|
||||||
boolean isFlying = client.player.getAbilities().flying;
|
|
||||||
var option = client.options.getSneakToggled();
|
|
||||||
|
|
||||||
button.asKeyBinding().ifPresent(binding -> {
|
|
||||||
boolean sneakToggled = option.getValue();
|
|
||||||
if (isFlying && sneakToggled)
|
|
||||||
option.setValue(false);
|
|
||||||
else if (MidnightControlsConfig.controllerToggleSneak != sneakToggled)
|
|
||||||
option.setValue(!sneakToggled);
|
|
||||||
binding.setPressed(button.isPressed());
|
|
||||||
if (isFlying && sneakToggled)
|
|
||||||
option.setValue(true);
|
|
||||||
else if (MidnightControlsConfig.controllerToggleSneak != sneakToggled)
|
|
||||||
option.setValue(sneakToggled);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public static boolean toggleSprint(ButtonBinding button) {
|
|
||||||
if (client.player == null) return false;
|
|
||||||
boolean isFlying = client.player.getAbilities().flying;
|
|
||||||
var option = client.options.getSprintToggled();
|
|
||||||
|
|
||||||
button.asKeyBinding().ifPresent(binding -> {
|
|
||||||
boolean sprintToggled = option.getValue();
|
|
||||||
if (isFlying && sprintToggled)
|
|
||||||
option.setValue(false);
|
|
||||||
else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
|
|
||||||
option.setValue(!sprintToggled);
|
|
||||||
binding.setPressed(button.isPressed());
|
|
||||||
if (client.player.getAbilities().flying && sprintToggled)
|
|
||||||
option.setValue(true);
|
|
||||||
else if (MidnightControlsConfig.controllerToggleSprint != sprintToggled)
|
|
||||||
option.setValue(sprintToggled);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util.platform;
|
|
||||||
|
|
||||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
|
||||||
import net.minecraft.client.gui.widget.PressableWidget;
|
|
||||||
import net.minecraft.item.ItemGroup;
|
|
||||||
import net.minecraft.item.ItemGroups;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ItemGroupUtil {
|
|
||||||
@ExpectPlatform
|
|
||||||
public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean cyclePage(boolean next, CreativeInventoryScreen screen) {
|
|
||||||
try {
|
|
||||||
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
|
||||||
.map(element -> (PressableWidget) element)
|
|
||||||
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
|
|
||||||
.anyMatch(element -> {
|
|
||||||
if (next && element.getMessage().getString().equals(">")) {
|
|
||||||
element.onPress();
|
|
||||||
return true;
|
|
||||||
} else if (element.getMessage().getString().equals("<")) {
|
|
||||||
element.onPress();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NotNull ItemGroup cycleTab(boolean next, MinecraftClient client) {
|
|
||||||
ItemGroup currentTab = CreativeInventoryScreenAccessor.getSelectedTab();
|
|
||||||
int currentColumn = currentTab.getColumn();
|
|
||||||
ItemGroup.Row currentRow = currentTab.getRow();
|
|
||||||
ItemGroup newTab = null;
|
|
||||||
List<ItemGroup> visibleTabs = ItemGroupUtil.getVisibleGroups((CreativeInventoryScreen) client.currentScreen);
|
|
||||||
for (ItemGroup tab : visibleTabs) {
|
|
||||||
if (tab.getRow().equals(currentRow) && ((newTab == null && ((next && tab.getColumn() > currentColumn) ||
|
|
||||||
(!next && tab.getColumn() < currentColumn))) || (newTab != null && ((next && tab.getColumn() > currentColumn && tab.getColumn() < newTab.getColumn()) ||
|
|
||||||
(!next && tab.getColumn() < currentColumn && tab.getColumn() > newTab.getColumn())))))
|
|
||||||
newTab = tab;
|
|
||||||
}
|
|
||||||
if (newTab == null)
|
|
||||||
for (ItemGroup tab : visibleTabs) {
|
|
||||||
if ((tab.getRow().compareTo(currentRow)) != 0 && ((next && newTab == null || next && newTab.getColumn() > tab.getColumn()) || (!next && newTab == null) || (!next && newTab.getColumn() < tab.getColumn())))
|
|
||||||
newTab = tab;
|
|
||||||
}
|
|
||||||
if (newTab == null) {
|
|
||||||
for (ItemGroup tab : visibleTabs) {
|
|
||||||
if ((next && tab.getRow() == ItemGroup.Row.TOP && tab.getColumn() == 0) ||
|
|
||||||
!next && tab.getRow() == ItemGroup.Row.BOTTOM && (newTab == null || tab.getColumn() > newTab.getColumn()))
|
|
||||||
newTab = tab;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newTab == null || newTab.equals(currentTab)) newTab = ItemGroups.getDefaultTab();
|
|
||||||
return newTab;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util.platform;
|
|
||||||
|
|
||||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
|
||||||
import net.minecraft.network.packet.CustomPayload;
|
|
||||||
import net.minecraft.network.packet.Packet;
|
|
||||||
|
|
||||||
public class NetworkUtil {
|
|
||||||
@ExpectPlatform
|
|
||||||
public static void sendPacketC2S(Packet<?> packet) {
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
@ExpectPlatform
|
|
||||||
public static void sendPayloadC2S(CustomPayload payload) {
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util.storage;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightInput.BUTTON_COOLDOWNS;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.controller.InputManager.STATES;
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER;
|
|
||||||
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.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER;
|
|
||||||
|
|
||||||
public class AxisStorage {
|
|
||||||
public final int axis;
|
|
||||||
public float value, absValue;
|
|
||||||
public final double deadZone;
|
|
||||||
public final Polarity polarity;
|
|
||||||
public final boolean isTrigger;
|
|
||||||
public final ButtonState buttonState;
|
|
||||||
|
|
||||||
// Used for joysticks
|
|
||||||
public static AxisStorage of(int axis, float value) {
|
|
||||||
return new AxisStorage(axis, value, isLeftAxis(axis) ? MidnightControlsConfig.leftDeadZone : MidnightControlsConfig.rightDeadZone);
|
|
||||||
}
|
|
||||||
public static AxisStorage of(int axis, float value, double deadZone) {
|
|
||||||
return new AxisStorage(axis, value, deadZone);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AxisStorage(int axis, float value, double deadZone) {
|
|
||||||
this.axis = axis;
|
|
||||||
this.deadZone = deadZone;
|
|
||||||
|
|
||||||
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)) {
|
|
||||||
this.isTrigger = true;
|
|
||||||
if (value < -.5f) {
|
|
||||||
value = 0f;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Fixes Triggers not working correctly on some controllers
|
|
||||||
if (MidnightControlsConfig.triggerFix) {
|
|
||||||
value = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else isTrigger = false;
|
|
||||||
|
|
||||||
this.value = value;
|
|
||||||
this.buttonState = value > .5f ? ButtonState.PRESS : (value < -.5f ? ButtonState.RELEASE : ButtonState.NONE);
|
|
||||||
this.absValue = Math.abs(value);
|
|
||||||
boolean currentPlusState = value > deadZone;
|
|
||||||
boolean currentMinusState = value < -deadZone;
|
|
||||||
if (isTrigger) currentMinusState = false;
|
|
||||||
else if (!MidnightControlsConfig.analogMovement && isLeftAxis(axis)) {
|
|
||||||
currentPlusState = buttonState == ButtonState.PRESS;
|
|
||||||
currentMinusState = buttonState == ButtonState.RELEASE;
|
|
||||||
}
|
|
||||||
this.polarity = currentPlusState ? AxisStorage.Polarity.PLUS : currentMinusState ? AxisStorage.Polarity.MINUS : AxisStorage.Polarity.ZERO;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns the specified axis as a button.
|
|
||||||
*
|
|
||||||
* @param positive true if the axis part is positive, else false
|
|
||||||
* @return the axis as a button
|
|
||||||
*/
|
|
||||||
public int getButtonId(boolean positive) {
|
|
||||||
return ButtonBinding.axisAsButton(axis, positive);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setupButtonStates() {
|
|
||||||
var posButton = getButtonId(true);
|
|
||||||
var negButton = getButtonId(false);
|
|
||||||
var previousPlusState = STATES.getOrDefault(posButton, ButtonState.NONE);
|
|
||||||
var previousMinusState = STATES.getOrDefault(negButton, ButtonState.NONE);
|
|
||||||
|
|
||||||
if (polarity.isPositive() != previousPlusState.isPressed()) {
|
|
||||||
STATES.put(posButton, polarity.isPositive() ? ButtonState.PRESS : ButtonState.RELEASE);
|
|
||||||
if (polarity.isPositive())
|
|
||||||
BUTTON_COOLDOWNS.put(posButton, 5);
|
|
||||||
} else if (polarity.isPositive()) {
|
|
||||||
STATES.put(posButton, ButtonState.REPEAT);
|
|
||||||
if (BUTTON_COOLDOWNS.getOrDefault(posButton, 0) == 0) {
|
|
||||||
BUTTON_COOLDOWNS.put(posButton, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (polarity.isNegative() != previousMinusState.isPressed()) {
|
|
||||||
STATES.put(negButton, polarity.isNegative() ? ButtonState.PRESS : ButtonState.RELEASE);
|
|
||||||
if (polarity.isNegative())
|
|
||||||
BUTTON_COOLDOWNS.put(negButton, 5);
|
|
||||||
} else if (polarity.isNegative()) {
|
|
||||||
STATES.put(negButton, ButtonState.REPEAT);
|
|
||||||
if (BUTTON_COOLDOWNS.getOrDefault(negButton, 0) == 0) {
|
|
||||||
BUTTON_COOLDOWNS.put(negButton, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static boolean isLeftAxis(int axis) {
|
|
||||||
return axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER;
|
|
||||||
}
|
|
||||||
public static boolean isRightAxis(int axis) {
|
|
||||||
return !isLeftAxis(axis);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Polarity {
|
|
||||||
MINUS(-1), ZERO(0), PLUS(1);
|
|
||||||
|
|
||||||
public final int multiplier;
|
|
||||||
Polarity(int multiplier) {
|
|
||||||
this.multiplier = multiplier;
|
|
||||||
}
|
|
||||||
public boolean isPositive() {
|
|
||||||
return this == PLUS;
|
|
||||||
}
|
|
||||||
public boolean isNegative() {
|
|
||||||
return this == MINUS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util.storage;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
|
||||||
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT;
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP;
|
|
||||||
|
|
||||||
public class ButtonStorage {
|
|
||||||
public final int button;
|
|
||||||
public final ButtonState state;
|
|
||||||
|
|
||||||
public static ButtonStorage of(int button, ButtonState state) {
|
|
||||||
return new ButtonStorage(button, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ButtonStorage(int button, ButtonState state) {
|
|
||||||
this.button = button;
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
public boolean isDpad() {
|
|
||||||
return button >= GLFW_GAMEPAD_BUTTON_DPAD_UP && button <= GLFW_GAMEPAD_BUTTON_DPAD_LEFT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public record ControlsModePayload(String controlsMode) implements CustomPayload {
|
|
||||||
public static final Id<ControlsModePayload> PACKET_ID = new Id<>(MidnightControlsConstants.CONTROLS_MODE_CHANNEL);
|
|
||||||
public static final PacketCodec<RegistryByteBuf, ControlsModePayload> codec = PacketCodec.of(ControlsModePayload::write, ControlsModePayload::read);
|
|
||||||
|
|
||||||
public static ControlsModePayload read(RegistryByteBuf buf) {
|
|
||||||
return new ControlsModePayload(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
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 FeaturePayload(MidnightControlsFeature... features) implements CustomPayload {
|
|
||||||
public static final Id<FeaturePayload> PACKET_ID = new Id<>(MidnightControlsConstants.FEATURE_CHANNEL);
|
|
||||||
public static final PacketCodec<RegistryByteBuf, FeaturePayload> codec = PacketCodec.of(FeaturePayload::write, FeaturePayload::read);
|
|
||||||
|
|
||||||
public static FeaturePayload 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 FeaturePayload(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
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 HelloPayload(String version, String controlsMode) implements CustomPayload {
|
|
||||||
public static final CustomPayload.Id<HelloPayload> PACKET_ID = new CustomPayload.Id<>(MidnightControlsConstants.HELLO_CHANNEL);
|
|
||||||
public static final PacketCodec<RegistryByteBuf, HelloPayload> codec = PacketCodec.of(HelloPayload::write, HelloPayload::read);
|
|
||||||
|
|
||||||
public static HelloPayload read(RegistryByteBuf buf) {
|
|
||||||
return new HelloPayload(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"accessWidener": "midnightcontrols.accesswidener"
|
|
||||||
}
|
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
{
|
|
||||||
"midnightcontrols.midnightconfig.title": "Configurações avançadas do MidnightControls",
|
|
||||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_LIGHT": "Padrão claro",
|
|
||||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_DARK": "Padrão escuro",
|
|
||||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_LIGHT": "Segundo claro",
|
|
||||||
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_DARK": "Segundo escuro",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.DEFAULT": "Padrão",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.DUALSHOCK": "DualShock",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.DUALSENSE": "DualSense",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.SWITCH": "Controle de Switch/Wii",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.XBOX": "Controle de Xbox One/Series",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.XBOX_360": "Controle de Xbox 360",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.STEAM_CONTROLLER": "Controle da Steam",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.STEAM_DECK": "Steam Deck",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.OUYA": "Controle de OUYA",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControllerType.NUMBERED": "Controle númerado",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControlsMode.DEFAULT": "Teclado/Mouse",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControlsMode.CONTROLLER": "Controle",
|
|
||||||
"midnightcontrols.midnightconfig.enum.ControlsMode.TOUCHSCREEN": "Tela sensível ao toque (Beta)",
|
|
||||||
"midnightcontrols.midnightconfig.enum.HudSide.LEFT": "Esquerda",
|
|
||||||
"midnightcontrols.midnightconfig.enum.HudSide.RIGHT": "Direita",
|
|
||||||
"midnightcontrols.midnightconfig.enum.TouchMode.CROSSHAIR": "Na mira",
|
|
||||||
"midnightcontrols.midnightconfig.enum.TouchMode.FINGER_POS": "Posição do dedo",
|
|
||||||
"midnightcontrols.midnightconfig.enum.CameraMode.FLAT": "Plano",
|
|
||||||
"midnightcontrols.midnightconfig.enum.CameraMode.ADAPTIVE": "Adaptativo",
|
|
||||||
"key.categories.midnightcontrols": "MidnightControls",
|
|
||||||
"key.midnightcontrols.look_down": "Olhar para baixo",
|
|
||||||
"key.midnightcontrols.look_left": "Olhar para a esquerda",
|
|
||||||
"key.midnightcontrols.look_right": "Olhar para a direita",
|
|
||||||
"key.midnightcontrols.look_up": "Olhar para cima",
|
|
||||||
"key.midnightcontrols.ring": "Abrir anel de teclas não vinculadas",
|
|
||||||
"midnightcontrols.action.attack": "Atacar",
|
|
||||||
"midnightcontrols.action.back": "Voltar",
|
|
||||||
"midnightcontrols.action.chat": "Abrir bate-papo",
|
|
||||||
"midnightcontrols.action.controls_ring": "Abrir anel de teclas não vinculadas",
|
|
||||||
"midnightcontrols.action.debug_screen": "Abrir HUD de depuração (F3)",
|
|
||||||
"midnightcontrols.action.drop_item": "Soltar item",
|
|
||||||
"midnightcontrols.action.drink": "Beber",
|
|
||||||
"midnightcontrols.action.eat": "Comer",
|
|
||||||
"midnightcontrols.action.equip": "Equipar",
|
|
||||||
"midnightcontrols.action.exit": "Sair da tela",
|
|
||||||
"midnightcontrols.action.forward": "Para frente",
|
|
||||||
"midnightcontrols.action.hit": "Atacar",
|
|
||||||
"midnightcontrols.action.hotbar_left": "Move a barra rápida para esquerda",
|
|
||||||
"midnightcontrols.action.hotbar_right": "Move a barra rápida para direita",
|
|
||||||
"midnightcontrols.action.inventory": "Invetário",
|
|
||||||
"midnightcontrols.action.jump": "Pular",
|
|
||||||
"midnightcontrols.action.left": "Esquerda",
|
|
||||||
"midnightcontrols.action.pause_game": "Pausar",
|
|
||||||
"midnightcontrols.action.pick_block": "Pegar bloco",
|
|
||||||
"midnightcontrols.action.pickup": "Pegar",
|
|
||||||
"midnightcontrols.action.pickup_all": "Pegar todos",
|
|
||||||
"midnightcontrols.action.place": "Colocar",
|
|
||||||
"midnightcontrols.action.player_list": "Lista de jogadores",
|
|
||||||
"midnightcontrols.action.quick_move": "Mover rápido",
|
|
||||||
"midnightcontrols.action.right": "Direita",
|
|
||||||
"midnightcontrols.action.screenshot": "Tirar Screenshot",
|
|
||||||
"midnightcontrols.action.slot_up": "Mover Slot para cima",
|
|
||||||
"midnightcontrols.action.slot_down": "Mover Slot para baixo",
|
|
||||||
"midnightcontrols.action.slot_left": "Mover Slot para esquerda",
|
|
||||||
"midnightcontrols.action.slot_right": "Mover Slot para direita",
|
|
||||||
"midnightcontrols.action.sneak": "Esgueirar",
|
|
||||||
"midnightcontrols.action.sprint": "Correr",
|
|
||||||
"midnightcontrols.action.swap_hands": "Trocar de mãos",
|
|
||||||
"midnightcontrols.action.toggle_perspective": "Alternar perspectiva",
|
|
||||||
"midnightcontrols.action.toggle_smooth_camera": "Ativar câmera cinemática",
|
|
||||||
"midnightcontrols.action.page_back": "Página anterior",
|
|
||||||
"midnightcontrols.action.page_next": "Próxima página",
|
|
||||||
"midnightcontrols.action.tab_back": "Aba anterior",
|
|
||||||
"midnightcontrols.action.tab_next": "Próxima aba",
|
|
||||||
"midnightcontrols.action.take": "Pegar item",
|
|
||||||
"midnightcontrols.action.take_all": "Pegar pilha",
|
|
||||||
"midnightcontrols.action.use": "Usar",
|
|
||||||
"midnightcontrols.action.zoom": "Zoom",
|
|
||||||
"midnightcontrols.action.zoom_in": "Aumentar o Zoom",
|
|
||||||
"midnightcontrols.action.zoom_out": "Diminuir o Zoom",
|
|
||||||
"midnightcontrols.action.zoom_reset": "Resetar o Zoom",
|
|
||||||
"midnightcontrols.action.emi_page_left": "Página anterior",
|
|
||||||
"midnightcontrols.action.emi_page_right": "Próxima pickup",
|
|
||||||
"midnightcontrols.category.emi": "EMI",
|
|
||||||
"midnightcontrols.button.a": "A",
|
|
||||||
"midnightcontrols.button.b": "B",
|
|
||||||
"midnightcontrols.button.x": "X",
|
|
||||||
"midnightcontrols.button.y": "Y",
|
|
||||||
"midnightcontrols.button.left_bumper": "Botão L1",
|
|
||||||
"midnightcontrols.button.right_bumper": "Botão R1",
|
|
||||||
"midnightcontrols.button.back": "Voltar",
|
|
||||||
"midnightcontrols.button.start": "Começar",
|
|
||||||
"midnightcontrols.button.guide": "Guia",
|
|
||||||
"midnightcontrols.button.left_thumb": "Analógico esquerdo",
|
|
||||||
"midnightcontrols.button.right_thumb": "Analógico direito",
|
|
||||||
"midnightcontrols.button.dpad_up": "Botão direcional para cima",
|
|
||||||
"midnightcontrols.button.dpad_right": "Botão direcional para direita",
|
|
||||||
"midnightcontrols.button.dpad_down": "Botão direcional para baixo",
|
|
||||||
"midnightcontrols.button.dpad_left": "Botão direcional para esquerda",
|
|
||||||
"midnightcontrols.button.l4": "L4",
|
|
||||||
"midnightcontrols.button.l5": "L5",
|
|
||||||
"midnightcontrols.button.r4": "R4",
|
|
||||||
"midnightcontrols.button.r5": "L5",
|
|
||||||
"midnightcontrols.axis.left_x+": "Esquerda X+",
|
|
||||||
"midnightcontrols.axis.left_y+": "Esquerda Y+",
|
|
||||||
"midnightcontrols.axis.right_x+": "Direita X+",
|
|
||||||
"midnightcontrols.axis.right_y+": "Direita Y+",
|
|
||||||
"midnightcontrols.axis.left_trigger": "Gatilho da esquerda",
|
|
||||||
"midnightcontrols.axis.right_trigger": "Gatilho da direita",
|
|
||||||
"midnightcontrols.axis.left_x-": "Esquerda X-",
|
|
||||||
"midnightcontrols.axis.left_y-": "Esquerda Y-",
|
|
||||||
"midnightcontrols.axis.right_x-": "Direita X-",
|
|
||||||
"midnightcontrols.axis.right_y-": "Direita Y-",
|
|
||||||
"midnightcontrols.button.unknown": "Desconhecido (%d)",
|
|
||||||
"midnightcontrols.controller.tutorial.title": "Jogue o jogo com um controle!",
|
|
||||||
"midnightcontrols.controller.tutorial.description": "Vá para %s -> %s -> %s",
|
|
||||||
"midnightcontrols.controller.connected": "Controle %d conectado.",
|
|
||||||
"midnightcontrols.controller.disconnected": "Controle %d desconectado.",
|
|
||||||
"midnightcontrols.controller.mappings.1": "Para configurar o mapeamento do controle, por favor use %s",
|
|
||||||
"midnightcontrols.controller.mappings.3": "e cole o mapeamento no editor de arquivos do mapeamento.",
|
|
||||||
"midnightcontrols.controller.mappings.error": "Erro ao carregar mapeamentos.",
|
|
||||||
"midnightcontrols.controller.mappings.error.write": "Erro ao gravar mapeamentos no arquivo.",
|
|
||||||
"midnightcontrols.controller.mappings.updated": "Atualizando mapeamentos!",
|
|
||||||
"midnightcontrols.controller_type.default": "Padrão",
|
|
||||||
"midnightcontrols.controller_type.dualshock": "DualShock",
|
|
||||||
"midnightcontrols.controller_type.dualsense": "DualSense",
|
|
||||||
"midnightcontrols.controller_type.switch": "Controle de Switch/Wii",
|
|
||||||
"midnightcontrols.controller_type.xbox": "Controle de Xbox One/Series",
|
|
||||||
"midnightcontrols.controller_type.xbox_360": "Controle de Xbox 360",
|
|
||||||
"midnightcontrols.controller_type.steam_controller": "Controle da Steam",
|
|
||||||
"midnightcontrols.controller_type.steam_deck": "Steam Deck",
|
|
||||||
"midnightcontrols.controller_type.ouya": "Controle de OUYA",
|
|
||||||
"midnightcontrols.controller_type.numbered": "Controle númerado",
|
|
||||||
"midnightcontrols.controls_mode.default": "Teclado/Mouse",
|
|
||||||
"midnightcontrols.controls_mode.controller": "Controle",
|
|
||||||
"midnightcontrols.controls_mode.touchscreen": "Tela sensível ao toque (Beta)",
|
|
||||||
"midnightcontrols.hud_side.LEFT": "Esquerda",
|
|
||||||
"midnightcontrols.hud_side.RIGHT": "Direita",
|
|
||||||
"midnightcontrols.menu.analog_movement": "Movemento analógico",
|
|
||||||
"midnightcontrols.menu.analog_movement.tooltip": "Quando possível, ative o movemento analógico.",
|
|
||||||
"midnightcontrols.menu.auto_switch_mode": "Modo de troca automática",
|
|
||||||
"midnightcontrols.menu.auto_switch_mode.tooltip": "Se o modo de controle deve ser alterado automaticamente para o controle quando um for conectado.",
|
|
||||||
"midnightcontrols.menu.camera_mode": "Modo de câmera",
|
|
||||||
"midnightcontrols.menu.controller": "Controle",
|
|
||||||
"midnightcontrols.menu.controller2": "Segundo controle",
|
|
||||||
"midnightcontrols.menu.controller2.tooltip": "Segundo controle a ser usado, o que permite (por exemplo) o suporte a Joy-Cons.",
|
|
||||||
"midnightcontrols.menu.controller_toggle_sneak": "Alternar Esgueirar no Controle",
|
|
||||||
"midnightcontrols.menu.controller_toggle_sprint": "Alternar Correr no Controle",
|
|
||||||
"midnightcontrols.menu.controller_type": "Tipo de controle",
|
|
||||||
"midnightcontrols.menu.controller_type.tooltip": "O tipo de controle que você está usando (é preciso para mostrar os botões corretos)",
|
|
||||||
"midnightcontrols.menu.controls_mode": "Modo",
|
|
||||||
"midnightcontrols.menu.controls_mode.tooltip": "O modo de controle.",
|
|
||||||
"midnightcontrols.menu.copy_controller_guid": "Copiar o GUID",
|
|
||||||
"midnightcontrols.menu.current_controller_guid": "GUID do controle atual: %s",
|
|
||||||
"midnightcontrols.menu.double_tap_to_sprint": "Toque duplo para correr",
|
|
||||||
"midnightcontrols.menu.double_tap_to_sprint.tooltip": "Alterna se a tecla Andar para Frente faz o jogador correr quando pressionada duas vezes rapidamente",
|
|
||||||
"midnightcontrols.menu.fast_block_placing": "Colocação Rápida de Blocos",
|
|
||||||
"midnightcontrols.menu.fast_block_placing.tooltip": "Enquanto voando no criativo, ativar a Colocação de Rápida de Blocos. §cEm alguns servidores isso pode ser considerado como trapaça.",
|
|
||||||
"midnightcontrols.menu.fly_drifting": "Derrapagem ao Voar",
|
|
||||||
"midnightcontrols.menu.fly_drifting.tooltip": "Enquanto voando, ativa a deparragem/inércia Vanilla.",
|
|
||||||
"midnightcontrols.menu.fly_drifting_vertical": "Derrapagem vertical ao Voar",
|
|
||||||
"midnightcontrols.menu.fly_drifting_vertical.tooltip": "Enquanto voando, ativa a deparragem/inércia vertical Vanilla.",
|
|
||||||
"midnightcontrols.menu.hud_enable": "Ativar HUD",
|
|
||||||
"midnightcontrols.menu.hud_enable.tooltip": "Alterna o indicador de botão do controle na tela.",
|
|
||||||
"midnightcontrols.menu.hud_side": "Lado do HUD",
|
|
||||||
"midnightcontrols.menu.hud_side.tooltip": "A posição do HUD.",
|
|
||||||
"midnightcontrols.menu.invert_right_x_axis": "Inverter X Direito",
|
|
||||||
"midnightcontrols.menu.invert_right_y_axis": "Inverter Y Direito",
|
|
||||||
"midnightcontrols.menu.joystick_as_mouse": "Sempre usar analógico esquerdo como mouse",
|
|
||||||
"midnightcontrols.menu.joystick_as_mouse.tooltip": "Fazer o analógico agir como um mouse em todos os menus.",
|
|
||||||
"midnightcontrols.menu.eye_tracker_as_mouse": "Usar o rastreador ocular como um mouse",
|
|
||||||
"midnightcontrols.menu.eye_tracker_as_mouse.tooltip": "Substituir o mouse com um dispositivo de rastreamento ocular, (por exemplo) o Tobii 5.",
|
|
||||||
"midnightcontrols.menu.eye_tracker_deadzone": "Tamanho da zona morta do rastreador ocular",
|
|
||||||
"midnightcontrols.menu.eye_tracker_deadzone.tooltip": "Parar o movimento da camera quando olhar perto da mira",
|
|
||||||
"midnightcontrols.menu.keyboard_controls": "Controles do teclado...",
|
|
||||||
"midnightcontrols.menu.left_dead_zone": "Zona morta do analógico esquerdo",
|
|
||||||
"midnightcontrols.menu.left_dead_zone.tooltip": "A zona morta para o analógico esquerdo do controle.",
|
|
||||||
"midnightcontrols.menu.mappings.open_input_str": "Abrir editor de arquivo de mapeamentos",
|
|
||||||
"midnightcontrols.menu.max_left_x_value": "Valor máximo do eixo X esquerdo",
|
|
||||||
"midnightcontrols.menu.max_left_x_value.tooltip": "Altera o valor máximo considerado pelo mod para o eixo X esquerdo. Útil se o seu eixo não usa toda a faixa e parece lento.",
|
|
||||||
"midnightcontrols.menu.max_left_y_value": "Valor máximo do eixo Y esquerdo",
|
|
||||||
"midnightcontrols.menu.max_left_y_value.tooltip": "Altera o valor máximo considerado pelo mod para o eixo Y esquerdo. Útil se o seu eixo não usa toda a faixa e parece lento.",
|
|
||||||
"midnightcontrols.menu.max_right_x_value": "Valor máximo do eixo X direito",
|
|
||||||
"midnightcontrols.menu.max_right_x_value.tooltip": "Altera o valor máximo considerado pelo mod para o eixo X direito. Útil se o seu eixo não usa toda a faixa e parece lento.",
|
|
||||||
"midnightcontrols.menu.max_right_y_value": "Valor máximo do eixo Y direito",
|
|
||||||
"midnightcontrols.menu.max_right_y_value.tooltip": "Altera o valor máximo considerado pelo mod para o eixo Y direito. Útil se o seu eixo não usa toda a faixa e parece lento.",
|
|
||||||
"midnightcontrols.menu.mouse_speed": "Velocidade do mouse",
|
|
||||||
"midnightcontrols.menu.mouse_speed.tooltip": "A velocidade do mouse emulado pelo controle",
|
|
||||||
"midnightcontrols.menu.move_chat": "Mover a caixa do chat para o topo",
|
|
||||||
"midnightcontrols.menu.move_chat.tooltip": "Move a caixa do chat para o topo, para uma melhor digitação em dispositivos com teclados na tela.",
|
|
||||||
"midnightcontrols.menu.multiple_mapping_tip": "(Dica: Você também pode inserir múltiplos mapeamentos ao mesmo tempo)",
|
|
||||||
"midnightcontrols.menu.reacharound.horizontal": "Colocação frontal de blocos",
|
|
||||||
"midnightcontrols.menu.reacharound.horizontal.tooltip": "Ativa colocação frontal de blocos, §cEm alguns servidores isso pode ser considerado como trapaça.§r.",
|
|
||||||
"midnightcontrols.menu.reacharound.vertical": "Alcance vertical",
|
|
||||||
"midnightcontrols.menu.reacharound.vertical.tooltip": "Ativa alcance vertical, §c§cEm alguns servidores isso pode ser considerado como trapaça.§r.",
|
|
||||||
"midnightcontrols.menu.reload_controller_mappings": "Recarregar o mapeamento do controle",
|
|
||||||
"midnightcontrols.menu.reload_controller_mappings.tooltip": "Recarrega o arquivo de mapeamentos do controle.",
|
|
||||||
"midnightcontrols.menu.right_dead_zone": "Zona morta do analógico direito",
|
|
||||||
"midnightcontrols.menu.right_dead_zone.tooltip": "A zona morta para o analógico direito do controle..",
|
|
||||||
"midnightcontrols.menu.rotation_speed": "Velocidade de rotação do eixo X",
|
|
||||||
"midnightcontrols.menu.rotation_speed.tooltip": "A velocidade de rotação do eixo X da câmera no modo controle.",
|
|
||||||
"midnightcontrols.menu.y_axis_rotation_speed": "Velocidade de rotação do eixo Y",
|
|
||||||
"midnightcontrols.menu.y_axis_rotation_speed.tooltip": "A velocidade de rotação do eixo Y da câmera no modo controle.",
|
|
||||||
"midnightcontrols.menu.separate_controller_profile": "Separar perfil do controle",
|
|
||||||
"midnightcontrols.menu.separator.controller": "Controle",
|
|
||||||
"midnightcontrols.menu.separator.general": "Geral",
|
|
||||||
"midnightcontrols.menu.title": "MidnightControls - Configurações",
|
|
||||||
"midnightcontrols.menu.title.controller": "Configurações do controle",
|
|
||||||
"midnightcontrols.menu.title.controller_controls": "Mapeamento de controle",
|
|
||||||
"midnightcontrols.menu.title.gameplay": "Configurações de jogabilidade",
|
|
||||||
"midnightcontrols.menu.title.general": "Configurações gerais",
|
|
||||||
"midnightcontrols.menu.title.hud": "Configurações de HUD",
|
|
||||||
"midnightcontrols.menu.title.mappings.string": "Editor de arquivo de mapeamentos",
|
|
||||||
"midnightcontrols.menu.title.touch": "Configurações de toque",
|
|
||||||
"midnightcontrols.menu.title.visual": "Configurações de aparência",
|
|
||||||
"midnightcontrols.menu.touch_break_delay": "Atrasado de destruição do toque",
|
|
||||||
"midnightcontrols.menu.touch_speed": "Velocidade do toque",
|
|
||||||
"midnightcontrols.menu.invert_touch": "Inverter direção do toque",
|
|
||||||
"midnightcontrols.menu.touch_mode": "Modo de interação de toque",
|
|
||||||
"midnightcontrols.menu.touch_transparency": "Transparência do HUD de toque",
|
|
||||||
"midnightcontrols.menu.touch_with_controller": "Toque no modo do controle",
|
|
||||||
"midnightcontrols.menu.unfocused_input": "Entrada desfocada",
|
|
||||||
"midnightcontrols.menu.unfocused_input.tooltip": "Permite entrada de sinais do controle quando a janela não está em foco.",
|
|
||||||
"midnightcontrols.menu.virtual_mouse": "Mouse virtual",
|
|
||||||
"midnightcontrols.menu.virtual_mouse.tooltip": "Ativa o mouse virtual, que é útil durante o modo tela dividida.",
|
|
||||||
"midnightcontrols.menu.virtual_mouse.skin": "Tema do mouse virtual",
|
|
||||||
"midnightcontrols.menu.hide_cursor": "Desativar cursor do mouse padrão",
|
|
||||||
"midnightcontrols.menu.hide_cursor.tooltip": "Esconde o cursor padrão do mouse, deixando apenas o mouse virtual visível.",
|
|
||||||
"midnightcontrols.narrator.unbound": "Desmapear %s",
|
|
||||||
"midnightcontrols.not_bound": "Não mapeado",
|
|
||||||
"midnightcontrols.virtual_mouse.skin.default_light": "Padrão claro",
|
|
||||||
"midnightcontrols.virtual_mouse.skin.default_dark": "Padrão escuro",
|
|
||||||
"midnightcontrols.virtual_mouse.skin.second_light": "Segundo claro",
|
|
||||||
"midnightcontrols.virtual_mouse.skin.second_dark": "Segundo escuro",
|
|
||||||
"midnightcontrols.midnightconfig.category.controller": "Controle",
|
|
||||||
"midnightcontrols.midnightconfig.category.misc": "Variados",
|
|
||||||
"midnightcontrols.midnightconfig.category.screens": "Telas",
|
|
||||||
"midnightcontrols.midnightconfig.category.gameplay": "Jogabilidade",
|
|
||||||
"midnightcontrols.midnightconfig.category.touch": "Toque",
|
|
||||||
"midnightcontrols.midnightconfig.category.visual": "Visual",
|
|
||||||
"modmenu.descriptionTranslation.midnightcontrols": "Adiciona suporte a controles e aprimora o controle no geral.\nDerivado do LambdaControls, que infelizmente foi descontinuado."
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,111 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'com.github.johnrengelman.shadow'
|
|
||||||
id "me.shedaniel.unified-publishing"
|
|
||||||
}
|
|
||||||
|
|
||||||
architectury {
|
|
||||||
platformSetupLoomIde()
|
|
||||||
fabric()
|
|
||||||
}
|
|
||||||
|
|
||||||
loom {
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
common
|
|
||||||
shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files.
|
|
||||||
compileClasspath.extendsFrom common
|
|
||||||
runtimeClasspath.extendsFrom common
|
|
||||||
developmentFabric.extendsFrom common
|
|
||||||
archivesBaseName = rootProject.archives_base_name + "-fabric"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
|
||||||
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
|
|
||||||
modImplementation include ("maven.modrinth:midnightlib:${rootProject.midnightlib_version}-fabric")
|
|
||||||
modImplementation include ("maven.modrinth:obsidianui:${rootProject.obsidianui_version}-fabric") {}
|
|
||||||
include 'org.aperlambda:lambdajcommon:1.8.1'
|
|
||||||
modCompileOnly "maven.modrinth:emi:${project.emi_version}"
|
|
||||||
|
|
||||||
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
|
||||||
shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
|
|
||||||
}
|
|
||||||
|
|
||||||
processResources {
|
|
||||||
inputs.property "version", project.version
|
|
||||||
|
|
||||||
filesMatching("fabric.mod.json") {
|
|
||||||
expand "version": project.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shadowJar {
|
|
||||||
exclude "architectury.common.json"
|
|
||||||
|
|
||||||
configurations = [project.configurations.shadowCommon]
|
|
||||||
archiveClassifier = "dev-shadow"
|
|
||||||
}
|
|
||||||
|
|
||||||
remapJar {
|
|
||||||
input.set shadowJar.archiveFile
|
|
||||||
dependsOn shadowJar
|
|
||||||
}
|
|
||||||
|
|
||||||
sourcesJar {
|
|
||||||
def commonSources = project(":common").sourcesJar
|
|
||||||
dependsOn commonSources
|
|
||||||
from commonSources.archiveFile.map { zipTree(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
components.java {
|
|
||||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
|
||||||
skip()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unifiedPublishing {
|
|
||||||
project {
|
|
||||||
displayName = "MidnightControls $project.version - Fabric $project.minecraft_version"
|
|
||||||
releaseType = "$project.release_type"
|
|
||||||
changelog = releaseChangelog()
|
|
||||||
gameVersions = []
|
|
||||||
gameLoaders = ["fabric","quilt"]
|
|
||||||
mainPublication remapJar
|
|
||||||
relations {
|
|
||||||
depends {
|
|
||||||
curseforge = "fabric-api"
|
|
||||||
modrinth = "fabric-api"
|
|
||||||
}
|
|
||||||
includes {
|
|
||||||
curseforge = "midnightlib"
|
|
||||||
modrinth = "midnightlib"
|
|
||||||
}
|
|
||||||
includes {
|
|
||||||
curseforge = "obsidianui"
|
|
||||||
modrinth = "obsidianui"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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-$project.name"
|
|
||||||
gameVersions.addAll project.minecraft_version
|
|
||||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util.platform.fabric;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
|
||||||
import net.minecraft.item.ItemGroup;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of fabric methods for
|
|
||||||
* @see eu.midnightdust.midnightcontrols.client.util.platform.ItemGroupUtil
|
|
||||||
*/
|
|
||||||
public class ItemGroupUtilImpl {
|
|
||||||
public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
|
||||||
return (screen.getItemGroupsOnPage(screen.getCurrentPage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util.platform.fabric;
|
|
||||||
|
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
|
||||||
import net.minecraft.network.packet.CustomPayload;
|
|
||||||
import net.minecraft.network.packet.Packet;
|
|
||||||
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of fabric methods for
|
|
||||||
* @see eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil
|
|
||||||
*/
|
|
||||||
public class NetworkUtilImpl {
|
|
||||||
private static final ClientPlayNetworkHandler handler = client.getNetworkHandler();
|
|
||||||
|
|
||||||
public static void sendPacketC2S(Packet<?> packet) {
|
|
||||||
if (handler != null)
|
|
||||||
handler.sendPacket(packet);
|
|
||||||
}
|
|
||||||
public static void sendPayloadC2S(CustomPayload payload) {
|
|
||||||
if (handler != null && client.world != null)
|
|
||||||
handler.sendPacket(new CustomPayloadC2SPacket(payload));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.fabric;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.FeaturePayload;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.HelloPayload;
|
|
||||||
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 org.thinkingstudio.obsidianui.fabric.event.OpenScreenCallback;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_DOWN;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_LEFT;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_RIGHT;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_UP;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_RING;
|
|
||||||
|
|
||||||
public class MidnightControlsClientFabric implements ClientModInitializer {
|
|
||||||
@Override
|
|
||||||
public void onInitializeClient() {
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_UP);
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT);
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN);
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT);
|
|
||||||
KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
|
||||||
ClientPlayNetworking.registerGlobalReceiver(ControlsModePayload.PACKET_ID, (payload, context) ->
|
|
||||||
context.responseSender().sendPacket(new ControlsModePayload(MidnightControlsConfig.controlsMode.getName())));
|
|
||||||
ClientPlayNetworking.registerGlobalReceiver(FeaturePayload.PACKET_ID, ((payload, context) -> {}));
|
|
||||||
|
|
||||||
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
|
||||||
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 HelloPayload(version, controlsMode));
|
|
||||||
sender.sendPacket(new ControlsModePayload(controlsMode));
|
|
||||||
});
|
|
||||||
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> MidnightControlsClient.onLeave());
|
|
||||||
|
|
||||||
ClientTickEvents.START_CLIENT_TICK.register(MidnightControlsClient::onTick);
|
|
||||||
|
|
||||||
FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE).ifPresent(modContainer -> {
|
|
||||||
ResourceManagerHelper.registerBuiltinResourcePack(id("bedrock"), modContainer, ResourcePackActivationType.NORMAL);
|
|
||||||
ResourceManagerHelper.registerBuiltinResourcePack(id("legacy"), modContainer, ResourcePackActivationType.NORMAL);
|
|
||||||
});
|
|
||||||
MidnightControlsClient.initClient();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.fabric;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
|
||||||
import eu.midnightdust.midnightcontrols.fabric.event.PlayerChangeControlsModeCallback;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.FeaturePayload;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.HelloPayload;
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
|
||||||
|
|
||||||
public class MidnightControlsFabric implements ModInitializer {
|
|
||||||
@Override
|
|
||||||
public void onInitialize() {
|
|
||||||
MidnightControls.init();
|
|
||||||
PayloadTypeRegistry.playC2S().register(HelloPayload.PACKET_ID, HelloPayload.codec);
|
|
||||||
PayloadTypeRegistry.playC2S().register(ControlsModePayload.PACKET_ID, ControlsModePayload.codec);
|
|
||||||
PayloadTypeRegistry.playS2C().register(ControlsModePayload.PACKET_ID, ControlsModePayload.codec);
|
|
||||||
PayloadTypeRegistry.playS2C().register(FeaturePayload.PACKET_ID, FeaturePayload.codec);
|
|
||||||
|
|
||||||
ServerPlayNetworking.registerGlobalReceiver(HelloPayload.PACKET_ID, (payload, context) -> {
|
|
||||||
ControlsMode.byId(payload.controlsMode()).ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode));
|
|
||||||
context.responseSender().sendPacket(new FeaturePayload(MidnightControlsFeature.HORIZONTAL_REACHAROUND));
|
|
||||||
});
|
|
||||||
ServerPlayNetworking.registerGlobalReceiver(ControlsModePayload.PACKET_ID, (payload, context) -> {
|
|
||||||
ControlsMode.byId(payload.controlsMode()).ifPresent(controlsMode -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.player(), controlsMode));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +1,36 @@
|
|||||||
# Makes things faster
|
# Done to increase the memory available to gradle.
|
||||||
org.gradle.parallel=true
|
org.gradle.jvmargs=-Xmx1G
|
||||||
org.gradle.jvmargs=-Xmx2048M
|
|
||||||
|
|
||||||
minecraft_version=1.21.4
|
# Fabric Properties
|
||||||
supported_versions=
|
# check these on https://fabricmc.net/use
|
||||||
yarn_mappings=1.21.4+build.1
|
minecraft_version=1.20.1
|
||||||
enabled_platforms=fabric,neoforge
|
yarn_mappings=1.20.1+build.10
|
||||||
|
loader_version=0.15.6
|
||||||
|
|
||||||
archives_base_name=midnightcontrols
|
# Mod Properties
|
||||||
mod_version=1.10.5
|
mod_version = 1.9.4
|
||||||
maven_group=eu.midnightdust
|
maven_group = eu.midnightdust
|
||||||
release_type=release
|
archives_base_name = midnightcontrols
|
||||||
modrinth_id = bXX9h73M
|
modrinth_id = bXX9h73M
|
||||||
curseforge_id = 621768
|
curseforge_id = 621768
|
||||||
# Configure the IDs here after creating the projects on the websites
|
changelog = See changes at: https://github.com/TeamMidnightDust/MidnightControls/commits/
|
||||||
|
|
||||||
midnightlib_version=1.6.8+1.21.4
|
# Dependencies
|
||||||
|
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
|
||||||
fabric_loader_version=0.16.9
|
fabric_version=0.91.0+1.20.1
|
||||||
fabric_api_version=0.110.5+1.21.4
|
sodium_version=mc1.19.2-0.4.4
|
||||||
|
spruceui_version=5.0.0+1.20
|
||||||
neoforge_version=21.4.9-beta
|
midnightlib_version=1.4.1-fabric
|
||||||
yarn_mappings_patch_neoforge_version = 1.21+build.4
|
modmenu_version=7.0.0
|
||||||
|
emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric
|
||||||
quilt_loader_version=0.19.0-beta.18
|
|
||||||
quilt_fabric_api_version=7.0.1+0.83.0-1.20
|
|
||||||
|
|
||||||
sodium_version=mc1.21-0.6.0-beta.1
|
|
||||||
obsidianui_version=0.2.10+mc1.21.3
|
|
||||||
modmenu_version=10.0.0-beta.1
|
|
||||||
emotecraft_version=2.5.5+1.21.4-fabric
|
|
||||||
bendylib_version=2.0.+
|
bendylib_version=2.0.+
|
||||||
emi_version=1.1.10+1.21+fabric
|
emi_version=1.1.1+1.20.1+fabric
|
||||||
libgui_version=6.0.0+1.19
|
libgui_version=6.0.0+1.19
|
||||||
inventorytabs_version=inventorytabs-0.9.beta-1.19.x
|
inventorytabs_version=inventorytabs-0.9.beta-1.19.x
|
||||||
clothconfig_version=7.0.72
|
clothconfig_version=7.0.72
|
||||||
yacl_version=2.2.0
|
yacl_version=2.2.0
|
||||||
bedrockify_version=1.9+mc1.20
|
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
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -1,123 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'com.github.johnrengelman.shadow'
|
|
||||||
id "me.shedaniel.unified-publishing"
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
name = 'NeoForged'
|
|
||||||
url = 'https://maven.neoforged.net/releases'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
architectury {
|
|
||||||
platformSetupLoomIde()
|
|
||||||
neoForge()
|
|
||||||
}
|
|
||||||
|
|
||||||
loom {
|
|
||||||
accessWidenerPath = project(":common").loom.accessWidenerPath
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
common {
|
|
||||||
canBeResolved = true
|
|
||||||
canBeConsumed = false
|
|
||||||
}
|
|
||||||
compileClasspath.extendsFrom common
|
|
||||||
runtimeClasspath.extendsFrom common
|
|
||||||
developmentNeoForge.extendsFrom common
|
|
||||||
|
|
||||||
// Files in this configuration will be bundled into your mod using the Shadow plugin.
|
|
||||||
// Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files.
|
|
||||||
shadowBundle {
|
|
||||||
canBeResolved = true
|
|
||||||
canBeConsumed = false
|
|
||||||
}
|
|
||||||
archivesBaseName = rootProject.archives_base_name + "-neoforge"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
neoForge "net.neoforged:neoforge:$rootProject.neoforge_version"
|
|
||||||
modImplementation include ("maven.modrinth:midnightlib:${rootProject.midnightlib_version}-neoforge")
|
|
||||||
modImplementation include ("maven.modrinth:obsidianui:${rootProject.obsidianui_version}-neoforge") {}
|
|
||||||
shadowBundle('org.aperlambda:lambdajcommon:1.8.1') {
|
|
||||||
exclude group: 'com.google.code.gson'
|
|
||||||
exclude group: 'com.google.guava'
|
|
||||||
}
|
|
||||||
|
|
||||||
common(project(path: ':common', configuration: 'namedElements')) { transitive false }
|
|
||||||
shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge')
|
|
||||||
}
|
|
||||||
|
|
||||||
processResources {
|
|
||||||
inputs.property 'version', project.version
|
|
||||||
|
|
||||||
filesMatching('META-INF/neoforge.mods.toml') {
|
|
||||||
expand version: project.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shadowJar {
|
|
||||||
configurations = [project.configurations.shadowBundle]
|
|
||||||
archiveClassifier = 'dev-shadow'
|
|
||||||
}
|
|
||||||
|
|
||||||
remapJar {
|
|
||||||
input.set shadowJar.archiveFile
|
|
||||||
}
|
|
||||||
|
|
||||||
sourcesJar {
|
|
||||||
def commonSources = project(":common").sourcesJar
|
|
||||||
dependsOn commonSources
|
|
||||||
from commonSources.archiveFile.map { zipTree(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
components.java {
|
|
||||||
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
|
||||||
skip()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unifiedPublishing {
|
|
||||||
project {
|
|
||||||
displayName = "MidnightControls $project.version - NeoForge $project.minecraft_version"
|
|
||||||
releaseType = "$project.release_type"
|
|
||||||
changelog = releaseChangelog()
|
|
||||||
gameVersions = []
|
|
||||||
gameLoaders = ["neoforge"]
|
|
||||||
mainPublication remapJar
|
|
||||||
relations {
|
|
||||||
includes {
|
|
||||||
curseforge = "midnightlib"
|
|
||||||
modrinth = "midnightlib"
|
|
||||||
}
|
|
||||||
includes {
|
|
||||||
curseforge = "obsidianui"
|
|
||||||
modrinth = "obsidianui"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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-$project.name"
|
|
||||||
gameVersions.addAll project.minecraft_version
|
|
||||||
if (project.supported_versions != "") gameVersions.addAll project.supported_versions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
loom.platform=neoforge
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util.platform.neoforge;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
|
||||||
import net.minecraft.item.ItemGroup;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of neoforge methods for
|
|
||||||
* @see eu.midnightdust.midnightcontrols.client.util.platform.ItemGroupUtil
|
|
||||||
*/
|
|
||||||
public class ItemGroupUtilImpl {
|
|
||||||
public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
|
||||||
return (screen.getCurrentPage().getVisibleTabs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.util.platform.neoforge;
|
|
||||||
|
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
|
||||||
import net.minecraft.network.packet.CustomPayload;
|
|
||||||
import net.minecraft.network.packet.Packet;
|
|
||||||
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of neoforge methods for
|
|
||||||
* @see eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil
|
|
||||||
*/
|
|
||||||
public class NetworkUtilImpl {
|
|
||||||
private static final ClientPlayNetworkHandler handler = client.getNetworkHandler();
|
|
||||||
|
|
||||||
public static void sendPacketC2S(Packet<?> packet) {
|
|
||||||
if (handler != null)
|
|
||||||
handler.send(packet);
|
|
||||||
}
|
|
||||||
public static void sendPayloadC2S(CustomPayload payload) {
|
|
||||||
if (handler != null && client.world != null) {
|
|
||||||
try {
|
|
||||||
handler.send(new CustomPayloadC2SPacket(payload));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.fillInStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.neoforge;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.HelloPayload;
|
|
||||||
import net.minecraft.resource.DirectoryResourcePack;
|
|
||||||
import net.minecraft.resource.ResourcePackInfo;
|
|
||||||
import net.minecraft.resource.ResourcePackPosition;
|
|
||||||
import net.minecraft.resource.ResourcePackProfile;
|
|
||||||
import net.minecraft.resource.ResourcePackSource;
|
|
||||||
import net.minecraft.resource.ResourceType;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.neoforged.api.distmarker.Dist;
|
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
|
||||||
import net.neoforged.fml.ModList;
|
|
||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
|
||||||
import net.neoforged.fml.common.Mod;
|
|
||||||
import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent;
|
|
||||||
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
|
||||||
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
|
||||||
import net.neoforged.neoforge.event.AddPackFindersEvent;
|
|
||||||
import net.neoforged.neoforgespi.locating.IModFile;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControlsConstants.NAMESPACE;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_DOWN;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_LEFT;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_RIGHT;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_UP;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_RING;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
|
|
||||||
@Mod(value = NAMESPACE, dist = Dist.CLIENT)
|
|
||||||
public class MidnightControlsClientNeoforge {
|
|
||||||
public MidnightControlsClientNeoforge() {
|
|
||||||
MidnightControlsClient.initClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventBusSubscriber(modid = NAMESPACE, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
|
|
||||||
public class ClientEvents {
|
|
||||||
@SubscribeEvent
|
|
||||||
public static void registerKeybinding(RegisterKeyMappingsEvent event) {
|
|
||||||
event.register(BINDING_RING);
|
|
||||||
event.register(BINDING_LOOK_UP);
|
|
||||||
event.register(BINDING_LOOK_DOWN);
|
|
||||||
event.register(BINDING_LOOK_LEFT);
|
|
||||||
event.register(BINDING_LOOK_RIGHT);
|
|
||||||
}
|
|
||||||
@SubscribeEvent
|
|
||||||
public static void addPackFinders(AddPackFindersEvent event) {
|
|
||||||
if (event.getPackType() == ResourceType.CLIENT_RESOURCES) {
|
|
||||||
registerResourcePack(event, id("bedrock"), false);
|
|
||||||
registerResourcePack(event, id("legacy"), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void registerResourcePack(AddPackFindersEvent event, Identifier id, boolean alwaysEnabled) {
|
|
||||||
event.addRepositorySource(((profileAdder) -> {
|
|
||||||
IModFile file = ModList.get().getModFileById(id.getNamespace()).getFile();
|
|
||||||
try {
|
|
||||||
ResourcePackProfile.PackFactory pack = new DirectoryResourcePack.DirectoryBackedFactory(file.findResource("resourcepacks/" + id.getPath()));
|
|
||||||
ResourcePackInfo info = new ResourcePackInfo(id.toString(), Text.of(id.getNamespace()+"/"+id.getPath()), ResourcePackSource.BUILTIN, Optional.empty());
|
|
||||||
ResourcePackProfile packProfile = ResourcePackProfile.create(info, pack, ResourceType.CLIENT_RESOURCES, new ResourcePackPosition(alwaysEnabled, ResourcePackProfile.InsertionPosition.TOP, false));
|
|
||||||
if (packProfile != null) {
|
|
||||||
profileAdder.accept(packProfile);
|
|
||||||
}
|
|
||||||
} catch (NullPointerException e) {e.fillInStackTrace();}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventBusSubscriber(modid = NAMESPACE, bus = EventBusSubscriber.Bus.GAME, value = Dist.CLIENT)
|
|
||||||
public class ClientGameEvents {
|
|
||||||
@SubscribeEvent
|
|
||||||
public static void sendPacketOnLogin(ClientPlayerNetworkEvent.LoggingIn event) {
|
|
||||||
var version = ModList.get().getModFileById(NAMESPACE).versionString();
|
|
||||||
var controlsMode = MidnightControlsConfig.controlsMode.getName();
|
|
||||||
NetworkUtil.sendPayloadC2S(new HelloPayload(version, controlsMode));
|
|
||||||
NetworkUtil.sendPayloadC2S(new ControlsModePayload(controlsMode));
|
|
||||||
}
|
|
||||||
@SubscribeEvent
|
|
||||||
public static void onDisconnect(ClientPlayerNetworkEvent.LoggingOut event) {
|
|
||||||
MidnightControlsClient.onLeave();
|
|
||||||
}
|
|
||||||
@SubscribeEvent
|
|
||||||
public static void startClientTick(ClientTickEvent.Pre event) {
|
|
||||||
MidnightControlsClient.onTick(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.neoforge;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|
||||||
import eu.midnightdust.midnightcontrols.neoforge.event.PlayerChangeControlsModeEvent;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.FeaturePayload;
|
|
||||||
import eu.midnightdust.midnightcontrols.packet.HelloPayload;
|
|
||||||
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket;
|
|
||||||
import net.minecraft.network.packet.s2c.common.CustomPayloadS2CPacket;
|
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
|
||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
|
||||||
import net.neoforged.fml.common.Mod;
|
|
||||||
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
|
|
||||||
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControlsConstants.NAMESPACE;
|
|
||||||
|
|
||||||
@Mod(value = NAMESPACE)
|
|
||||||
public class MidnightControlsNeoforge {
|
|
||||||
public MidnightControlsNeoforge() {
|
|
||||||
MidnightControls.init();
|
|
||||||
}
|
|
||||||
@EventBusSubscriber(modid = NAMESPACE, bus = EventBusSubscriber.Bus.MOD)
|
|
||||||
public class CommonEvents {
|
|
||||||
@SubscribeEvent
|
|
||||||
public static void registerPayloads(RegisterPayloadHandlersEvent event) {
|
|
||||||
PayloadRegistrar registrar = event.registrar("1").optional();
|
|
||||||
registrar.playToServer(HelloPayload.PACKET_ID, HelloPayload.codec, (payload, context) -> {
|
|
||||||
ControlsMode.byId(payload.controlsMode()).ifPresent(controlsMode -> new PlayerChangeControlsModeEvent(context.player(), controlsMode));
|
|
||||||
context.connection().send(new CustomPayloadS2CPacket(new FeaturePayload(MidnightControlsFeature.HORIZONTAL_REACHAROUND)));
|
|
||||||
});
|
|
||||||
registrar.playBidirectional(ControlsModePayload.PACKET_ID, ControlsModePayload.codec, (payload, context) -> {
|
|
||||||
if (context.flow().isServerbound()) ControlsMode.byId(payload.controlsMode()).ifPresent(controlsMode -> new PlayerChangeControlsModeEvent(context.player(), controlsMode));
|
|
||||||
else context.connection().send(new CustomPayloadC2SPacket(new ControlsModePayload(MidnightControlsConfig.controlsMode.getName())));
|
|
||||||
});
|
|
||||||
registrar.playToClient(FeaturePayload.PACKET_ID, FeaturePayload.codec, (payload, context) -> {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package eu.midnightdust.midnightcontrols.neoforge.event;
|
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.neoforged.bus.api.Event;
|
|
||||||
import net.neoforged.fml.event.IModBusEvent;
|
|
||||||
|
|
||||||
public class PlayerChangeControlsModeEvent extends Event implements IModBusEvent {
|
|
||||||
public PlayerChangeControlsModeEvent(PlayerEntity player, ControlsMode controlsMode) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
modLoader = "javafml"
|
|
||||||
loaderVersion = "[2,)"
|
|
||||||
#issueTrackerURL = ""
|
|
||||||
license = "MIT License"
|
|
||||||
|
|
||||||
[[mods]]
|
|
||||||
modId = "midnightcontrols"
|
|
||||||
version = "${version}"
|
|
||||||
displayName = "MidnightControls"
|
|
||||||
logoFile = "icon.png"
|
|
||||||
authors = "Motschen, LambdAurora"
|
|
||||||
contributors = "akemin-dayo, DioEgizio, dogtopus, egeesin, EnnuiL, FlashyReese, gyular, Hambaka, Ivanoks, joaoh1, KiskaUWU, Madis0, RaptaG, ronniedude, spudpiggy, TrueHorse"
|
|
||||||
description = '''
|
|
||||||
Adds controller support and enhanced controls overall.
|
|
||||||
'''
|
|
||||||
|
|
||||||
[[mixins]]
|
|
||||||
config = "midnightcontrols.mixins.json"
|
|
||||||
|
|
||||||
[[dependencies.midnightcontrols]]
|
|
||||||
modId = "neoforge"
|
|
||||||
mandatory = true
|
|
||||||
versionRange = "[21.0,)"
|
|
||||||
ordering = "NONE"
|
|
||||||
side = "BOTH"
|
|
||||||
|
|
||||||
[[dependencies.midnightcontrols]]
|
|
||||||
modId = "minecraft"
|
|
||||||
mandatory = true
|
|
||||||
versionRange = "[1.21,)"
|
|
||||||
ordering = "NONE"
|
|
||||||
side = "BOTH"
|
|
||||||
|
|
||||||
[[dependencies.midnightcontrols]]
|
|
||||||
modId = "midnightlib"
|
|
||||||
mandatory = true
|
|
||||||
versionRange = "[1.0,)"
|
|
||||||
ordering = "AFTER"
|
|
||||||
side = "BOTH"
|
|
||||||
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -1,15 +1,11 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
maven { url "https://maven.fabricmc.net/" }
|
maven {
|
||||||
maven { url "https://maven.architectury.dev/" }
|
name 'Fabric'
|
||||||
maven { url "https://maven.neoforged.net/releases" }
|
url 'https://maven.fabricmc.net/'
|
||||||
|
}
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
include("common")
|
rootProject.name = 'midnightcontrols'
|
||||||
include("fabric")
|
|
||||||
//include("quilt") // Native quilt support is disabled atm, as the Quilt libraries are currently in maintenance mode
|
|
||||||
include("neoforge")
|
|
||||||
|
|
||||||
rootProject.name = "midnightcontrols"
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols;
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
|
import dev.lambdaurora.spruceui.util.Nameable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.thinkingstudio.obsidianui.util.Nameable;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -22,7 +22,7 @@ import java.util.Optional;
|
|||||||
* @version 1.7.0
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum ControlsMode {
|
public enum ControlsMode implements Nameable {
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
CONTROLLER,
|
CONTROLLER,
|
||||||
TOUCHSCREEN;
|
TOUCHSCREEN;
|
||||||
@@ -49,6 +49,7 @@ public enum ControlsMode {
|
|||||||
return "midnightcontrols.controls_mode." + this.getName();
|
return "midnightcontrols.controls_mode." + this.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.name().toLowerCase();
|
return this.name().toLowerCase();
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.event.PlayerChangeControlsModeCallback;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.fabricmc.loader.api.ModContainer;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the MidnightControls mod.
|
||||||
|
*
|
||||||
|
* @author LambdAurora & Motschen
|
||||||
|
* @version 1.8.0
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class MidnightControls implements ModInitializer {
|
||||||
|
private static MidnightControls INSTANCE;
|
||||||
|
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(MidnightControlsConstants.CONTROLS_MODE_CHANNEL.toString());
|
||||||
|
public static final Identifier FEATURE_CHANNEL = new Identifier(MidnightControlsConstants.FEATURE_CHANNEL.toString());
|
||||||
|
public static final Identifier HELLO_CHANNEL = new Identifier(MidnightControlsConstants.HELLO_CHANNEL.toString());
|
||||||
|
public static boolean isExtrasLoaded;
|
||||||
|
|
||||||
|
public final Logger logger = LogManager.getLogger("MidnightControls");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitialize() {
|
||||||
|
INSTANCE = this;
|
||||||
|
isExtrasLoaded = FabricLoader.getInstance().isModLoaded("midnightcontrols-extra");
|
||||||
|
this.log("Initializing MidnightControls...");
|
||||||
|
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(HELLO_CHANNEL, (server, player, handler, buf, responseSender) -> {
|
||||||
|
String version = buf.readString(32);
|
||||||
|
ControlsMode.byId(buf.readString(32))
|
||||||
|
.ifPresent(controlsMode -> server
|
||||||
|
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode)));
|
||||||
|
server.execute(() -> {
|
||||||
|
ServerPlayNetworking.send(player, FEATURE_CHANNEL, this.makeFeatureBuffer(MidnightControlsFeature.HORIZONTAL_REACHAROUND));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL,
|
||||||
|
(server, player, handler, buf, responseSender) -> ControlsMode.byId(buf.readString(32))
|
||||||
|
.ifPresent(controlsMode -> server
|
||||||
|
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(player, controlsMode))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a message to the terminal.
|
||||||
|
*
|
||||||
|
* @param info the message to print
|
||||||
|
*/
|
||||||
|
public void log(String info) {
|
||||||
|
this.logger.info("[MidnightControls] " + info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a warning to the terminal.
|
||||||
|
*
|
||||||
|
* @param warning the warning to print
|
||||||
|
*/
|
||||||
|
public void warn(String warning) {
|
||||||
|
this.logger.info("[MidnightControls] " + warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a packet byte buffer made for the midnightcontrols:controls_mode plugin message.
|
||||||
|
*
|
||||||
|
* @param controlsMode the controls mode to send
|
||||||
|
* @return the packet byte buffer
|
||||||
|
*/
|
||||||
|
public PacketByteBuf makeControlsModeBuffer(@NotNull ControlsMode controlsMode) {
|
||||||
|
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
|
||||||
|
return new PacketByteBuf(Unpooled.buffer()).writeString(controlsMode.getName(), 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a packet byte buffer made for the midnightcontrols:feature plugin message.
|
||||||
|
*
|
||||||
|
* @param features the features data to send
|
||||||
|
* @return the packet byte buffer
|
||||||
|
*/
|
||||||
|
public PacketByteBuf makeFeatureBuffer(MidnightControlsFeature... features) {
|
||||||
|
if (features.length == 0)
|
||||||
|
throw new IllegalArgumentException("At least one feature must be provided.");
|
||||||
|
var buffer = new PacketByteBuf(Unpooled.buffer());
|
||||||
|
buffer.writeVarInt(features.length);
|
||||||
|
for (var feature : features) {
|
||||||
|
buffer.writeString(feature.getName(), 64);
|
||||||
|
buffer.writeBoolean(feature.isAllowed());
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketByteBuf makeHello(@NotNull ControlsMode controlsMode) {
|
||||||
|
var version = "";
|
||||||
|
Optional<ModContainer> container;
|
||||||
|
if ((container = FabricLoader.getInstance().getModContainer(MidnightControlsConstants.NAMESPACE)).isPresent()) {
|
||||||
|
version = container.get().getMetadata().getVersion().getFriendlyString();
|
||||||
|
}
|
||||||
|
return new PacketByteBuf(Unpooled.buffer()).writeString(version, 32).writeString(controlsMode.getName(), 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the MidnightControls instance.
|
||||||
|
*
|
||||||
|
* @return the MidnightControls instance
|
||||||
|
*/
|
||||||
|
public static MidnightControls get() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,8 +12,6 @@ package eu.midnightdust.midnightcontrols;
|
|||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the constants used by MidnightControls.
|
* Represents the constants used by MidnightControls.
|
||||||
*
|
*
|
||||||
@@ -23,7 +21,7 @@ import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|||||||
*/
|
*/
|
||||||
public class MidnightControlsConstants {
|
public class MidnightControlsConstants {
|
||||||
public static final String NAMESPACE = "midnightcontrols";
|
public static final String NAMESPACE = "midnightcontrols";
|
||||||
public static final Identifier CONTROLS_MODE_CHANNEL = id("controls_mode");
|
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(NAMESPACE, "controls_mode");
|
||||||
public static final Identifier FEATURE_CHANNEL = id("feature");
|
public static final Identifier FEATURE_CHANNEL = new Identifier(NAMESPACE, "feature");
|
||||||
public static final Identifier HELLO_CHANNEL = id("hello");
|
public static final Identifier HELLO_CHANNEL = new Identifier("lambdacontrols", "hello");
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols;
|
package eu.midnightdust.midnightcontrols;
|
||||||
|
|
||||||
import org.thinkingstudio.obsidianui.util.Nameable;
|
import dev.lambdaurora.spruceui.util.Nameable;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -44,7 +44,6 @@ public class MidnightControlsFeature implements Nameable {
|
|||||||
this.setEnabled(this.defaultEnabled = enabled);
|
this.setEnabled(this.defaultEnabled = enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public MidnightControlsFeature(@NotNull String key) {
|
public MidnightControlsFeature(@NotNull String key) {
|
||||||
this(key, false, false);
|
this(key, false, false);
|
||||||
}
|
}
|
||||||
@@ -52,7 +51,6 @@ public class MidnightControlsFeature implements Nameable {
|
|||||||
/**
|
/**
|
||||||
* Allows the feature.
|
* Allows the feature.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public void allow() {
|
public void allow() {
|
||||||
this.setAllowed(true);
|
this.setAllowed(true);
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client;
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
|
import dev.lambdaurora.spruceui.event.OpenScreenCallback;
|
||||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
@@ -21,17 +22,22 @@ import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
|||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsHud;
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsHud;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||||
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
|
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
|
||||||
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
|
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
|
||||||
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
import dev.lambdaurora.spruceui.hud.HudManager;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import org.thinkingstudio.obsidianui.hud.HudManager;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||||
|
import net.fabricmc.fabric.api.resource.ResourcePackActivationType;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
import net.minecraft.client.option.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import net.minecraft.client.toast.SystemToast;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
@@ -44,70 +50,99 @@ import java.io.File;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the midnightcontrols client mod.
|
* Represents the midnightcontrols client mod.
|
||||||
*
|
*
|
||||||
* @author Motschen, LambdAurora
|
* @author LambdAurora
|
||||||
* @version 1.10.0
|
* @version 1.7.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class MidnightControlsClient extends MidnightControls {
|
public class MidnightControlsClient extends MidnightControls implements ClientModInitializer {
|
||||||
public static boolean lateInitDone = false;
|
public static boolean lateInitDone = false;
|
||||||
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(id("look_up"),
|
private static MidnightControlsClient INSTANCE;
|
||||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.midnightcontrols");
|
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_up"),
|
||||||
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(id("look_right"),
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement");
|
||||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.midnightcontrols");
|
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_right"),
|
||||||
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(id("look_down"),
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.movement");
|
||||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.midnightcontrols");
|
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_down"),
|
||||||
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(id("look_left"),
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.movement");
|
||||||
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.midnightcontrols");
|
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_left"),
|
||||||
public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(id("ring"),
|
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.movement");
|
||||||
InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), "key.categories.midnightcontrols");
|
public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "ring"),
|
||||||
public static final Identifier CONTROLLER_BUTTONS = id("textures/gui/controller_buttons.png");
|
InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), "key.categories.misc");
|
||||||
public static final Identifier CONTROLLER_EXPANDED = id("textures/gui/controller_expanded.png");
|
public static final Identifier CONTROLLER_BUTTONS = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_buttons.png");
|
||||||
public static final Identifier CONTROLLER_AXIS = id("textures/gui/controller_axis.png");
|
public static final Identifier CONTROLLER_EXPANDED = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_expanded.png");
|
||||||
public static final Identifier WAYLAND_CURSOR_TEXTURE_LIGHT = id("cursor/light/mouse_pointer");
|
public static final Identifier CONTROLLER_AXIS = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_axis.png");
|
||||||
public static final Identifier WAYLAND_CURSOR_TEXTURE_DARK = id("cursor/dark/mouse_pointer");
|
public static final Identifier CURSOR_TEXTURE = new Identifier(MidnightControlsConstants.NAMESPACE, "textures/gui/cursor.png");
|
||||||
public static final File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt");
|
public final static File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt");
|
||||||
public static final MinecraftClient client = MinecraftClient.getInstance();
|
public final MidnightInput input = new MidnightInput();
|
||||||
public static final MidnightInput input = new MidnightInput();
|
public final MidnightRing ring = new MidnightRing(this);
|
||||||
public static final MidnightRing ring = new MidnightRing();
|
public final MidnightReacharound reacharound = new MidnightReacharound();
|
||||||
public static final MidnightReacharound reacharound = new MidnightReacharound();
|
private MidnightControlsHud hud;
|
||||||
public static boolean isWayland;
|
private ControlsMode previousControlsMode;
|
||||||
private static MidnightControlsHud hud;
|
|
||||||
private static ControlsMode previousControlsMode;
|
|
||||||
|
|
||||||
public static void initClient() {
|
@Override
|
||||||
ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY);
|
public void onInitializeClient() {
|
||||||
|
INSTANCE = this;
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_UP);
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT);
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN);
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT);
|
||||||
|
KeyBindingHelper.registerKeyBinding(BINDING_RING);
|
||||||
|
|
||||||
|
this.ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY);
|
||||||
|
|
||||||
|
ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (client, handler, buf, responseSender) ->
|
||||||
|
responseSender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode)));
|
||||||
|
ClientPlayNetworking.registerGlobalReceiver(FEATURE_CHANNEL, (client, handler, buf, responseSender) -> {
|
||||||
|
int features = buf.readVarInt();
|
||||||
|
for (int i = 0; i < features; i++) {
|
||||||
|
var name = buf.readString(64);
|
||||||
|
boolean allowed = buf.readBoolean();
|
||||||
|
MidnightControlsFeature.fromName(name).ifPresent(feature -> client.execute(() -> feature.setAllowed(allowed)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
||||||
|
sender.sendPacket(HELLO_CHANNEL, this.makeHello(MidnightControlsConfig.controlsMode));
|
||||||
|
sender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode));
|
||||||
|
});
|
||||||
|
ClientPlayConnectionEvents.DISCONNECT.register(this::onLeave);
|
||||||
|
|
||||||
|
ClientTickEvents.START_CLIENT_TICK.register(this.reacharound::tick);
|
||||||
|
ClientTickEvents.START_CLIENT_TICK.register(this::onTick);
|
||||||
|
|
||||||
|
OpenScreenCallback.EVENT.register((client, screen) -> {
|
||||||
|
if (screen == null && MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) {
|
||||||
|
screen = new TouchscreenOverlay(this);
|
||||||
|
screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||||
|
client.skipGameRender = false;
|
||||||
|
client.currentScreen = screen;
|
||||||
|
} else if (screen != null) {
|
||||||
|
this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
int delay = 0; // delay for 0 sec.
|
int delay = 0; // delay for 0 sec.
|
||||||
int period = 1; // repeat every 0.001 sec. (1000 times a second)
|
int period = 1; // repeat every 0.001 sec. (100 times a second)
|
||||||
Timer timer = new Timer();
|
Timer timer = new Timer();
|
||||||
timer.scheduleAtFixedRate(new TimerTask() {
|
timer.scheduleAtFixedRate(new TimerTask() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
input.updateCamera(client);
|
||||||
if (lateInitDone && client.isRunning()) {
|
|
||||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput)) {
|
|
||||||
input.tickCameraStick();
|
|
||||||
input.updateCamera();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception | Error e) {
|
|
||||||
MidnightControls.logger.error("Exception encountered in camera loop: ",e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, delay, period);
|
}, delay, period);
|
||||||
|
|
||||||
HudManager.register(hud = new MidnightControlsHud());
|
HudManager.register(this.hud = new MidnightControlsHud(this));
|
||||||
isWayland = GLFW.glfwGetVersionString().contains("Wayland");
|
FabricLoader.getInstance().getModContainer("midnightcontrols").ifPresent(modContainer -> {
|
||||||
|
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","bedrock"), modContainer, ResourcePackActivationType.NORMAL);
|
||||||
|
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","legacy"), modContainer, ResourcePackActivationType.NORMAL);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when Minecraft is initializing.
|
* This method is called when Minecraft is initializing.
|
||||||
*/
|
*/
|
||||||
public static void onMcInit(@NotNull MinecraftClient client) {
|
public void onMcInit(@NotNull MinecraftClient client) {
|
||||||
ButtonBinding.init(client.options);
|
ButtonBinding.init(client.options);
|
||||||
MidnightControlsConfig.load();
|
MidnightControlsConfig.load();
|
||||||
if (MidnightControlsConfig.configVersion < 2) {
|
if (MidnightControlsConfig.configVersion < 2) {
|
||||||
@@ -116,9 +151,9 @@ public class MidnightControlsClient extends MidnightControls {
|
|||||||
MidnightControlsConfig.mouseScreens.remove("net.minecraft.class_5375");
|
MidnightControlsConfig.mouseScreens.remove("net.minecraft.class_5375");
|
||||||
MidnightControlsConfig.mouseScreens.remove("net.minecraft.client.gui.screen.pack.PackScreen");
|
MidnightControlsConfig.mouseScreens.remove("net.minecraft.client.gui.screen.pack.PackScreen");
|
||||||
MidnightControlsConfig.configVersion = 2;
|
MidnightControlsConfig.configVersion = 2;
|
||||||
MidnightControlsConfig.write(MidnightControlsConstants.NAMESPACE);
|
MidnightControlsConfig.write("midnightcontrols");
|
||||||
}
|
}
|
||||||
hud.setVisible(MidnightControlsConfig.hudEnable);
|
this.hud.setVisible(MidnightControlsConfig.hudEnable);
|
||||||
Controller.updateMappings();
|
Controller.updateMappings();
|
||||||
try {
|
try {
|
||||||
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
||||||
@@ -131,16 +166,17 @@ public class MidnightControlsClient extends MidnightControls {
|
|||||||
null));
|
null));
|
||||||
}
|
}
|
||||||
|
|
||||||
switchControlsMode();
|
this.switchControlsMode();
|
||||||
});
|
});
|
||||||
} catch (Exception e) {e.fillInStackTrace();}
|
} catch (Exception e) {e.fillInStackTrace();}
|
||||||
|
|
||||||
MidnightControlsCompat.init();
|
MidnightControlsCompat.init(this);
|
||||||
}
|
}
|
||||||
|
ButtonCategory category;
|
||||||
/**
|
/**
|
||||||
* This method is called to initialize keybindings
|
* This method is called to initialize keybindings
|
||||||
*/
|
*/
|
||||||
public static void initKeybindings() {
|
public void initKeybindings() {
|
||||||
if (lateInitDone) return;
|
if (lateInitDone) return;
|
||||||
if (KeyBindingIDAccessor.getKEYS_BY_ID() == null || KeyBindingIDAccessor.getKEYS_BY_ID().isEmpty()) 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("voxelmap") && !KeyBindingIDAccessor.getKEYS_BY_ID().containsKey("key.minimap.toggleingamewaypoints")) return;
|
||||||
@@ -148,20 +184,20 @@ public class MidnightControlsClient extends MidnightControls {
|
|||||||
for (int i = 0; i < KeyBindingIDAccessor.getKEYS_BY_ID().size(); ++i) {
|
for (int i = 0; i < KeyBindingIDAccessor.getKEYS_BY_ID().size(); ++i) {
|
||||||
KeyBinding keyBinding = KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().toList().get(i).getValue();
|
KeyBinding keyBinding = KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().toList().get(i).getValue();
|
||||||
if (MidnightControlsConfig.excludedKeybindings.stream().noneMatch(excluded -> keyBinding.getTranslationKey().startsWith(excluded))) {
|
if (MidnightControlsConfig.excludedKeybindings.stream().noneMatch(excluded -> keyBinding.getTranslationKey().startsWith(excluded))) {
|
||||||
if (!keyBinding.getTranslationKey().contains(MidnightControlsConstants.NAMESPACE)) {
|
if (!keyBinding.getTranslationKey().contains("midnightcontrols") && !keyBinding.getTranslationKey().contains("ok_zoomer") && !keyBinding.getTranslationKey().contains("okzoomer")) {
|
||||||
AtomicReference<ButtonCategory> category = new AtomicReference<>();
|
category = null;
|
||||||
InputManager.streamCategories().forEach(buttonCategory -> {
|
InputManager.streamCategories().forEach(buttonCategory -> {
|
||||||
if (buttonCategory.getIdentifier().equals(validVanillaId(keyBinding.getCategory())))
|
if (buttonCategory.getIdentifier().equals(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory())))
|
||||||
category.set(buttonCategory);
|
category = buttonCategory;
|
||||||
});
|
});
|
||||||
if (category.get() == null) {
|
if (category == null) {
|
||||||
category.set(new ButtonCategory(validVanillaId(keyBinding.getCategory())));
|
category = new ButtonCategory(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory()));
|
||||||
InputManager.registerCategory(category.get());
|
InputManager.registerCategory(category);
|
||||||
}
|
}
|
||||||
ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getTranslationKey()).category(category.get()).linkKeybind(keyBinding).register();
|
ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getTranslationKey()).category(category).linkKeybind(keyBinding).register();
|
||||||
if (MidnightControlsConfig.debug) {
|
if (MidnightControlsConfig.debug) {
|
||||||
MidnightControls.log(keyBinding.getTranslationKey());
|
logger.info(keyBinding.getTranslationKey());
|
||||||
MidnightControls.log(String.valueOf(buttonBinding));
|
logger.info(buttonBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,26 +205,17 @@ public class MidnightControlsClient extends MidnightControls {
|
|||||||
InputManager.loadButtonBindings();
|
InputManager.loadButtonBindings();
|
||||||
lateInitDone = true;
|
lateInitDone = true;
|
||||||
}
|
}
|
||||||
private static Identifier validVanillaId(String path) {
|
|
||||||
for(int i = 0; i < path.length(); ++i) {
|
|
||||||
if (!Identifier.isPathCharacterValid(path.charAt(i))) {
|
|
||||||
path = path.replace(path.charAt(i), '_');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Identifier.ofVanilla(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called every Minecraft tick.
|
* This method is called every Minecraft tick.
|
||||||
*
|
*
|
||||||
* @param client the client instance
|
* @param client the client instance
|
||||||
*/
|
*/
|
||||||
public static void onTick(@NotNull MinecraftClient client) {
|
public void onTick(@NotNull MinecraftClient client) {
|
||||||
initKeybindings();
|
this.initKeybindings();
|
||||||
input.tick();
|
this.input.tick(client);
|
||||||
reacharound.tick();
|
|
||||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput))
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput))
|
||||||
input.tickController();
|
this.input.tickController(client);
|
||||||
|
|
||||||
if (BINDING_RING.wasPressed()) {
|
if (BINDING_RING.wasPressed()) {
|
||||||
ring.loadFromUnbound();
|
ring.loadFromUnbound();
|
||||||
@@ -201,46 +228,31 @@ public class MidnightControlsClient extends MidnightControls {
|
|||||||
MidnightControlsConfig.enableHints = false;
|
MidnightControlsConfig.enableHints = false;
|
||||||
MidnightControlsConfig.save();
|
MidnightControlsConfig.save();
|
||||||
}
|
}
|
||||||
RainbowColor.tick();
|
|
||||||
TouchInput.tick();
|
TouchInput.tick();
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Called when opening a screen.
|
|
||||||
*/
|
|
||||||
public static void onScreenOpen(Screen screen) {
|
|
||||||
if (screen == null && MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) {
|
|
||||||
screen = new TouchscreenOverlay();
|
|
||||||
screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
|
||||||
client.skipGameRender = false;
|
|
||||||
client.currentScreen = screen;
|
|
||||||
} else if (screen != null) {
|
|
||||||
MidnightControlsClient.input.onScreenOpen(client.getWindow().getWidth(), client.getWindow().getHeight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when leaving a server.
|
* Called when leaving a server.
|
||||||
*/
|
*/
|
||||||
public static void onLeave() {
|
public void onLeave(ClientPlayNetworkHandler handler, MinecraftClient client) {
|
||||||
MidnightControlsFeature.resetAllAllowed();
|
MidnightControlsFeature.resetAllAllowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches the controls mode if the auto switch is enabled.
|
* Switches the controls mode if the auto switch is enabled.
|
||||||
*/
|
*/
|
||||||
public static void switchControlsMode() {
|
public void switchControlsMode() {
|
||||||
if (MidnightControlsConfig.autoSwitchMode) {
|
if (MidnightControlsConfig.autoSwitchMode) {
|
||||||
if (MidnightControlsConfig.getController().isGamepad()) {
|
if (MidnightControlsConfig.getController().isGamepad()) {
|
||||||
previousControlsMode = MidnightControlsConfig.controlsMode;
|
this.previousControlsMode = MidnightControlsConfig.controlsMode;
|
||||||
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||||
} else {
|
} else {
|
||||||
if (previousControlsMode == null) {
|
if (this.previousControlsMode == null) {
|
||||||
previousControlsMode = ControlsMode.DEFAULT;
|
this.previousControlsMode = ControlsMode.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
MidnightControlsConfig.controlsMode = previousControlsMode;
|
MidnightControlsConfig.controlsMode = this.previousControlsMode;
|
||||||
}
|
}
|
||||||
NetworkUtil.sendPayloadC2S(new ControlsModePayload(MidnightControlsConfig.controlsMode.getName()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,18 +261,16 @@ public class MidnightControlsClient extends MidnightControls {
|
|||||||
*
|
*
|
||||||
* @param enabled true if the HUD is enabled, else false
|
* @param enabled true if the HUD is enabled, else false
|
||||||
*/
|
*/
|
||||||
public static void setHudEnabled(boolean enabled) {
|
public void setHudEnabled(boolean enabled) {
|
||||||
MidnightControlsConfig.hudEnable = enabled;
|
MidnightControlsConfig.hudEnable = enabled;
|
||||||
hud.setVisible(enabled);
|
this.hud.setVisible(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final MidnightControlsClient INSTANCE = new MidnightControlsClient();
|
|
||||||
/**
|
/**
|
||||||
* Gets the midnightcontrols client instance.
|
* Gets the midnightcontrols client instance.
|
||||||
*
|
*
|
||||||
* @return the midnightcontrols client instance
|
* @return the midnightcontrols client instance
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public static MidnightControlsClient get() {
|
public static MidnightControlsClient get() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
@@ -14,13 +14,10 @@ import com.google.common.collect.Maps;
|
|||||||
import com.mojang.blaze3d.platform.GlDebugInfo;
|
import com.mojang.blaze3d.platform.GlDebugInfo;
|
||||||
import eu.midnightdust.lib.config.MidnightConfig;
|
import eu.midnightdust.lib.config.MidnightConfig;
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
import eu.midnightdust.midnightcontrols.ControlsMode;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
|
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
|
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
|
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
|
||||||
@@ -74,7 +71,6 @@ public class MidnightControlsConfig extends MidnightConfig {
|
|||||||
@Entry(category = VISUAL, name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102;
|
@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.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.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.25;
|
||||||
@Entry(category = CONTROLLER, name = "Trigger Dead-Zone", isSlider = true, min = 0.05, max = 1) public static double triggerDeadZone = 0.1;
|
|
||||||
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false;
|
@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.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.rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double rotationSpeed = 35.0; //used for x-axis, name kept for compatibility
|
||||||
@@ -112,12 +108,12 @@ public class MidnightControlsConfig extends MidnightConfig {
|
|||||||
@Entry @Hidden public static Map<String, String> BINDING = new HashMap<>();
|
@Entry @Hidden public static Map<String, String> BINDING = new HashMap<>();
|
||||||
|
|
||||||
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
|
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
|
||||||
@Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = 1;
|
@Deprecated @Hidden @Entry public static double[] maxAnalogValues = new double[]{1, 1, 1, 1};
|
||||||
@Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = 1;
|
@Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = maxAnalogValues[0];
|
||||||
@Entry(category = CONTROLLER, name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = 1;
|
@Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = maxAnalogValues[1];
|
||||||
@Entry(category = CONTROLLER, name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = 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 = CONTROLLER, name = "Trigger button fix") public static boolean triggerFix = true;
|
||||||
@Entry(category = CONTROLLER, name = "Excluded Controllers (Name Regex)") public static List<String> excludedControllers = Lists.newArrayList(".*(Keyboard)$", ".*(Touchpad)$", ".*(Pen)$", ".*(Finger)$");
|
|
||||||
@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",
|
@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.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");
|
"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");
|
||||||
@@ -133,8 +129,8 @@ public class MidnightControlsConfig extends MidnightConfig {
|
|||||||
* Loads the configuration
|
* Loads the configuration
|
||||||
*/
|
*/
|
||||||
public static void load() {
|
public static void load() {
|
||||||
MidnightControlsConfig.init(MidnightControlsConstants.NAMESPACE, MidnightControlsConfig.class);
|
MidnightControlsConfig.init("midnightcontrols", MidnightControlsConfig.class);
|
||||||
MidnightControls.log("Configuration loaded.");
|
MidnightControlsClient.get().log("Configuration loaded.");
|
||||||
// Controller controls.
|
// Controller controls.
|
||||||
InputManager.loadButtonBindings();
|
InputManager.loadButtonBindings();
|
||||||
}
|
}
|
||||||
@@ -143,8 +139,8 @@ public class MidnightControlsConfig extends MidnightConfig {
|
|||||||
* Saves the configuration.
|
* Saves the configuration.
|
||||||
*/
|
*/
|
||||||
public static void save() {
|
public static void save() {
|
||||||
MidnightControlsConfig.write(MidnightControlsConstants.NAMESPACE);
|
MidnightControlsConfig.write("midnightcontrols");
|
||||||
MidnightControls.log("Configuration saved.");
|
MidnightControlsClient.get().log("Configuration saved.");
|
||||||
MidnightControlsFeature.refreshEnabled();
|
MidnightControlsFeature.refreshEnabled();
|
||||||
}
|
}
|
||||||
public static void updateBindingsForController(Controller controller) {
|
public static void updateBindingsForController(Controller controller) {
|
||||||
@@ -191,7 +187,7 @@ public class MidnightControlsConfig extends MidnightConfig {
|
|||||||
*/
|
*/
|
||||||
public static void setController(Controller controller) {
|
public static void setController(Controller controller) {
|
||||||
MidnightControlsConfig.controllerID = controller.id();
|
MidnightControlsConfig.controllerID = controller.id();
|
||||||
MidnightControlsConfig.write(MidnightControlsConstants.NAMESPACE);
|
MidnightControlsConfig.write("midnightcontrols");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -279,20 +275,20 @@ public class MidnightControlsConfig extends MidnightConfig {
|
|||||||
buttons[count - 1] = Integer.parseInt(current);
|
buttons[count - 1] = Integer.parseInt(current);
|
||||||
}
|
}
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
MidnightControls.warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
MidnightControlsClient.get().warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
||||||
MidnightControlsConfig.setButtonBinding(button, new int[]{-1});
|
MidnightControlsConfig.setButtonBinding(button, new int[]{-1});
|
||||||
}
|
}
|
||||||
|
|
||||||
button.setButton(buttons);
|
button.setButton(buttons);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
MidnightControls.warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
MidnightControlsClient.get().warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
|
||||||
setButtonBinding(button, button.getButton());
|
setButtonBinding(button, button.getButton());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkValidity(@NotNull ButtonBinding binding, @NotNull String input, String group) {
|
private static boolean checkValidity(@NotNull ButtonBinding binding, @NotNull String input, String group) {
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
MidnightControls.warn("Malformed config value \"" + input + "\" for binding \"" + binding.getName() + "\".");
|
MidnightControlsClient.get().warn("Malformed config value \"" + input + "\" for binding \"" + binding.getName() + "\".");
|
||||||
setButtonBinding(binding, binding.getButton());
|
setButtonBinding(binding, binding.getButton());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -312,28 +308,28 @@ public class MidnightControlsConfig extends MidnightConfig {
|
|||||||
else BINDING.put("controller.controls." + binding.getName(), binding.getButtonCode());
|
else BINDING.put("controller.controls." + binding.getName(), binding.getButtonCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isBackButton(int btn, boolean isBtn, ButtonState state) {
|
public static boolean isBackButton(int btn, boolean isBtn, int state) {
|
||||||
if (!isBtn && state == ButtonState.NONE)
|
if (!isBtn && state == 0)
|
||||||
return false;
|
return false;
|
||||||
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false) == ButtonBinding.axisAsButton(btn, state == ButtonState.PRESS);
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false) == ButtonBinding.axisAsButton(btn, state == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isForwardButton(int btn, boolean isBtn, ButtonState state) {
|
public static boolean isForwardButton(int btn, boolean isBtn, int state) {
|
||||||
if (!isBtn && state == ButtonState.NONE)
|
if (!isBtn && state == 0)
|
||||||
return false;
|
return false;
|
||||||
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true) == ButtonBinding.axisAsButton(btn, state == ButtonState.PRESS);
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true) == ButtonBinding.axisAsButton(btn, state == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLeftButton(int btn, boolean isBtn, ButtonState state) {
|
public static boolean isLeftButton(int btn, boolean isBtn, int state) {
|
||||||
if (!isBtn && state == ButtonState.NONE)
|
if (!isBtn && state == 0)
|
||||||
return false;
|
return false;
|
||||||
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false) == ButtonBinding.axisAsButton(btn, state == ButtonState.PRESS);
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false) == ButtonBinding.axisAsButton(btn, state == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isRightButton(int btn, boolean isBtn, ButtonState state) {
|
public static boolean isRightButton(int btn, boolean isBtn, int state) {
|
||||||
if (!isBtn && state == ButtonState.NONE)
|
if (!isBtn && state == 0)
|
||||||
return false;
|
return false;
|
||||||
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true) == ButtonBinding.axisAsButton(btn, state == ButtonState.PRESS);
|
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true) == ButtonBinding.axisAsButton(btn, state == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -368,7 +364,7 @@ public class MidnightControlsConfig extends MidnightConfig {
|
|||||||
leftDeadZone = 0.25;
|
leftDeadZone = 0.25;
|
||||||
invertRightYAxis = false;
|
invertRightYAxis = false;
|
||||||
invertRightXAxis = false;
|
invertRightXAxis = false;
|
||||||
rotationSpeed = 35.0;
|
rotationSpeed = 40.0;
|
||||||
yAxisRotationSpeed = rotationSpeed;
|
yAxisRotationSpeed = rotationSpeed;
|
||||||
mouseSpeed = 25.0;
|
mouseSpeed = 25.0;
|
||||||
unfocusedInput = false;
|
unfocusedInput = false;
|
||||||
@@ -0,0 +1,935 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of midnightcontrols.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget;
|
||||||
|
import dev.lambdaurora.spruceui.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.*;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.ring.RingPage;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
|
||||||
|
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.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;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
|
||||||
|
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.MerchantScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.StonecutterScreen;
|
||||||
|
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
|
||||||
|
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
|
||||||
|
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
||||||
|
import net.minecraft.client.gui.widget.*;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.text.TranslatableTextContent;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import org.aperlambda.lambdacommon.utils.Pair;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.lwjgl.glfw.GLFWGamepadState;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the midnightcontrols' input handler.
|
||||||
|
*
|
||||||
|
* @author LambdAurora
|
||||||
|
* @version 1.7.0
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public class MidnightInput {
|
||||||
|
private static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
||||||
|
// Cooldowns
|
||||||
|
public int actionGuiCooldown = 0;
|
||||||
|
public int joystickCooldown = 0;
|
||||||
|
public boolean ignoreNextARelease = false;
|
||||||
|
public boolean ignoreNextXRelease = false;
|
||||||
|
private double targetYaw = 0.0;
|
||||||
|
private double targetPitch = 0.0;
|
||||||
|
private float prevXAxis = 0.f;
|
||||||
|
private float prevYAxis = 0.f;
|
||||||
|
private int targetMouseX = 0;
|
||||||
|
private int targetMouseY = 0;
|
||||||
|
private float mouseSpeedX = 0.f;
|
||||||
|
private float mouseSpeedY = 0.f;
|
||||||
|
public int inventoryInteractionCooldown = 0;
|
||||||
|
public int screenCloseCooldown = 0;
|
||||||
|
|
||||||
|
private ControllerControlsWidget controlsInput = null;
|
||||||
|
|
||||||
|
public MidnightInput() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called every Minecraft tick.
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
*/
|
||||||
|
public void tick(@NotNull MinecraftClient client) {
|
||||||
|
this.targetYaw = 0.F;
|
||||||
|
this.targetPitch = 0.F;
|
||||||
|
|
||||||
|
// Handles the key bindings.
|
||||||
|
if (MidnightControlsClient.BINDING_LOOK_UP.isPressed()) {
|
||||||
|
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 2);
|
||||||
|
} else if (MidnightControlsClient.BINDING_LOOK_DOWN.isPressed()) {
|
||||||
|
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 1);
|
||||||
|
}
|
||||||
|
if (MidnightControlsClient.BINDING_LOOK_LEFT.isPressed()) {
|
||||||
|
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 2);
|
||||||
|
} else if (MidnightControlsClient.BINDING_LOOK_RIGHT.isPressed()) {
|
||||||
|
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
InputManager.INPUT_MANAGER.tick(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called every Minecraft tick for controller input update.
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
*/
|
||||||
|
public void tickController(@NotNull MinecraftClient client) {
|
||||||
|
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0)
|
||||||
|
.forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
|
||||||
|
// 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);
|
||||||
|
this.fetchAxeInput(client, state, false);
|
||||||
|
}
|
||||||
|
MidnightControlsConfig.getSecondController().filter(Controller::isConnected)
|
||||||
|
.ifPresent(joycon -> {
|
||||||
|
GLFWGamepadState state = joycon.getState();
|
||||||
|
this.fetchButtonInput(client, state, true);
|
||||||
|
this.fetchAxeInput(client, state, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
boolean allowInput = this.controlsInput == null || this.controlsInput.focusedBinding == null;
|
||||||
|
|
||||||
|
if (allowInput)
|
||||||
|
InputManager.updateBindings(client);
|
||||||
|
|
||||||
|
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++)
|
||||||
|
buttons[i] = this.controlsInput.currentButtons.get(i);
|
||||||
|
this.controlsInput.finishBindingEdit(buttons);
|
||||||
|
this.controlsInput = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.inventoryInteractionCooldown > 0)
|
||||||
|
this.inventoryInteractionCooldown--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called before the screen is rendered.
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
* @param screen the screen to render
|
||||||
|
*/
|
||||||
|
public void onPreRenderScreen(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
||||||
|
if (!isScreenInteractive(screen)) {
|
||||||
|
InputManager.INPUT_MANAGER.updateMousePosition(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called to update the camera
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
*/
|
||||||
|
public void updateCamera(@NotNull MinecraftClient client) {
|
||||||
|
if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var player = client.player;
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.targetYaw != 0.f || this.targetPitch != 0.f) {
|
||||||
|
float rotationYaw = (float) (client.player.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() && 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when a Screen is opened.
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
* @param windowWidth the window width
|
||||||
|
* @param windowHeight the window height
|
||||||
|
*/
|
||||||
|
public void onScreenOpen(@NotNull MinecraftClient client, int windowWidth, int windowHeight) {
|
||||||
|
if (client.currentScreen == null) {
|
||||||
|
this.mouseSpeedX = this.mouseSpeedY = 0.0F;
|
||||||
|
InputManager.INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight);
|
||||||
|
} else if (isScreenInteractive(client.currentScreen) && MidnightControlsConfig.virtualMouse) {
|
||||||
|
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), 0, 0);
|
||||||
|
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
||||||
|
}
|
||||||
|
this.inventoryInteractionCooldown = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beginControlsInput(ControllerControlsWidget widget) {
|
||||||
|
this.controlsInput = widget;
|
||||||
|
if (widget != null) {
|
||||||
|
this.controlsInput.currentButtons.clear();
|
||||||
|
this.controlsInput.waiting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchButtonInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
|
||||||
|
var buffer = gamepadState.buttons();
|
||||||
|
for (int i = 0; i < buffer.limit(); i++) {
|
||||||
|
int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i;
|
||||||
|
boolean btnState = buffer.get() == (byte) 1;
|
||||||
|
var state = ButtonState.NONE;
|
||||||
|
var previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
|
||||||
|
|
||||||
|
if (btnState != previousState.isPressed()) {
|
||||||
|
state = btnState ? ButtonState.PRESS : ButtonState.RELEASE;
|
||||||
|
this.handleButton(client, btn, btnState ? 0 : 1, btnState);
|
||||||
|
if (btnState)
|
||||||
|
BUTTON_COOLDOWNS.put(btn, 5);
|
||||||
|
} else if (btnState) {
|
||||||
|
state = ButtonState.REPEAT;
|
||||||
|
if (BUTTON_COOLDOWNS.getOrDefault(btn, 0) == 0) {
|
||||||
|
BUTTON_COOLDOWNS.put(btn, 5);
|
||||||
|
this.handleButton(client, btn, 2, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
var buttons = new int[this.controlsInput.currentButtons.size()];
|
||||||
|
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
||||||
|
buttons[i] = this.controlsInput.currentButtons.get(i);
|
||||||
|
this.controlsInput.focusedBinding.setButton(buttons);
|
||||||
|
|
||||||
|
this.controlsInput.waiting = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.currentScreen != null && (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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == 1) {
|
||||||
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
|
||||||
|
if (this.actionGuiCooldown == 0) {
|
||||||
|
var focused = client.currentScreen.getFocused();
|
||||||
|
if (focused != null && isScreenInteractive(client.currentScreen)) {
|
||||||
|
if (this.handleAButton(client.currentScreen, focused)) {
|
||||||
|
this.actionGuiCooldown = 5; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
||||||
|
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(() -> {
|
||||||
|
((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(() -> {
|
||||||
|
((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.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);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to go back.
|
||||||
|
*
|
||||||
|
* @param screen the current screen
|
||||||
|
* @return true if successful, else false
|
||||||
|
*/
|
||||||
|
public boolean tryGoBack(@NotNull Screen screen) {
|
||||||
|
var set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
|
||||||
|
|
||||||
|
return screen.children().stream().filter(element -> element instanceof PressableWidget)
|
||||||
|
.map(element -> (PressableWidget) element)
|
||||||
|
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
|
||||||
|
.anyMatch(element -> {
|
||||||
|
if (element.getMessage().getContent() instanceof TranslatableTextContent translatableText) {
|
||||||
|
if (set.stream().anyMatch(key -> translatableText.getKey().equals(key))) {
|
||||||
|
element.onPress();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getDeadZoneValue(int axis) {
|
||||||
|
return (axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y) ? MidnightControlsConfig.leftDeadZone
|
||||||
|
: MidnightControlsConfig.rightDeadZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) {
|
||||||
|
int asButtonState = value > .5f ? 1 : (value < -.5f ? 2 : 0);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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 = 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);
|
||||||
|
|
||||||
|
if (currentPlusState != previousPlusState.isPressed()) {
|
||||||
|
InputManager.STATES.put(ButtonBinding.axisAsButton(axis, true), currentPlusState ? ButtonState.PRESS : ButtonState.RELEASE);
|
||||||
|
if (currentPlusState)
|
||||||
|
BUTTON_COOLDOWNS.put(ButtonBinding.axisAsButton(axis, true), 5);
|
||||||
|
} else if (currentPlusState) {
|
||||||
|
InputManager.STATES.put(ButtonBinding.axisAsButton(axis, true), ButtonState.REPEAT);
|
||||||
|
if (BUTTON_COOLDOWNS.getOrDefault(ButtonBinding.axisAsButton(axis, true), 0) == 0) {
|
||||||
|
BUTTON_COOLDOWNS.put(ButtonBinding.axisAsButton(axis, true), 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentMinusState != previousMinusState.isPressed()) {
|
||||||
|
InputManager.STATES.put(ButtonBinding.axisAsButton(axis, false), currentMinusState ? ButtonState.PRESS : ButtonState.RELEASE);
|
||||||
|
if (currentMinusState)
|
||||||
|
BUTTON_COOLDOWNS.put(ButtonBinding.axisAsButton(axis, false), 5);
|
||||||
|
} else if (currentMinusState) {
|
||||||
|
InputManager.STATES.put(ButtonBinding.axisAsButton(axis, false), ButtonState.REPEAT);
|
||||||
|
if (BUTTON_COOLDOWNS.getOrDefault(ButtonBinding.axisAsButton(axis, false), 0) == 0) {
|
||||||
|
BUTTON_COOLDOWNS.put(ButtonBinding.axisAsButton(axis, false), 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
InputManager.BUTTON_VALUES.put(ButtonBinding.axisAsButton(axis, true), axisValue);
|
||||||
|
else
|
||||||
|
InputManager.BUTTON_VALUES.put(ButtonBinding.axisAsButton(axis, true), 0.f);
|
||||||
|
if (currentMinusState)
|
||||||
|
InputManager.BUTTON_VALUES.put(ButtonBinding.axisAsButton(axis, false), axisValue);
|
||||||
|
else
|
||||||
|
InputManager.BUTTON_VALUES.put(ButtonBinding.axisAsButton(axis, false), 0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
double deadZone = this.getDeadZoneValue(axis);
|
||||||
|
|
||||||
|
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) {
|
||||||
|
if (asButtonState != 0 && !this.controlsInput.currentButtons.contains(ButtonBinding.axisAsButton(axis, asButtonState == 1))) {
|
||||||
|
|
||||||
|
this.controlsInput.currentButtons.add(ButtonBinding.axisAsButton(axis, asButtonState == 1));
|
||||||
|
|
||||||
|
int[] buttons = new int[this.controlsInput.currentButtons.size()];
|
||||||
|
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
|
||||||
|
buttons[i] = this.controlsInput.currentButtons.get(i);
|
||||||
|
this.controlsInput.focusedBinding.setButton(buttons);
|
||||||
|
|
||||||
|
this.controlsInput.waiting = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (client.currentScreen instanceof CreativeInventoryScreen creativeInventoryScreen) {
|
||||||
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||||
|
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
||||||
|
// @TODO allow rebinding to left stick
|
||||||
|
if (accessor.midnightcontrols$hasScrollbar() && absValue >= deadZone) {
|
||||||
|
creativeInventoryScreen.mouseScrolled(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, -(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, -(value * 1.5f));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (client.currentScreen instanceof AdvancementsScreen advancementsScreen) {
|
||||||
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X || axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
|
||||||
|
var accessor = (AdvancementsScreenAccessor) advancementsScreen;
|
||||||
|
if (absValue >= deadZone) {
|
||||||
|
AdvancementTab tab = accessor.getSelectedTab();
|
||||||
|
tab.move(axis == GLFW_GAMEPAD_AXIS_RIGHT_X ? -value * 5.0 : 0.0, axis == GLFW_GAMEPAD_AXIS_RIGHT_Y ? -value * 5.0 : 0.0);
|
||||||
|
}
|
||||||
|
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, -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, -finalValue);
|
||||||
|
return true;
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
client.currentScreen.mouseScrolled(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 = (float) MathHelper.clamp(absValue / MidnightControlsConfig.getAxisMaxValue(axis), 0.f, 1.f);
|
||||||
|
if (client.currentScreen == null) {
|
||||||
|
// Handles the look direction.
|
||||||
|
this.handleLook(client, axis, absValue, state);
|
||||||
|
} else {
|
||||||
|
boolean allowMouseControl = true;
|
||||||
|
|
||||||
|
if (this.actionGuiCooldown == 0 && MidnightControlsConfig.isMovementAxis(axis) && isScreenInteractive(client.currentScreen)) {
|
||||||
|
if (MidnightControlsConfig.isForwardButton(axis, false, asButtonState)) {
|
||||||
|
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.UP);
|
||||||
|
} else if (MidnightControlsConfig.isBackButton(axis, false, asButtonState)) {
|
||||||
|
allowMouseControl = this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
|
||||||
|
} else if (MidnightControlsConfig.isLeftButton(axis, false, asButtonState)) {
|
||||||
|
allowMouseControl = this.handleLeftRight(client.currentScreen, false);
|
||||||
|
} else if (MidnightControlsConfig.isRightButton(axis, false, asButtonState)) {
|
||||||
|
allowMouseControl = this.handleLeftRight(client.currentScreen, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float movementX = 0.f;
|
||||||
|
float movementY = 0.f;
|
||||||
|
|
||||||
|
if (MidnightControlsConfig.isBackButton(axis, false, (value > 0 ? 1 : 2))) {
|
||||||
|
movementY = absValue;
|
||||||
|
} else if (MidnightControlsConfig.isForwardButton(axis, false, (value > 0 ? 1 : 2))) {
|
||||||
|
movementY = -absValue;
|
||||||
|
} else if (MidnightControlsConfig.isLeftButton(axis, false, (value > 0 ? 1 : 2))) {
|
||||||
|
movementX = -absValue;
|
||||||
|
} else if (MidnightControlsConfig.isRightButton(axis, false, (value > 0 ? 1 : 2))) {
|
||||||
|
movementX = absValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.currentScreen != null && allowMouseControl) {
|
||||||
|
boolean moving = movementY != 0 || movementX != 0;
|
||||||
|
if (moving) {
|
||||||
|
/*
|
||||||
|
Updates the target mouse position when the initial movement stick movement is detected.
|
||||||
|
It prevents the cursor to jump to the old target mouse position if the user moves the cursor with the mouse.
|
||||||
|
*/
|
||||||
|
if (Math.abs(prevXAxis) < deadZone && Math.abs(prevYAxis) < deadZone) {
|
||||||
|
InputManager.INPUT_MANAGER.resetMouseTarget(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mouseSpeedX = movementX;
|
||||||
|
this.mouseSpeedY = movementY;
|
||||||
|
} else {
|
||||||
|
this.mouseSpeedX = 0.f;
|
||||||
|
this.mouseSpeedY = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(this.mouseSpeedX) >= .05f || Math.abs(this.mouseSpeedY) >= .05f) {
|
||||||
|
InputManager.queueMoveMousePosition(
|
||||||
|
this.mouseSpeedX * MidnightControlsConfig.mouseSpeed,
|
||||||
|
this.mouseSpeedY * MidnightControlsConfig.mouseSpeed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.moveMouseToClosestSlot(client, client.currentScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.prevXAxis = movementX;
|
||||||
|
this.prevYAxis = movementY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
|
||||||
|
if (focused instanceof PressableWidget widget) {
|
||||||
|
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
|
||||||
|
widget.onPress();
|
||||||
|
return true;
|
||||||
|
} else if (focused instanceof AbstractSprucePressableButtonWidget widget) {
|
||||||
|
widget.playDownSound();
|
||||||
|
widget.onPress();
|
||||||
|
return true;
|
||||||
|
} else if (focused instanceof SpruceLabelWidget labelWidget) {
|
||||||
|
labelWidget.onPress();
|
||||||
|
return true;
|
||||||
|
} else if (focused instanceof WorldListWidget list) {
|
||||||
|
list.getSelectedAsOptional().ifPresent(WorldListWidget.WorldEntry::play);
|
||||||
|
return true;
|
||||||
|
} else if (focused instanceof MultiplayerServerListWidget list) {
|
||||||
|
var entry = list.getSelectedOrNull();
|
||||||
|
if (entry instanceof MultiplayerServerListWidget.LanServerEntry || entry instanceof MultiplayerServerListWidget.ServerEntry) {
|
||||||
|
((MultiplayerScreen) screen).select(entry);
|
||||||
|
((MultiplayerScreen) screen).connect();
|
||||||
|
}
|
||||||
|
} else if (focused instanceof SpruceParentWidget) {
|
||||||
|
var childFocused = ((SpruceParentWidget<?>) focused).getFocused();
|
||||||
|
if (childFocused != null)
|
||||||
|
return this.handleAButton(screen, childFocused);
|
||||||
|
} else if (focused instanceof ParentElement widget) {
|
||||||
|
var childFocused = widget.getFocused();
|
||||||
|
if (childFocused != null)
|
||||||
|
return this.handleAButton(screen, childFocused);
|
||||||
|
} else if (FabricLoader.getInstance().isModLoaded("yet-another-config-lib") && YACLCompat.handleAButton(screen, focused)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else pressKeyboardKey(screen, GLFW_KEY_ENTER);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the left and right buttons.
|
||||||
|
*
|
||||||
|
* @param screen the current screen
|
||||||
|
* @param right true if the right button is pressed, else false
|
||||||
|
*/
|
||||||
|
private boolean handleLeftRight(@NotNull Screen screen, boolean right) {
|
||||||
|
if (screen instanceof SpruceScreen spruceScreen) {
|
||||||
|
spruceScreen.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
||||||
|
this.actionGuiCooldown = 5;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (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))
|
||||||
|
return this.changeFocus(screen, right ? NavigationDirection.RIGHT : NavigationDirection.LEFT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleRightLeftElement(@NotNull Element element, boolean right) {
|
||||||
|
if (element instanceof SpruceElement spruceElement) {
|
||||||
|
if (spruceElement.requiresCursor())
|
||||||
|
return true;
|
||||||
|
return !spruceElement.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
|
||||||
|
}
|
||||||
|
if (element instanceof SliderWidget slider) {
|
||||||
|
if (slider.active) {
|
||||||
|
slider.keyPressed(right ? 262 : 263, 0, 0);
|
||||||
|
this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (element instanceof AlwaysSelectedEntryListWidget) {
|
||||||
|
//TODO((EntryListWidgetAccessor) element).midnightcontrols$moveSelection(right ? EntryListWidget.MoveDirection.DOWN : EntryListWidget.MoveDirection.UP);
|
||||||
|
return false;
|
||||||
|
} else if (element instanceof ParentElement entryList) {
|
||||||
|
var focused = entryList.getFocused();
|
||||||
|
if (focused == null)
|
||||||
|
return true;
|
||||||
|
return this.handleRightLeftElement(focused, right);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private double prevX = 0;
|
||||||
|
private double prevY = 0;
|
||||||
|
private double xValue;
|
||||||
|
private int xState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the look direction input.
|
||||||
|
*
|
||||||
|
* @param client the client instance
|
||||||
|
* @param axis the axis to change
|
||||||
|
* @param value the value of the look
|
||||||
|
* @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 (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.yAxisRotationSpeed * powValue) * 0.11D;
|
||||||
|
} else if (state == 1) {
|
||||||
|
this.targetPitch = MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powValue) * 0.11D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
|
||||||
|
if (state == 2) {
|
||||||
|
this.targetYaw = -MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
|
||||||
|
} else if (state == 1) {
|
||||||
|
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 (!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;
|
||||||
|
}
|
||||||
|
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 HandledScreen || MidnightControlsConfig.joystickAsMouse || MidnightControlsConfig.mouseScreens.stream().anyMatch(a -> screen.getClass().toString().contains(a))
|
||||||
|
|| (screen instanceof SpruceScreen && ((SpruceScreen) screen).requiresCursor())
|
||||||
|
|| MidnightControlsCompat.requireMouseOnScreen(screen));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
|
||||||
|
private void moveMouseToClosestSlot(@NotNull MinecraftClient client, @Nullable Screen screen) {
|
||||||
|
// Makes the mouse attracted to slots. This helps with selecting items when using a controller.
|
||||||
|
if (screen instanceof HandledScreen inventoryScreen) {
|
||||||
|
var accessor = (HandledScreenAccessor) inventoryScreen;
|
||||||
|
int guiLeft = accessor.getX();
|
||||||
|
int guiTop = accessor.getY();
|
||||||
|
int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
||||||
|
int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
|
||||||
|
|
||||||
|
// Finds the closest slot in the GUI within 14 pixels.
|
||||||
|
Optional<Pair<Slot, Double>> closestSlot = inventoryScreen.getScreenHandler().slots.parallelStream()
|
||||||
|
.map(slot -> {
|
||||||
|
int x = guiLeft + slot.x + 8;
|
||||||
|
int y = guiTop + slot.y + 8;
|
||||||
|
|
||||||
|
// Distance between the slot and the cursor.
|
||||||
|
double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2));
|
||||||
|
return Pair.of(slot, distance);
|
||||||
|
}).filter(entry -> entry.value <= 14.0)
|
||||||
|
.min(Comparator.comparingDouble(p -> p.value));
|
||||||
|
|
||||||
|
if (closestSlot.isPresent()) {
|
||||||
|
var slot = closestSlot.get().key;
|
||||||
|
if (slot.hasStack() || !client.player.getInventory().getMainHandStack().isEmpty()) {
|
||||||
|
int slotCenterXScaled = guiLeft + slot.x + 8;
|
||||||
|
int slotCenterYScaled = guiTop + slot.y + 8;
|
||||||
|
int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
|
||||||
|
int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()));
|
||||||
|
double deltaX = slotCenterX - targetMouseX;
|
||||||
|
double deltaY = slotCenterY - targetMouseY;
|
||||||
|
|
||||||
|
if (mouseX != slotCenterXScaled || mouseY != slotCenterYScaled) {
|
||||||
|
this.targetMouseX += deltaX * 0.75;
|
||||||
|
this.targetMouseY += deltaY * 0.75;
|
||||||
|
} else {
|
||||||
|
this.mouseSpeedX *= 0.3F;
|
||||||
|
this.mouseSpeedY *= 0.3F;
|
||||||
|
}
|
||||||
|
this.mouseSpeedX *= .75F;
|
||||||
|
this.mouseSpeedY *= .75F;
|
||||||
|
} else {
|
||||||
|
this.mouseSpeedX *= .1F;
|
||||||
|
this.mouseSpeedY *= .1F;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.mouseSpeedX *= .3F;
|
||||||
|
this.mouseSpeedY *= .3F;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.mouseSpeedX = 0.F;
|
||||||
|
this.mouseSpeedY = 0.F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,6 @@ import net.minecraft.block.BlockState;
|
|||||||
import net.minecraft.block.FluidBlock;
|
import net.minecraft.block.FluidBlock;
|
||||||
import net.minecraft.block.SlabBlock;
|
import net.minecraft.block.SlabBlock;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.entity.attribute.EntityAttributes;
|
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
@@ -28,8 +27,6 @@ import net.minecraft.world.RaycastContext;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the reach-around API of midnightcontrols.
|
* Represents the reach-around API of midnightcontrols.
|
||||||
*
|
*
|
||||||
@@ -41,10 +38,10 @@ public class MidnightReacharound {
|
|||||||
private boolean lastReacharoundVertical = false;
|
private boolean lastReacharoundVertical = false;
|
||||||
private boolean onSlab = false;
|
private boolean onSlab = false;
|
||||||
|
|
||||||
public void tick() {
|
public void tick(@NotNull MinecraftClient client) {
|
||||||
this.lastReacharoundResult = this.tryVerticalReachAround();
|
this.lastReacharoundResult = this.tryVerticalReachAround(client);
|
||||||
if (this.lastReacharoundResult == null) {
|
if (this.lastReacharoundResult == null) {
|
||||||
this.lastReacharoundResult = this.tryHorizontalReachAround();
|
this.lastReacharoundResult = this.tryHorizontalReachAround(client);
|
||||||
this.lastReacharoundVertical = false;
|
this.lastReacharoundVertical = false;
|
||||||
} else this.lastReacharoundVertical = true;
|
} else this.lastReacharoundVertical = true;
|
||||||
}
|
}
|
||||||
@@ -77,15 +74,16 @@ public class MidnightReacharound {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static float getPlayerRange(@NotNull MinecraftClient client) {
|
public static float getPlayerRange(@NotNull MinecraftClient client) {
|
||||||
return client.player != null ? Double.valueOf(client.player.getAttributeValue(EntityAttributes.BLOCK_INTERACTION_RANGE)).floatValue() : 0.f;
|
return client.interactionManager != null ? client.interactionManager.getReachDistance() : 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a nullable block hit result if vertical reach-around is possible.
|
* Returns a nullable block hit result if vertical reach-around is possible.
|
||||||
*
|
*
|
||||||
|
* @param client the client instance
|
||||||
* @return a block hit result if vertical reach-around is possible, else {@code null}
|
* @return a block hit result if vertical reach-around is possible, else {@code null}
|
||||||
*/
|
*/
|
||||||
public @Nullable BlockHitResult tryVerticalReachAround() {
|
public @Nullable BlockHitResult tryVerticalReachAround(@NotNull MinecraftClient client) {
|
||||||
if (!MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable())
|
if (!MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable())
|
||||||
return null;
|
return null;
|
||||||
if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.MISS
|
if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.MISS
|
||||||
@@ -114,13 +112,14 @@ public class MidnightReacharound {
|
|||||||
/**
|
/**
|
||||||
* Returns a nullable block hit result if horizontal reach-around is possible.
|
* Returns a nullable block hit result if horizontal reach-around is possible.
|
||||||
*
|
*
|
||||||
|
* @param client the client instance
|
||||||
* @return a block hit result if horizontal reach-around is possible
|
* @return a block hit result if horizontal reach-around is possible
|
||||||
*/
|
*/
|
||||||
public @Nullable BlockHitResult tryHorizontalReachAround() {
|
public @Nullable BlockHitResult tryHorizontalReachAround(@NotNull MinecraftClient client) {
|
||||||
if (!MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable())
|
if (!MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (client.world != null && client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS
|
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())
|
if (client.player.isRiding())
|
||||||
return null;
|
return null;
|
||||||
@@ -9,7 +9,14 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import me.juancarloscp52.bedrockify.client.BedrockifyClient;
|
import me.juancarloscp52.bedrockify.client.BedrockifyClient;
|
||||||
|
import me.juancarloscp52.bedrockify.client.BedrockifyClientSettings;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents HQM compatibility handler.
|
* Represents HQM compatibility handler.
|
||||||
@@ -21,7 +28,7 @@ import me.juancarloscp52.bedrockify.client.BedrockifyClient;
|
|||||||
public class BedrockifyCompat implements CompatHandler {
|
public class BedrockifyCompat implements CompatHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle() {
|
public void handle(@NotNull MidnightControlsClient mod) {
|
||||||
BedrockifyClient.getInstance().settings.disableFlyingMomentum = false;
|
BedrockifyClient.getInstance().settings.disableFlyingMomentum = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
@@ -27,20 +26,12 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public interface CompatHandler {
|
public interface CompatHandler {
|
||||||
/**
|
|
||||||
* Handles compatibility of a mod.
|
|
||||||
*/
|
|
||||||
default void handle() {
|
|
||||||
handle(MidnightControlsClient.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles compatibility of a mod.
|
* Handles compatibility of a mod.
|
||||||
*
|
*
|
||||||
* @param mod this mod instance
|
* @param mod this mod instance
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
void handle(@NotNull MidnightControlsClient mod);
|
||||||
default void handle(@NotNull MidnightControlsClient mod) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles custom camera updates
|
* Handles custom camera updates
|
||||||
@@ -49,32 +40,6 @@ public interface CompatHandler {
|
|||||||
*/
|
*/
|
||||||
default void handleCamera(@NotNull MinecraftClient client, double targetYaw, double targetPitch) {};
|
default void handleCamera(@NotNull MinecraftClient client, double targetYaw, double targetPitch) {};
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles movement for players as well as vehicles
|
|
||||||
*
|
|
||||||
* @param storage the storage containing info about the current axis
|
|
||||||
* @param adjustedValue the value of the axis, adjusted for max values and non-analogue movement, recommended for player movement
|
|
||||||
*/
|
|
||||||
default void handleMovement(@NotNull MinecraftClient client, AxisStorage storage, float adjustedValue) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles custom tab behavior
|
|
||||||
*
|
|
||||||
* @param forward whether the direction is forward or backward
|
|
||||||
*/
|
|
||||||
default boolean handleTabs(Screen screen, boolean forward) {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles custom page behavior
|
|
||||||
*
|
|
||||||
* @param forward whether the direction is forward or backward
|
|
||||||
*/
|
|
||||||
default boolean handlePages(Screen screen, boolean forward) {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the mouse is required on the specified screen.
|
* Returns whether the mouse is required on the specified screen.
|
||||||
*
|
*
|
||||||
@@ -7,35 +7,35 @@ import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
|||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import org.aperlambda.lambdacommon.Identifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|
||||||
|
|
||||||
public class EMICompat implements CompatHandler {
|
public class EMICompat implements CompatHandler {
|
||||||
public static boolean handleEmiPages(boolean direction) {
|
public static boolean handleTabs(boolean direction) {
|
||||||
if (isEMIEnabled() && MidnightControlsClient.input.actionGuiCooldown == 0 && EmiScreenManager.getSearchPanel() != null && EmiScreenManager.getSearchPanel().pageLeft != null && EmiScreenManager.getSearchPanel().pageRight != null) {
|
if (isEMIEnabled() && MidnightControlsClient.get().input.actionGuiCooldown == 0 && EmiScreenManager.getSearchPanel() != null && EmiScreenManager.getSearchPanel().pageLeft != null && EmiScreenManager.getSearchPanel().pageRight != null) {
|
||||||
if (direction) EmiScreenManager.getSearchPanel().pageRight.onPress();
|
if (direction) EmiScreenManager.getSearchPanel().pageRight.onPress();
|
||||||
else EmiScreenManager.getSearchPanel().pageLeft.onPress();
|
else EmiScreenManager.getSearchPanel().pageLeft.onPress();
|
||||||
MidnightControlsClient.input.actionGuiCooldown = 5;
|
MidnightControlsClient.get().input.actionGuiCooldown = 5;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void handle() {
|
public void handle(@NotNull MidnightControlsClient mod) {
|
||||||
ButtonCategory category = new ButtonCategory(id("category.emi"));
|
ButtonCategory category = new ButtonCategory(new Identifier("midnightcontrols","category.emi"));
|
||||||
InputManager.registerCategory(category);
|
InputManager.registerCategory(category);
|
||||||
new ButtonBinding.Builder("emi_page_left")
|
new ButtonBinding.Builder("emi_page_left")
|
||||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||||
.category(category)
|
.category(category)
|
||||||
.action((client,action,value,buttonState)->handleEmiPages(false)).cooldown()
|
.action((client,action,value,buttonState)->handleTabs(false)).cooldown()
|
||||||
.filter(((buttonBinding) -> EmiApi.getHandledScreen() != null))
|
.filter(((client, buttonBinding) -> EmiApi.getHandledScreen() != null))
|
||||||
.register();
|
.register();
|
||||||
new ButtonBinding.Builder("emi_page_right")
|
new ButtonBinding.Builder("emi_page_right")
|
||||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||||
.category(category)
|
.category(category)
|
||||||
.action((client,action,value,buttonState)->handleEmiPages(true)).cooldown()
|
.action((client,action,value,buttonState)->handleTabs(true)).cooldown()
|
||||||
.filter(((buttonBinding) -> EmiApi.getHandledScreen() != null))
|
.filter(((client, buttonBinding) -> EmiApi.getHandledScreen() != null))
|
||||||
.register();
|
.register();
|
||||||
}
|
}
|
||||||
public static boolean isEMIEnabled() {
|
public static boolean isEMIEnabled() {
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
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 net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,8 +9,10 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -28,7 +30,7 @@ public class HQMCompat implements CompatHandler {
|
|||||||
private Optional<Class<?>> guiBaseClass;
|
private Optional<Class<?>> guiBaseClass;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle() {
|
public void handle(@NotNull MidnightControlsClient mod) {
|
||||||
this.guiBaseClass = LambdaReflection.getClass(GUI_BASE_CLASS_PATH);
|
this.guiBaseClass = LambdaReflection.getClass(GUI_BASE_CLASS_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5,39 +5,29 @@ import net.minecraft.client.gui.screen.Screen;
|
|||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
|
||||||
public class InventoryTabsCompat implements CompatHandler {
|
public class InventoryTabsCompat {
|
||||||
@Override
|
|
||||||
public boolean handleTabs(Screen screen, boolean next) {
|
public static void handleInventoryTabs(Screen screen, boolean next) {
|
||||||
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
||||||
TabManager tabManager = TabManager.getInstance();
|
TabManager tabManager = TabManager.getInstance();
|
||||||
int tabIndex = tabManager.tabs.indexOf(tabManager.currentTab);
|
int tabIndex = tabManager.tabs.indexOf(tabManager.currentTab);
|
||||||
if (next) {
|
if (next) {
|
||||||
if (tabIndex < tabManager.tabs.size() - 1) tabManager.onTabClick(tabManager.tabs.get(tabIndex + 1));
|
if (tabIndex < tabManager.tabs.size() - 1) tabManager.onTabClick(tabManager.tabs.get(tabIndex + 1));
|
||||||
else tabManager.onTabClick(tabManager.tabs.getFirst());
|
else tabManager.onTabClick(tabManager.tabs.get(0));
|
||||||
} else {
|
} else {
|
||||||
if (tabIndex > 0) tabManager.onTabClick(tabManager.tabs.get(tabIndex - 1));
|
if (tabIndex > 0) tabManager.onTabClick(tabManager.tabs.get(tabIndex - 1));
|
||||||
else tabManager.onTabClick(tabManager.tabs.getLast());
|
else tabManager.onTabClick(tabManager.tabs.get(tabManager.tabs.size() - 1));
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
@Override
|
public static void handleInventoryPage(Screen screen, boolean next) {
|
||||||
public boolean handlePages(Screen screen, boolean next) {
|
|
||||||
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
|
||||||
TabManager tabManager = TabManager.getInstance();
|
TabManager tabManager = TabManager.getInstance();
|
||||||
if (next) {
|
if (next) {
|
||||||
if (tabManager.canGoForwardAPage()) {
|
if (tabManager.canGoForwardAPage()) tabManager.setCurrentPage(tabManager.currentPage + 1);
|
||||||
tabManager.setCurrentPage(tabManager.currentPage + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (tabManager.canGoBackAPage()) {
|
if (tabManager.canGoBackAPage()) tabManager.setCurrentPage(tabManager.currentPage - 1);
|
||||||
tabManager.setCurrentPage(tabManager.currentPage - 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
@@ -23,49 +23,41 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.log;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a compatibility handler.
|
* Represents a compatibility handler.
|
||||||
*
|
*
|
||||||
* @author LambdAurora, Motschen
|
* @author LambdAurora
|
||||||
* @version 1.10.0
|
* @version 1.5.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class MidnightControlsCompat {
|
public class MidnightControlsCompat {
|
||||||
@Deprecated // INTERNAL -> PLEASE USE streamCompatHandlers() INSTEAD
|
|
||||||
public static final List<CompatHandler> HANDLERS = new ArrayList<>();
|
public static final List<CompatHandler> HANDLERS = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes compatibility with other mods if needed.
|
* Initializes compatibility with other mods if needed.
|
||||||
|
*
|
||||||
|
* @param mod the mod instance
|
||||||
*/
|
*/
|
||||||
public static void init() {
|
public static void init(@NotNull MidnightControlsClient mod) {
|
||||||
if (PlatformFunctions.isModLoaded("emi")) {
|
// "okzoomer" is the mod ID used by Fabric-compatible versions of Ok Zoomer. (5.0.0-beta.6 and below.)
|
||||||
log("Adding EMI compatibility...");
|
// "ok_zoomer" is the mod ID used by Quilt-exclusive versions of Ok Zoomer. (5.0.0-beta.7 and above.)
|
||||||
registerCompatHandler(new EMICompat());
|
if (FabricLoader.getInstance().isModLoaded("okzoomer") || FabricLoader.getInstance().isModLoaded("ok_zoomer")) {
|
||||||
|
mod.log("Adding Ok Zoomer compatibility...");
|
||||||
|
HANDLERS.add(new OkZoomerCompat());
|
||||||
}
|
}
|
||||||
if (PlatformFunctions.isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
|
if (isEMIPresent()) {
|
||||||
log("Adding HQM compatibility...");
|
mod.log("Adding EMI compatibility...");
|
||||||
registerCompatHandler(new HQMCompat());
|
HANDLERS.add(new EMICompat());
|
||||||
}
|
}
|
||||||
if (PlatformFunctions.isModLoaded("bedrockify")) {
|
if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
|
||||||
log("Adding Bedrockify compatibility...");
|
mod.log("Adding HQM compatibility...");
|
||||||
registerCompatHandler(new BedrockifyCompat());
|
HANDLERS.add(new HQMCompat());
|
||||||
}
|
}
|
||||||
if (PlatformFunctions.isModLoaded("yet-another-config-lib")) {
|
if (FabricLoader.getInstance().isModLoaded("bedrockify")) {
|
||||||
log("Adding YACL compatibility...");
|
mod.log("Adding Bedrockify compatibility...");
|
||||||
registerCompatHandler(new YACLCompat());
|
HANDLERS.add(new BedrockifyCompat());
|
||||||
}
|
}
|
||||||
if (PlatformFunctions.isModLoaded("sodium")) {
|
HANDLERS.forEach(handler -> handler.handle(mod));
|
||||||
log("Adding Sodium compatibility...");
|
|
||||||
registerCompatHandler(new SodiumCompat());
|
|
||||||
}
|
|
||||||
if (PlatformFunctions.isModLoaded("inventorytabs")) {
|
|
||||||
log("Adding Inventory Tabs compatibility...");
|
|
||||||
registerCompatHandler(new InventoryTabsCompat());
|
|
||||||
}
|
|
||||||
HANDLERS.forEach(CompatHandler::handle);
|
|
||||||
InputManager.loadButtonBindings();
|
InputManager.loadButtonBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,25 +86,7 @@ public class MidnightControlsCompat {
|
|||||||
* @return true if the mouse is requried on the specified screen, else false
|
* @return true if the mouse is requried on the specified screen, else false
|
||||||
*/
|
*/
|
||||||
public static boolean requireMouseOnScreen(Screen screen) {
|
public static boolean requireMouseOnScreen(Screen screen) {
|
||||||
return streamCompatHandlers().anyMatch(handler -> handler.requireMouseOnScreen(screen));
|
return HANDLERS.stream().anyMatch(handler -> handler.requireMouseOnScreen(screen));
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Handles custom tabs for modded screens
|
|
||||||
*
|
|
||||||
* @param screen the screen
|
|
||||||
* @return true if the handle was fired and succeed, else false
|
|
||||||
*/
|
|
||||||
public static boolean handleTabs(Screen screen, boolean forward) {
|
|
||||||
return streamCompatHandlers().anyMatch(handler -> handler.handleTabs(screen, forward));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Handles custom pages for modded screens
|
|
||||||
*
|
|
||||||
* @param screen the screen
|
|
||||||
* @return true if the handle was fired and succeed, else false
|
|
||||||
*/
|
|
||||||
public static boolean handlePages(Screen screen, boolean forward) {
|
|
||||||
return streamCompatHandlers().anyMatch(handler -> handler.handlePages(screen, forward));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,22 +154,37 @@ public class MidnightControlsCompat {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the camera movement.
|
* Returns whether Roughly Enough Items is present.
|
||||||
*
|
*
|
||||||
* @param targetYaw the target yaw
|
* @return true if Roughly Enough Items is present, else false
|
||||||
* @param targetPitch the target pitch
|
|
||||||
*/
|
*/
|
||||||
public static void handleCamera(double targetYaw, double targetPitch) {
|
public static boolean isReiPresent() {
|
||||||
MidnightControlsCompat.HANDLERS.forEach(handler -> handler.handleCamera(client, targetYaw, targetPitch));
|
return FabricLoader.getInstance().isModLoaded("roughlyenoughitems");
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Handles movement for players as well as vehicles
|
* Returns whether EMI is present.
|
||||||
*
|
*
|
||||||
* @param storage the storage containing info about the current axis
|
* @return true if EMI is present, else false
|
||||||
* @param adjustedValue the value of the axis, adjusted for max values and non-analogue movement, recommended for player movement
|
|
||||||
*/
|
*/
|
||||||
public static void handleMovement(AxisStorage storage, float adjustedValue) {
|
public static boolean isEMIPresent() {
|
||||||
streamCompatHandlers().forEach(handler -> handler.handleMovement(client, storage, adjustedValue));
|
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,27 +9,36 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
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.objectweb.asm.tree.ClassNode;
|
||||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This plugin is only present for the conditional mixins.
|
* This plugin is only present for the conditional mixins.
|
||||||
*
|
*
|
||||||
* @author LambdAurora & Motschen
|
* @author LambdAurora
|
||||||
* @version 1.6.0
|
* @version 1.5.0
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
||||||
private String mixinPackage;
|
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>();
|
||||||
|
|
||||||
|
public MidnightControlsMixinPlugin() {
|
||||||
|
//this.putConditionalMixin("SodiumOptionsGUIAccessor", FabricLoader.getInstance().isModLoaded("sodium"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putConditionalMixin(@NotNull String path, boolean condition) {
|
||||||
|
this.conditionalMixins.put("eu.midnightdust.midnightcontrols.client.compat.mixin." + path, condition);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad(String mixinPackage) {
|
public void onLoad(String mixinPackage) {
|
||||||
this.mixinPackage = mixinPackage + ".";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -39,13 +48,7 @@ public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||||
final String mixinName = mixinClassName.substring(this.mixinPackage.length());
|
return this.conditionalMixins.getOrDefault(mixinClassName, Boolean.TRUE);
|
||||||
final String packageName = mixinName.substring(0, mixinName.lastIndexOf('.'));
|
|
||||||
|
|
||||||
if (packageName.startsWith("sodium") && !PlatformFunctions.isModLoaded("sodium"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021-2022 Karen/あけみ <karen@akemi.ai>, LambdAurora <aurora42lambda@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of MidnightControls.
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license. For more information,
|
||||||
|
* see the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
|
import net.minecraft.client.option.KeyBinding;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a compatibility handler for Ok Zoomer.
|
||||||
|
*
|
||||||
|
* @author Karen/あけみ, LambdAurora
|
||||||
|
* @version 1.4.3
|
||||||
|
* @since 1.1.0
|
||||||
|
*/
|
||||||
|
public class OkZoomerCompat implements CompatHandler {
|
||||||
|
private boolean didAllReflectionCallsSucceed = false;
|
||||||
|
|
||||||
|
private KeyBinding okZoomerZoomKey;
|
||||||
|
private KeyBinding okZoomerIncreaseZoomKey;
|
||||||
|
private KeyBinding okZoomerDecreaseZoomKey;
|
||||||
|
private KeyBinding okZoomerResetZoomKey;
|
||||||
|
|
||||||
|
private Method okZoomerAreExtraKeyBindsEnabledMethod;
|
||||||
|
|
||||||
|
public OkZoomerCompat() {
|
||||||
|
// These strings represent the names of the classes, fields, and methods we use from the Ok Zoomer API
|
||||||
|
String okZoomerZoomKeybindsClassString;
|
||||||
|
|
||||||
|
String okZoomerZoomKeyFieldString;
|
||||||
|
String okZoomerIncreaseZoomKeyFieldString;
|
||||||
|
String okZoomerDecreaseZoomKeyFieldString;
|
||||||
|
String okZoomerResetZoomKeyFieldString;
|
||||||
|
|
||||||
|
String okZoomerAreExtraKeyBindsEnabledMethodNameString;
|
||||||
|
|
||||||
|
// These variables represent the actual objects that we reflect to
|
||||||
|
Class<?> okZoomerZoomKeybindsClass;
|
||||||
|
|
||||||
|
Field okZoomerZoomKeyField;
|
||||||
|
Field okZoomerIncreaseZoomKeyField;
|
||||||
|
Field okZoomerDecreaseZoomKeyField;
|
||||||
|
Field okZoomerResetZoomKeyField;
|
||||||
|
|
||||||
|
// First, we need to determine which version of the Ok Zoomer API we're dealing with here.
|
||||||
|
if (LambdaReflection.doesClassExist("io.github.ennuil.okzoomer.keybinds.ZoomKeybinds")) {
|
||||||
|
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.3+1.17.1/src/main/java/io/github/ennuil/okzoomer/keybinds/ZoomKeybinds.java
|
||||||
|
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.3 or below detected!");
|
||||||
|
|
||||||
|
okZoomerZoomKeybindsClassString = "io.github.ennuil.okzoomer.keybinds.ZoomKeybinds";
|
||||||
|
|
||||||
|
okZoomerZoomKeyFieldString = "zoomKey";
|
||||||
|
okZoomerIncreaseZoomKeyFieldString = "increaseZoomKey";
|
||||||
|
okZoomerDecreaseZoomKeyFieldString = "decreaseZoomKey";
|
||||||
|
okZoomerResetZoomKeyFieldString = "resetZoomKey";
|
||||||
|
|
||||||
|
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeybindsEnabled";
|
||||||
|
} else if (LambdaReflection.doesClassExist("io.github.ennuil.okzoomer.key_binds.ZoomKeyBinds")) {
|
||||||
|
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.6+1.18.2/src/main/java/io/github/ennuil/okzoomer/key_binds/ZoomKeyBinds.java
|
||||||
|
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.6, 5.0.0-beta.5, or 5.0.0-beta.4 detected!");
|
||||||
|
|
||||||
|
okZoomerZoomKeybindsClassString = "io.github.ennuil.okzoomer.key_binds.ZoomKeyBinds";
|
||||||
|
|
||||||
|
okZoomerZoomKeyFieldString = "ZOOM_KEY";
|
||||||
|
okZoomerIncreaseZoomKeyFieldString = "INCREASE_ZOOM_KEY";
|
||||||
|
okZoomerDecreaseZoomKeyFieldString = "DECREASE_ZOOM_KEY";
|
||||||
|
okZoomerResetZoomKeyFieldString = "RESET_ZOOM_KEY";
|
||||||
|
|
||||||
|
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeyBindsEnabled";
|
||||||
|
} else if (LambdaReflection.doesClassExist("io.github.ennuil.ok_zoomer.key_binds.ZoomKeyBinds")) {
|
||||||
|
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.7+1.18.2/src/main/java/io/github/ennuil/ok_zoomer/key_binds/ZoomKeyBinds.java
|
||||||
|
MidnightControlsClient.get().log("Ok Zoomer version 5.0.0-beta.7 (Quilt) or above detected!");
|
||||||
|
|
||||||
|
okZoomerZoomKeybindsClassString = "io.github.ennuil.ok_zoomer.key_binds.ZoomKeyBinds";
|
||||||
|
|
||||||
|
okZoomerZoomKeyFieldString = "ZOOM_KEY";
|
||||||
|
okZoomerIncreaseZoomKeyFieldString = "INCREASE_ZOOM_KEY";
|
||||||
|
okZoomerDecreaseZoomKeyFieldString = "DECREASE_ZOOM_KEY";
|
||||||
|
okZoomerResetZoomKeyFieldString = "RESET_ZOOM_KEY";
|
||||||
|
|
||||||
|
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeyBindsEnabled";
|
||||||
|
} else {
|
||||||
|
// If all of the above checks fail, then the version of the Ok Zoomer API that the user is trying to use is too new.
|
||||||
|
MidnightControlsClient.get().warn("The version of Ok Zoomer that you are currently using is too new, and is not yet supported by MidnightControls!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflect to the ZoomKeyBinds (>= 5.0.0-beta.4) / ZoomKeybinds (<= 5.0.0-beta.3) class.
|
||||||
|
try {
|
||||||
|
okZoomerZoomKeybindsClass = Class.forName(okZoomerZoomKeybindsClassString);
|
||||||
|
} catch (ClassNotFoundException exception) {
|
||||||
|
// This theoretically should never happen.
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybinds class!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflect to all of the keybind fields.
|
||||||
|
try {
|
||||||
|
okZoomerZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerZoomKeyFieldString);
|
||||||
|
okZoomerIncreaseZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerIncreaseZoomKeyFieldString);
|
||||||
|
okZoomerDecreaseZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerDecreaseZoomKeyFieldString);
|
||||||
|
okZoomerResetZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerResetZoomKeyFieldString);
|
||||||
|
} catch (NoSuchFieldException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybind fields!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise KeyBinding objects
|
||||||
|
try {
|
||||||
|
okZoomerZoomKey = (KeyBinding) okZoomerZoomKeyField.get(null);
|
||||||
|
okZoomerIncreaseZoomKey = (KeyBinding) okZoomerIncreaseZoomKeyField.get(null);
|
||||||
|
okZoomerDecreaseZoomKey = (KeyBinding) okZoomerDecreaseZoomKeyField.get(null);
|
||||||
|
okZoomerResetZoomKey = (KeyBinding) okZoomerResetZoomKeyField.get(null);
|
||||||
|
} catch (IllegalAccessException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls failed to reflect to the Ok Zoomer keybind objects!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflect to the areExtraKeyBindsEnabled (>= 5.0.0-beta.4) / areExtraKeybindsEnabled (<= 5.0.0-beta.3) method.
|
||||||
|
// TODO: Consider replacing this entirely with getExtraKeyBind (>= 5.0.0-beta.4) / getExtraKeybind (<= 5.0.0-beta.3) in the future.
|
||||||
|
try {
|
||||||
|
okZoomerAreExtraKeyBindsEnabledMethod = okZoomerZoomKeybindsClass.getDeclaredMethod(okZoomerAreExtraKeyBindsEnabledMethodNameString);
|
||||||
|
} catch (NoSuchMethodException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls failed to reflect to an Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
didAllReflectionCallsSucceed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(@NotNull MidnightControlsClient mod) {
|
||||||
|
if (didAllReflectionCallsSucceed) {
|
||||||
|
new ButtonBinding.Builder("zoom")
|
||||||
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
|
||||||
|
.onlyInGame()
|
||||||
|
.cooldown(true)
|
||||||
|
.category(ButtonBinding.MISC_CATEGORY)
|
||||||
|
.linkKeybind(okZoomerZoomKey)
|
||||||
|
.register();
|
||||||
|
|
||||||
|
boolean okZoomerAreExtraKeyBindsEnabled = false;
|
||||||
|
try {
|
||||||
|
okZoomerAreExtraKeyBindsEnabled = (boolean) okZoomerAreExtraKeyBindsEnabledMethod.invoke(null);
|
||||||
|
} catch (IllegalAccessException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls encountered an IllegalAccessException while attempting to invoke a reflected Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
} catch (InvocationTargetException exception) {
|
||||||
|
MidnightControlsClient.get().warn("MidnightControls encountered an InvocationTargetException while attempting to invoke a reflected Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (okZoomerAreExtraKeyBindsEnabled) {
|
||||||
|
new ButtonBinding.Builder("zoom_in")
|
||||||
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||||
|
.onlyInGame()
|
||||||
|
.cooldown(true)
|
||||||
|
.category(ButtonBinding.MISC_CATEGORY)
|
||||||
|
.linkKeybind(okZoomerIncreaseZoomKey)
|
||||||
|
.register();
|
||||||
|
new ButtonBinding.Builder("zoom_out")
|
||||||
|
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||||
|
.onlyInGame()
|
||||||
|
.cooldown(true)
|
||||||
|
.category(ButtonBinding.MISC_CATEGORY)
|
||||||
|
.linkKeybind(okZoomerDecreaseZoomKey)
|
||||||
|
.register();
|
||||||
|
new ButtonBinding.Builder("zoom_reset")
|
||||||
|
.onlyInGame()
|
||||||
|
.cooldown(true)
|
||||||
|
.category(ButtonBinding.MISC_CATEGORY)
|
||||||
|
.linkKeybind(okZoomerResetZoomKey)
|
||||||
|
.register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.compat;
|
package eu.midnightdust.midnightcontrols.client.compat;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.mixin.sodium.SodiumOptionsGUIAccessor;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.compat.mixin.SodiumOptionsGUIAccessor;
|
||||||
|
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
|
||||||
public class SodiumCompat implements CompatHandler {
|
public class SodiumCompat {
|
||||||
@Override
|
public static void handleTabs(Screen screen, boolean direction) {
|
||||||
public boolean handleTabs(Screen screen, boolean direction) {
|
|
||||||
if (screen instanceof SodiumOptionsGUI optionsGUI) {
|
if (screen instanceof SodiumOptionsGUI optionsGUI) {
|
||||||
SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI;
|
SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI;
|
||||||
final int max = accessor.getPages().size()-1;
|
final int max = accessor.getPages().size()-1;
|
||||||
int i = accessor.getPages().indexOf(accessor.getCurrentPage());
|
int i = accessor.getPages().indexOf(accessor.getCurrentPage());
|
||||||
i = (direction ? ((max > i) ? ++i : 0) : (i > 0 ? --i : max));
|
i = (direction ? ((max > i) ? ++i : 0) : (i > 0 ? --i : max));
|
||||||
|
if (MidnightControlsConfig.debug) MidnightControls.get().log(""+i);
|
||||||
optionsGUI.setPage(accessor.getPages().get(i));
|
optionsGUI.setPage(accessor.getPages().get(i));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,10 @@ import net.minecraft.client.gui.Element;
|
|||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
public class YACLCompat implements CompatHandler {
|
public class YACLCompat {
|
||||||
public static boolean handleAButton(Screen screen, Element element) {
|
public static boolean handleAButton(Screen screen, Element element) {
|
||||||
if (element instanceof AbstractWidget abstractWidget) {
|
if (element instanceof AbstractWidget abstractWidget) {
|
||||||
// imitate enter key press
|
// imitate ender key press
|
||||||
return abstractWidget.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0);
|
return abstractWidget.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -41,8 +41,7 @@ public class YACLCompat implements CompatHandler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static boolean handleCategories(Screen screen, boolean direction) {
|
||||||
public boolean handleTabs(Screen screen, boolean direction) {
|
|
||||||
if (screen instanceof YACLScreen yaclScreen) {
|
if (screen instanceof YACLScreen yaclScreen) {
|
||||||
int categoryIdx = yaclScreen.getCurrentCategoryIdx();
|
int categoryIdx = yaclScreen.getCurrentCategoryIdx();
|
||||||
if (direction) categoryIdx++; else categoryIdx--;
|
if (direction) categoryIdx++; else categoryIdx--;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.compat.mixin.sodium;
|
package eu.midnightdust.midnightcontrols.client.compat.mixin;
|
||||||
|
|
||||||
import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI;
|
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
|
||||||
import net.caffeinemc.mods.sodium.client.gui.options.OptionPage;
|
import me.jellysquid.mods.sodium.client.gui.options.OptionPage;
|
||||||
import net.caffeinemc.mods.sodium.client.gui.options.control.ControlElement;
|
import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
|
||||||
@@ -19,14 +18,14 @@ import net.minecraft.client.option.KeyBinding;
|
|||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
||||||
|
import org.aperlambda.lambdacommon.utils.function.Predicates;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +49,7 @@ public class ButtonBinding {
|
|||||||
public static final ButtonBinding CONTROLS_RING = new Builder("controls_ring").buttons(GLFW_GAMEPAD_BUTTON_GUIDE).onlyInGame().cooldown()
|
public static final ButtonBinding CONTROLS_RING = new Builder("controls_ring").buttons(GLFW_GAMEPAD_BUTTON_GUIDE).onlyInGame().cooldown()
|
||||||
.action((client, button1, value, action) -> {
|
.action((client, button1, value, action) -> {
|
||||||
if (action.isPressed()) {
|
if (action.isPressed()) {
|
||||||
MidnightControlsClient.ring.loadFromUnbound();
|
MidnightControlsClient.get().ring.loadFromUnbound();
|
||||||
client.setScreen(new RingScreen());
|
client.setScreen(new RingScreen());
|
||||||
}
|
}
|
||||||
if (action.isUnpressed() && client.currentScreen != null) client.currentScreen.close();
|
if (action.isUnpressed() && client.currentScreen != null) client.currentScreen.close();
|
||||||
@@ -64,7 +63,7 @@ public class ButtonBinding {
|
|||||||
public static final ButtonBinding HOTBAR_RIGHT = new Builder("hotbar_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
public static final ButtonBinding HOTBAR_RIGHT = new Builder("hotbar_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||||
.action(InputHandlers.handleHotbar(true)).onlyInGame().cooldown().register();
|
.action(InputHandlers.handleHotbar(true)).onlyInGame().cooldown().register();
|
||||||
public static final ButtonBinding INVENTORY = new Builder("inventory").buttons(GLFW_GAMEPAD_BUTTON_Y).onlyInGame().cooldown().register();
|
public static final ButtonBinding INVENTORY = new Builder("inventory").buttons(GLFW_GAMEPAD_BUTTON_Y).onlyInGame().cooldown().register();
|
||||||
public static final ButtonBinding EXIT = new Builder("exit").buttons(GLFW_GAMEPAD_BUTTON_B).filter((buttonBinding) -> client.currentScreen != null && buttonBinding.cooldown == 0 && INVENTORY.cooldown == 0)
|
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();
|
.action(InputHandlers.handleExit()).cooldown().register();
|
||||||
public static final ButtonBinding JUMP = new Builder("jump").buttons(GLFW_GAMEPAD_BUTTON_A).onlyInGame().register();
|
public static final ButtonBinding JUMP = new Builder("jump").buttons(GLFW_GAMEPAD_BUTTON_A).onlyInGame().register();
|
||||||
public static final ButtonBinding LEFT = new Builder("left").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false))
|
public static final ButtonBinding LEFT = new Builder("left").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false))
|
||||||
@@ -77,7 +76,7 @@ public class ButtonBinding {
|
|||||||
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
|
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
|
||||||
.action(InputHandlers::handleScreenshot).cooldown().register();
|
.action(InputHandlers::handleScreenshot).cooldown().register();
|
||||||
public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B)
|
public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B)
|
||||||
.action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.inGameHud.getDebugHud().toggleDebugHud(); return true;}).cooldown().register();
|
.action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.options.debugEnabled = !client.options.debugEnabled; return true;}).cooldown().register();
|
||||||
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
||||||
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
|
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
|
||||||
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
|
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
|
||||||
@@ -89,12 +88,12 @@ public class ButtonBinding {
|
|||||||
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
||||||
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register();
|
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register();
|
||||||
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
||||||
.actions(InputHandlers::handleToggleSprint).onlyInGame().cooldown().register();
|
.actions(InputHandlers::handleToggleSprint).onlyInGame().register();
|
||||||
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).onlyInGame().cooldown().register();
|
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).onlyInGame().cooldown().register();
|
||||||
public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
||||||
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((binding) -> client.currentScreen != null)).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)
|
public static final ButtonBinding TAB_RIGHT = new Builder("tab_next").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||||
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((binding) -> client.currentScreen != null)).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))
|
public static final ButtonBinding PAGE_LEFT = new Builder("page_back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
|
||||||
.action(InputHandlers.handlePage(false)).filter(InputHandlers::inInventory).cooldown(30).register();
|
.action(InputHandlers.handlePage(false)).filter(InputHandlers::inInventory).cooldown(30).register();
|
||||||
public static final ButtonBinding PAGE_RIGHT = new Builder("page_next").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
public static final ButtonBinding PAGE_RIGHT = new Builder("page_next").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
|
||||||
@@ -113,14 +112,14 @@ public class ButtonBinding {
|
|||||||
private final String key;
|
private final String key;
|
||||||
private final Text text;
|
private final Text text;
|
||||||
private KeyBinding mcKeyBinding = null;
|
private KeyBinding mcKeyBinding = null;
|
||||||
protected Predicate<ButtonBinding> filter;
|
protected PairPredicate<MinecraftClient, ButtonBinding> filter;
|
||||||
private final List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
|
private final List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
|
||||||
private final boolean hasCooldown;
|
private boolean hasCooldown;
|
||||||
private int cooldownLength = 5;
|
private int cooldownLength = 5;
|
||||||
private int cooldown = 0;
|
private int cooldown = 0;
|
||||||
private boolean pressed = false;
|
boolean pressed = false;
|
||||||
|
|
||||||
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, Predicate<ButtonBinding> filter, boolean hasCooldown) {
|
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
||||||
this.setButton(this.defaultButton = defaultButton);
|
this.setButton(this.defaultButton = defaultButton);
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.text = Text.translatable(this.key);
|
this.text = Text.translatable(this.key);
|
||||||
@@ -128,7 +127,7 @@ public class ButtonBinding {
|
|||||||
this.actions.addAll(actions);
|
this.actions.addAll(actions);
|
||||||
this.hasCooldown = hasCooldown;
|
this.hasCooldown = hasCooldown;
|
||||||
}
|
}
|
||||||
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, Predicate<ButtonBinding> filter, boolean hasCooldown, int cooldownLength) {
|
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown, int cooldownLength) {
|
||||||
this.setButton(this.defaultButton = defaultButton);
|
this.setButton(this.defaultButton = defaultButton);
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.text = Text.translatable(this.key);
|
this.text = Text.translatable(this.key);
|
||||||
@@ -139,10 +138,10 @@ public class ButtonBinding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown) {
|
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown) {
|
||||||
this(key, defaultButton, Collections.emptyList(), Predicates.alwaysTrue(), hasCooldown);
|
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown);
|
||||||
}
|
}
|
||||||
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown, int cooldownLength) {
|
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown, int cooldownLength) {
|
||||||
this(key, defaultButton, Collections.emptyList(), Predicates.alwaysTrue(), hasCooldown, cooldownLength);
|
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown, cooldownLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,14 +164,6 @@ public class ButtonBinding {
|
|||||||
if (InputManager.hasBinding(this))
|
if (InputManager.hasBinding(this))
|
||||||
InputManager.sortBindings();
|
InputManager.sortBindings();
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Sets the button press state.
|
|
||||||
*
|
|
||||||
* @param pressed whether the button is pressed
|
|
||||||
*/
|
|
||||||
public void setPressed(boolean pressed) {
|
|
||||||
this.pressed = pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the bound button is the specified button or not.
|
* Returns whether the bound button is the specified button or not.
|
||||||
@@ -188,18 +179,8 @@ public class ButtonBinding {
|
|||||||
* Returns whether this button is down or not.
|
* Returns whether this button is down or not.
|
||||||
*
|
*
|
||||||
* @return true if the button is down, else false
|
* @return true if the button is down, else false
|
||||||
* @deprecated Use {@link #isPressed()} instead
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public boolean isButtonDown() {
|
public boolean isButtonDown() {
|
||||||
return isPressed();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns whether this button is down or not.
|
|
||||||
*
|
|
||||||
* @return true if the button is down, else false
|
|
||||||
*/
|
|
||||||
public boolean isPressed() {
|
|
||||||
return this.pressed;
|
return this.pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,10 +234,11 @@ public class ButtonBinding {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the button binding is available in the current context.
|
* Returns whether the button binding is available in the current context.
|
||||||
*
|
*
|
||||||
|
* @param client the client instance
|
||||||
* @return true if the button binding is available, else false
|
* @return true if the button binding is available, else false
|
||||||
*/
|
*/
|
||||||
public boolean isAvailable() {
|
public boolean isAvailable(@NotNull MinecraftClient client) {
|
||||||
return this.filter.test(this);
|
return this.filter.test(client, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -480,7 +462,7 @@ public class ButtonBinding {
|
|||||||
private final String key;
|
private final String key;
|
||||||
private int[] buttons = new int[0];
|
private int[] buttons = new int[0];
|
||||||
private final List<PressAction> actions = new ArrayList<>();
|
private final List<PressAction> actions = new ArrayList<>();
|
||||||
private Predicate<ButtonBinding> filter = Predicates.alwaysTrue();
|
private PairPredicate<MinecraftClient, ButtonBinding> filter = Predicates.pairAlwaysTrue();
|
||||||
private boolean cooldown = false;
|
private boolean cooldown = false;
|
||||||
private int cooldownLength = 5;
|
private int cooldownLength = 5;
|
||||||
private ButtonCategory category = null;
|
private ButtonCategory category = null;
|
||||||
@@ -499,10 +481,6 @@ public class ButtonBinding {
|
|||||||
public Builder(@NotNull Identifier identifier) {
|
public Builder(@NotNull Identifier identifier) {
|
||||||
this(identifier.getNamespace() + "." + identifier.getPath());
|
this(identifier.getNamespace() + "." + identifier.getPath());
|
||||||
}
|
}
|
||||||
@Deprecated
|
|
||||||
public Builder(@NotNull org.aperlambda.lambdacommon.Identifier identifier) {
|
|
||||||
this(identifier.getNamespace() + "." + identifier.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the default buttons of the {@link ButtonBinding}.
|
* Defines the default buttons of the {@link ButtonBinding}.
|
||||||
@@ -552,7 +530,7 @@ public class ButtonBinding {
|
|||||||
* @param filter the filter
|
* @param filter the filter
|
||||||
* @return the builder instance
|
* @return the builder instance
|
||||||
*/
|
*/
|
||||||
public Builder filter(@NotNull Predicate<ButtonBinding> filter) {
|
public Builder filter(@NotNull PairPredicate<MinecraftClient, ButtonBinding> filter) {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -561,8 +539,8 @@ public class ButtonBinding {
|
|||||||
* Sets the filter of {@link ButtonBinding} to only in game.
|
* Sets the filter of {@link ButtonBinding} to only in game.
|
||||||
*
|
*
|
||||||
* @return the builder instance
|
* @return the builder instance
|
||||||
* @see #filter(Predicate)
|
* @see #filter(PairPredicate)
|
||||||
* @see InputHandlers#inGame(ButtonBinding)
|
* @see InputHandlers#inGame(MinecraftClient, ButtonBinding)
|
||||||
*/
|
*/
|
||||||
public Builder onlyInGame() {
|
public Builder onlyInGame() {
|
||||||
return this.filter(InputHandlers::inGame);
|
return this.filter(InputHandlers::inGame);
|
||||||
@@ -572,8 +550,8 @@ public class ButtonBinding {
|
|||||||
* Sets the filter of {@link ButtonBinding} to only in inventory.
|
* Sets the filter of {@link ButtonBinding} to only in inventory.
|
||||||
*
|
*
|
||||||
* @return the builder instance
|
* @return the builder instance
|
||||||
* @see #filter(Predicate)
|
* @see #filter(PairPredicate)
|
||||||
* @see InputHandlers#inInventory(ButtonBinding)
|
* @see InputHandlers#inInventory(MinecraftClient, ButtonBinding)
|
||||||
*/
|
*/
|
||||||
public Builder onlyInInventory() {
|
public Builder onlyInInventory() {
|
||||||
return this.filter(InputHandlers::inInventory);
|
return this.filter(InputHandlers::inInventory);
|
||||||
@@ -10,7 +10,8 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.util.Identifier;
|
import org.aperlambda.lambdacommon.Identifier;
|
||||||
|
import org.aperlambda.lambdacommon.utils.Identifiable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -25,7 +26,7 @@ import java.util.List;
|
|||||||
* @version 1.1.0
|
* @version 1.1.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
public class ButtonCategory {
|
public class ButtonCategory implements Identifiable {
|
||||||
private final List<ButtonBinding> bindings = new ArrayList<>();
|
private final List<ButtonBinding> bindings = new ArrayList<>();
|
||||||
private final Identifier id;
|
private final Identifier id;
|
||||||
private final int priority;
|
private final int priority;
|
||||||
@@ -38,15 +39,6 @@ public class ButtonCategory {
|
|||||||
public ButtonCategory(@NotNull Identifier id) {
|
public ButtonCategory(@NotNull Identifier id) {
|
||||||
this(id, 100);
|
this(id, 100);
|
||||||
}
|
}
|
||||||
@Deprecated
|
|
||||||
public ButtonCategory(@NotNull org.aperlambda.lambdacommon.Identifier id, int priority) {
|
|
||||||
this(Identifier.of(id.getNamespace(), id.getName()), priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public ButtonCategory(@NotNull org.aperlambda.lambdacommon.Identifier id) {
|
|
||||||
this(id, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerBinding(@NotNull ButtonBinding binding) {
|
public void registerBinding(@NotNull ButtonBinding binding) {
|
||||||
if (this.bindings.contains(binding))
|
if (this.bindings.contains(binding))
|
||||||
@@ -80,9 +72,9 @@ public class ButtonCategory {
|
|||||||
*/
|
*/
|
||||||
public @NotNull String getTranslatedName() {
|
public @NotNull String getTranslatedName() {
|
||||||
if (this.id.getNamespace().equals("minecraft"))
|
if (this.id.getNamespace().equals("minecraft"))
|
||||||
return I18n.translate(this.id.getPath());
|
return I18n.translate(this.id.getName());
|
||||||
else
|
else
|
||||||
return I18n.translate(this.id.getNamespace() + "." + this.id.getPath());
|
return I18n.translate(this.id.getNamespace() + "." + this.id.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,6 +87,7 @@ public class ButtonCategory {
|
|||||||
return this.priority;
|
return this.priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public @NotNull Identifier getIdentifier() {
|
public @NotNull Identifier getIdentifier() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ import org.lwjgl.system.MemoryStack;
|
|||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URI;
|
import java.net.URL;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -43,7 +43,7 @@ import static org.lwjgl.BufferUtils.createByteBuffer;
|
|||||||
* @version 1.7.0
|
* @version 1.7.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public record Controller(int id) {
|
public record Controller(int id) implements Nameable {
|
||||||
private static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
private static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +79,7 @@ public record Controller(int id) {
|
|||||||
*
|
*
|
||||||
* @return the controller's name
|
* @return the controller's name
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
var name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
|
var name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
|
||||||
return name == null ? String.valueOf(this.id()) : name;
|
return name == null ? String.valueOf(this.id()) : name;
|
||||||
@@ -98,7 +99,7 @@ public record Controller(int id) {
|
|||||||
|
|
||||||
public static Controller byId(int id) {
|
public static Controller byId(int id) {
|
||||||
if (id > GLFW.GLFW_JOYSTICK_LAST) {
|
if (id > GLFW.GLFW_JOYSTICK_LAST) {
|
||||||
MidnightControls.log("Controller '" + id + "' doesn't exist.");
|
MidnightControlsClient.get().log("Controller '" + id + "' doesn't exist.");
|
||||||
id = GLFW.GLFW_JOYSTICK_LAST;
|
id = GLFW.GLFW_JOYSTICK_LAST;
|
||||||
}
|
}
|
||||||
Controller controller;
|
Controller controller;
|
||||||
@@ -121,10 +122,11 @@ public record Controller(int id) {
|
|||||||
* Reads the specified resource and returns the raw data as a ByteBuffer.
|
* Reads the specified resource and returns the raw data as a ByteBuffer.
|
||||||
*
|
*
|
||||||
* @param resource the resource to read
|
* @param resource the resource to read
|
||||||
|
* @param bufferSize the initial buffer size
|
||||||
* @return the resource data
|
* @return the resource data
|
||||||
* @throws IOException If an IO error occurs.
|
* @throws IOException If an IO error occurs.
|
||||||
*/
|
*/
|
||||||
private static ByteBuffer ioResourceToBuffer(String resource) throws IOException {
|
private static ByteBuffer ioResourceToBuffer(String resource, int bufferSize) throws IOException {
|
||||||
ByteBuffer buffer = null;
|
ByteBuffer buffer = null;
|
||||||
|
|
||||||
var path = Paths.get(resource);
|
var path = Paths.get(resource);
|
||||||
@@ -148,18 +150,26 @@ public record Controller(int id) {
|
|||||||
}
|
}
|
||||||
private static boolean updateMappingsSync() {
|
private static boolean updateMappingsSync() {
|
||||||
try {
|
try {
|
||||||
MidnightControls.log("Updating controller mappings...");
|
MidnightControlsClient.get().log("Updating controller mappings...");
|
||||||
Optional<File> databaseFile = getDatabaseFile();
|
File databaseFile = new File("config/gamecontrollerdatabase.txt");
|
||||||
if (databaseFile.isPresent()) {
|
try {
|
||||||
var database = ioResourceToBuffer(databaseFile.get().getPath());
|
BufferedInputStream in = new BufferedInputStream(new URL("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").openStream());
|
||||||
if (database != null) GLFW.glfwUpdateGamepadMappings(database);
|
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(databaseFile));
|
||||||
}
|
byte[] dataBuffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
||||||
|
out.write(dataBuffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
} catch (Exception ignored) {/* Just continue when internet connection is not available */}
|
||||||
|
var database = ioResourceToBuffer(databaseFile.getPath(), 1024);
|
||||||
|
if (database != null) GLFW.glfwUpdateGamepadMappings(database);
|
||||||
if (!MidnightControlsClient.MAPPINGS_FILE.exists())
|
if (!MidnightControlsClient.MAPPINGS_FILE.exists())
|
||||||
return false;
|
return false;
|
||||||
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath());
|
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024);
|
||||||
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
|
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.fillInStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
try (var memoryStack = MemoryStack.stackPush()) {
|
try (var memoryStack = MemoryStack.stackPush()) {
|
||||||
@@ -172,8 +182,8 @@ public record Controller(int id) {
|
|||||||
if (client != null) {
|
if (client != null) {
|
||||||
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
|
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
|
||||||
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string)));
|
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string)));
|
||||||
|
MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
|
||||||
}
|
}
|
||||||
MidnightControls.log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
/* Ignored :concern: */
|
/* Ignored :concern: */
|
||||||
@@ -186,7 +196,7 @@ public record Controller(int id) {
|
|||||||
if (!controller.isConnected())
|
if (!controller.isConnected())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MidnightControls.log(String.format("Controller #%d name: \"%s\"\n GUID: %s\n Gamepad: %s",
|
MidnightControls.get().log(String.format("Controller #%d name: \"%s\"\n GUID: %s\n Gamepad: %s",
|
||||||
controller.id,
|
controller.id,
|
||||||
controller.getName(),
|
controller.getName(),
|
||||||
controller.getGuid(),
|
controller.getGuid(),
|
||||||
@@ -195,19 +205,4 @@ public record Controller(int id) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Optional<File> getDatabaseFile() {
|
|
||||||
File databaseFile = new File("config/gamecontrollerdatabase.txt");
|
|
||||||
try {
|
|
||||||
BufferedInputStream in = new BufferedInputStream(URI.create("https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt").toURL().openStream());
|
|
||||||
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(databaseFile));
|
|
||||||
byte[] dataBuffer = new byte[1024];
|
|
||||||
int bytesRead;
|
|
||||||
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
|
||||||
out.write(dataBuffer, 0, bytesRead);
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
} catch (Exception e) {return Optional.empty();}
|
|
||||||
return Optional.of(databaseFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -10,34 +10,45 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.controller;
|
package eu.midnightdust.midnightcontrols.client.controller;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.InventoryTabsCompat;
|
import eu.midnightdust.midnightcontrols.client.compat.InventoryTabsCompat;
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
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.RingScreen;
|
||||||
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
|
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.*;
|
import eu.midnightdust.midnightcontrols.client.mixin.*;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.InventoryUtil;
|
import net.fabricmc.fabric.impl.client.itemgroup.CreativeGuiExtensions;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.ToggleSneakSprintUtil;
|
import net.fabricmc.fabric.impl.client.itemgroup.FabricCreativeGuiComponents;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.platform.ItemGroupUtil;
|
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.TitleScreen;
|
import net.minecraft.client.gui.screen.TitleScreen;
|
||||||
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.*;
|
import net.minecraft.client.gui.screen.ingame.*;
|
||||||
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
|
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.gui.widget.TabNavigationWidget;
|
||||||
import net.minecraft.client.util.ScreenshotRecorder;
|
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.Slot;
|
||||||
import net.minecraft.screen.slot.SlotActionType;
|
import net.minecraft.screen.slot.SlotActionType;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import org.aperlambda.lambdacommon.utils.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_2;
|
import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_2;
|
||||||
|
|
||||||
@@ -48,9 +59,17 @@ import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_2;
|
|||||||
* @version 1.7.0
|
* @version 1.7.0
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
public class InputHandlers {
|
public class InputHandlers {
|
||||||
private InputHandlers() {
|
private InputHandlers() {
|
||||||
}
|
}
|
||||||
|
private static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
|
||||||
|
return ItemGroups.getGroups().stream()
|
||||||
|
.filter(itemGroup -> {
|
||||||
|
if (FabricCreativeGuiComponents.COMMON_GROUPS.contains(itemGroup)) return true;
|
||||||
|
return ((CreativeGuiExtensions)screen).fabric_currentPage() == ((FabricItemGroup)itemGroup).getPage() && itemGroup.shouldDisplay();
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
public static PressAction handleHotbar(boolean next) {
|
public static PressAction handleHotbar(boolean next) {
|
||||||
return (client, button, value, action) -> {
|
return (client, button, value, action) -> {
|
||||||
@@ -60,11 +79,10 @@ public class InputHandlers {
|
|||||||
// When in-game
|
// When in-game
|
||||||
if (client.currentScreen == null && client.player != null) {
|
if (client.currentScreen == null && client.player != null) {
|
||||||
if (!client.player.isSpectator()) {
|
if (!client.player.isSpectator()) {
|
||||||
var inv = client.player.getInventory();
|
|
||||||
if (next)
|
if (next)
|
||||||
inv.setSelectedSlot(inv.selectedSlot < 8 ? inv.selectedSlot + 1 : inv.selectedSlot - 8);
|
client.player.getInventory().scrollInHotbar(-1.0);
|
||||||
else
|
else
|
||||||
inv.setSelectedSlot(inv.selectedSlot > 0 ? inv.selectedSlot - 1 : inv.selectedSlot + 8);
|
client.player.getInventory().scrollInHotbar(1.0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (client.inGameHud.getSpectatorHud().isOpen()) {
|
if (client.inGameHud.getSpectatorHud().isOpen()) {
|
||||||
@@ -76,18 +94,46 @@ public class InputHandlers {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (client.currentScreen instanceof RingScreen) {
|
} else if (client.currentScreen instanceof RingScreen) {
|
||||||
MidnightControlsClient.ring.cyclePage(next);
|
MidnightControlsClient.get().ring.cyclePage(next);
|
||||||
} else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) {
|
} else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) {
|
||||||
inventory.midnightcontrols$setSelectedTab(ItemGroupUtil.cycleTab(next, client));
|
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;
|
return true;
|
||||||
} else if (client.currentScreen instanceof RecipeBookScreen<?> recipeBookScreen) {
|
} else if (client.currentScreen instanceof InventoryScreen || client.currentScreen instanceof CraftingScreen || client.currentScreen instanceof AbstractFurnaceScreen<?>) {
|
||||||
RecipeBookWidget<?> recipeBook = ((RecipeBookScreenAccessor) recipeBookScreen).getRecipeBook();
|
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 recipeBookAccessor = (RecipeBookWidgetAccessor) recipeBook;
|
||||||
var tabs = recipeBookAccessor.getTabButtons();
|
var tabs = recipeBookAccessor.getTabButtons();
|
||||||
var currentTab = recipeBookAccessor.getCurrentTab();
|
var currentTab = recipeBookAccessor.getCurrentTab();
|
||||||
if (currentTab == null || !recipeBook.isOpen()) {
|
if (currentTab == null || !recipeBook.isOpen()) {
|
||||||
return MidnightControlsCompat.handleTabs(client.currentScreen, next);
|
if (MidnightControlsCompat.isInventoryTabsPresent()) InventoryTabsCompat.handleInventoryTabs(client.currentScreen, next);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1);
|
int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1);
|
||||||
if (nextTab < 0)
|
if (nextTab < 0)
|
||||||
@@ -97,7 +143,7 @@ public class InputHandlers {
|
|||||||
currentTab.setToggled(false);
|
currentTab.setToggled(false);
|
||||||
recipeBookAccessor.setCurrentTab(currentTab = tabs.get(nextTab));
|
recipeBookAccessor.setCurrentTab(currentTab = tabs.get(nextTab));
|
||||||
currentTab.setToggled(true);
|
currentTab.setToggled(true);
|
||||||
recipeBookScreen.refreshRecipeBook();
|
recipeBookAccessor.midnightcontrols$refreshResults(true);
|
||||||
return true;
|
return true;
|
||||||
} else if (client.currentScreen instanceof AdvancementsScreenAccessor screen) {
|
} else if (client.currentScreen instanceof AdvancementsScreenAccessor screen) {
|
||||||
var tabs = screen.getTabs().values().stream().distinct().toList();
|
var tabs = screen.getTabs().values().stream().distinct().toList();
|
||||||
@@ -111,7 +157,7 @@ public class InputHandlers {
|
|||||||
nextTab = tabs.size() - 1;
|
nextTab = tabs.size() - 1;
|
||||||
else if (nextTab >= tabs.size())
|
else if (nextTab >= tabs.size())
|
||||||
nextTab = 0;
|
nextTab = 0;
|
||||||
screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot().getAdvancementEntry(), true);
|
screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot(), true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,29 +175,47 @@ public class InputHandlers {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
} else return MidnightControlsCompat.handleTabs(client.currentScreen, next);
|
} 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;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PressAction handlePage(boolean next) {
|
public static PressAction handlePage(boolean next) {
|
||||||
return (client, button, value, action) -> {
|
return (client, button, value, action) -> {
|
||||||
if (action == ButtonState.RELEASE)
|
if (action == ButtonState.RELEASE)
|
||||||
return false;
|
return false;
|
||||||
if (client.currentScreen instanceof CreativeInventoryScreen creativeScreen) {
|
if (client.currentScreen instanceof CreativeInventoryScreen) {
|
||||||
return ItemGroupUtil.cyclePage(next, creativeScreen);
|
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;
|
||||||
return MidnightControlsCompat.handlePages(client.currentScreen, next);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public static PressAction handleExit() {
|
public static PressAction handleExit() {
|
||||||
return (client, button, value, action) -> {
|
return (client, button, value, action) -> {
|
||||||
if (client.currentScreen != null && client.currentScreen.getClass() != TitleScreen.class) {
|
if (client.currentScreen != null && client.currentScreen.getClass() != TitleScreen.class) {
|
||||||
if (!MidnightControlsCompat.handleMenuBack(client, client.currentScreen))
|
if (!MidnightControlsCompat.handleMenuBack(client, client.currentScreen))
|
||||||
if (!MidnightControlsClient.input.tryGoBack(client.currentScreen))
|
if (!MidnightControlsClient.get().input.tryGoBack(client.currentScreen))
|
||||||
client.currentScreen.close();
|
client.currentScreen.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -164,17 +228,18 @@ public class InputHandlers {
|
|||||||
if (client.interactionManager == null || client.player == null)
|
if (client.interactionManager == null || client.player == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (MidnightControlsClient.input.inventoryInteractionCooldown > 0)
|
if (MidnightControlsClient.get().input.inventoryInteractionCooldown > 0)
|
||||||
return true;
|
return true;
|
||||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
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();
|
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||||
|
|
||||||
var accessor = (HandledScreenAccessor) screen;
|
var accessor = (HandledScreenAccessor) screen;
|
||||||
Slot slot = accessor.midnightcontrols$getSlotAt(x, y);
|
Slot slot = ((HandledScreenAccessor) screen).midnightcontrols$getSlotAt(x, y);
|
||||||
|
|
||||||
int slotId;
|
int slotId;
|
||||||
if (slot == null) {
|
if (slot == null) {
|
||||||
if (button.getName().equals("take_all")) {
|
if (button.getName().equals("take_all")) {
|
||||||
|
((MouseAccessor) client.mouse).setLeftButtonClicked(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
slotId = accessor.midnightcontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1;
|
slotId = accessor.midnightcontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1;
|
||||||
@@ -184,7 +249,7 @@ public class InputHandlers {
|
|||||||
var actionType = SlotActionType.PICKUP;
|
var actionType = SlotActionType.PICKUP;
|
||||||
int clickData = GLFW.GLFW_MOUSE_BUTTON_1;
|
int clickData = GLFW.GLFW_MOUSE_BUTTON_1;
|
||||||
|
|
||||||
MidnightControlsClient.input.inventoryInteractionCooldown = 5;
|
MidnightControlsClient.get().input.inventoryInteractionCooldown = 5;
|
||||||
switch (button.getName()) {
|
switch (button.getName()) {
|
||||||
case "take_all" -> {
|
case "take_all" -> {
|
||||||
if (screen instanceof CreativeInventoryScreen) {
|
if (screen instanceof CreativeInventoryScreen) {
|
||||||
@@ -211,7 +276,7 @@ public class InputHandlers {
|
|||||||
if (action == ButtonState.PRESS) {
|
if (action == ButtonState.PRESS) {
|
||||||
// If in game, then pause the game.
|
// If in game, then pause the game.
|
||||||
if (client.currentScreen == null || client.currentScreen instanceof RingScreen)
|
if (client.currentScreen == null || client.currentScreen instanceof RingScreen)
|
||||||
client.openGameMenu(false);
|
client.openPauseMenu(false);
|
||||||
else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it.
|
else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it.
|
||||||
client.player.closeHandledScreen();
|
client.player.closeHandledScreen();
|
||||||
else // Else just close the current screen.
|
else // Else just close the current screen.
|
||||||
@@ -236,25 +301,95 @@ public class InputHandlers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||||
return ToggleSneakSprintUtil.toggleSneak(button);
|
button.asKeyBinding().ifPresent(binding -> {
|
||||||
|
boolean sneakToggled = client.options.getSneakToggled().getValue();
|
||||||
|
if (client.player.getAbilities().flying && sneakToggled)
|
||||||
|
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.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) {
|
public static boolean handleToggleSprint(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
|
||||||
return ToggleSneakSprintUtil.toggleSprint(button);
|
button.asKeyBinding().ifPresent(binding -> {
|
||||||
|
boolean sprintToggled = client.options.getSprintToggled().getValue();
|
||||||
|
if (client.player.getAbilities().flying && sprintToggled)
|
||||||
|
client.options.getSprintToggled().setValue(false);
|
||||||
|
else if (MidnightControlsConfig.controllerToggleSneak != sprintToggled)
|
||||||
|
client.options.getSprintToggled().setValue(!sprintToggled);
|
||||||
|
binding.setPressed(button.pressed);
|
||||||
|
if (client.player.getAbilities().flying && sprintToggled)
|
||||||
|
client.options.getSprintToggled().setValue(true);
|
||||||
|
else if (MidnightControlsConfig.controllerToggleSneak != sprintToggled)
|
||||||
|
client.options.getSprintToggled().setValue(sprintToggled);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PressAction handleInventorySlotPad(int direction) {
|
public static PressAction handleInventorySlotPad(int direction) {
|
||||||
return (client, binding, value, action) -> {
|
return (client, binding, value, action) -> {
|
||||||
if (!(client.currentScreen instanceof HandledScreen<?> inventory && action != ButtonState.RELEASE))
|
if (!(client.currentScreen instanceof HandledScreen inventory && action != ButtonState.RELEASE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var accessor = (HandledScreenAccessor) inventory;
|
var accessor = (HandledScreenAccessor) inventory;
|
||||||
|
int guiLeft = accessor.getX();
|
||||||
|
int guiTop = accessor.getY();
|
||||||
|
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||||
|
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||||
|
|
||||||
Optional<Slot> closestSlot = InventoryUtil.findClosestSlot(inventory, direction);
|
// Finds the hovered slot.
|
||||||
|
var mouseSlot = accessor.midnightcontrols$getSlotAt(mouseX, mouseY);
|
||||||
|
|
||||||
|
// Finds the closest slot in the GUI within 14 pixels.
|
||||||
|
Optional<Slot> closestSlot = inventory.getScreenHandler().slots.parallelStream()
|
||||||
|
.filter(Predicate.isEqual(mouseSlot).negate())
|
||||||
|
.map(slot -> {
|
||||||
|
int posX = guiLeft + slot.x + 8;
|
||||||
|
int posY = guiTop + slot.y + 8;
|
||||||
|
|
||||||
|
int otherPosX = (int) mouseX;
|
||||||
|
int otherPosY = (int) mouseY;
|
||||||
|
if (mouseSlot != null) {
|
||||||
|
otherPosX = guiLeft + mouseSlot.x + 8;
|
||||||
|
otherPosY = guiTop + mouseSlot.y + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distance between the slot and the cursor.
|
||||||
|
double distance = Math.sqrt(Math.pow(posX - otherPosX, 2) + Math.pow(posY - otherPosY, 2));
|
||||||
|
return Pair.of(slot, distance);
|
||||||
|
}).filter(entry -> {
|
||||||
|
var slot = entry.key;
|
||||||
|
int posX = guiLeft + slot.x + 8;
|
||||||
|
int posY = guiTop + slot.y + 8;
|
||||||
|
int otherPosX = (int) mouseX;
|
||||||
|
int otherPosY = (int) mouseY;
|
||||||
|
if (mouseSlot != null) {
|
||||||
|
otherPosX = guiLeft + mouseSlot.x + 8;
|
||||||
|
otherPosY = guiTop + mouseSlot.y + 8;
|
||||||
|
}
|
||||||
|
if (direction == 0)
|
||||||
|
return posY < otherPosY;
|
||||||
|
else if (direction == 1)
|
||||||
|
return posY > otherPosY;
|
||||||
|
else if (direction == 2)
|
||||||
|
return posX > otherPosX;
|
||||||
|
else if (direction == 3)
|
||||||
|
return posX < otherPosX;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.min(Comparator.comparingDouble(p -> p.value))
|
||||||
|
.map(p -> p.key);
|
||||||
|
|
||||||
if (closestSlot.isPresent()) {
|
if (closestSlot.isPresent()) {
|
||||||
var slot = closestSlot.get();
|
var slot = closestSlot.get();
|
||||||
int x = accessor.getX() + slot.x + 8;
|
int x = guiLeft + slot.x + 8;
|
||||||
int y = accessor.getY() + slot.y + 8;
|
int y = guiTop + slot.y + 8;
|
||||||
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
|
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
|
||||||
y * (double) client.getWindow().getHeight() / (double) client.getWindow().getScaledHeight());
|
y * (double) client.getWindow().getHeight() / (double) client.getWindow().getScaledHeight());
|
||||||
return true;
|
return true;
|
||||||
@@ -266,30 +401,33 @@ public class InputHandlers {
|
|||||||
/**
|
/**
|
||||||
* Returns always true to the filter.
|
* Returns always true to the filter.
|
||||||
*
|
*
|
||||||
|
* @param client the client instance
|
||||||
* @param binding the affected binding
|
* @param binding the affected binding
|
||||||
* @return true
|
* @return true
|
||||||
*/
|
*/
|
||||||
public static boolean always(@NotNull ButtonBinding binding) {
|
public static boolean always(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the client is in game or not.
|
* Returns whether the client is in game or not.
|
||||||
*
|
*
|
||||||
|
* @param client the client instance
|
||||||
* @param binding the affected binding
|
* @param binding the affected binding
|
||||||
* @return true if the client is in game, else false
|
* @return true if the client is in game, else false
|
||||||
*/
|
*/
|
||||||
public static boolean inGame(@NotNull ButtonBinding binding) {
|
public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
return (client.currentScreen == null && MidnightControlsClient.input.screenCloseCooldown <= 0) || client.currentScreen instanceof TouchscreenOverlay || client.currentScreen instanceof RingScreen;
|
return (client.currentScreen == null && MidnightControlsClient.get().input.screenCloseCooldown <= 0) || client.currentScreen instanceof TouchscreenOverlay || client.currentScreen instanceof RingScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the client is in a non-interactive screen (which means require mouse input) or not.
|
* Returns whether the client is in a non-interactive screen (which means require mouse input) or not.
|
||||||
*
|
*
|
||||||
|
* @param client the client instance
|
||||||
* @param binding the affected binding
|
* @param binding the affected binding
|
||||||
* @return true if the client is in a non-interactive screen, else false
|
* @return true if the client is in a non-interactive screen, else false
|
||||||
*/
|
*/
|
||||||
public static boolean inNonInteractiveScreens(@NotNull ButtonBinding binding) {
|
public static boolean inNonInteractiveScreens(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
if (client.currentScreen == null)
|
if (client.currentScreen == null)
|
||||||
return false;
|
return false;
|
||||||
return !MidnightInput.isScreenInteractive(client.currentScreen);
|
return !MidnightInput.isScreenInteractive(client.currentScreen);
|
||||||
@@ -298,20 +436,22 @@ public class InputHandlers {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the client is in an inventory or not.
|
* Returns whether the client is in an inventory or not.
|
||||||
*
|
*
|
||||||
|
* @param client the client instance
|
||||||
* @param binding the affected binding
|
* @param binding the affected binding
|
||||||
* @return true if the client is in an inventory, else false
|
* @return true if the client is in an inventory, else false
|
||||||
*/
|
*/
|
||||||
public static boolean inInventory(@NotNull ButtonBinding binding) {
|
public static boolean inInventory(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
return client.currentScreen instanceof HandledScreen;
|
return client.currentScreen instanceof HandledScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the client is in the advancements screen or not.
|
* Returns whether the client is in the advancements screen or not.
|
||||||
*
|
*
|
||||||
|
* @param client the client instance
|
||||||
* @param binding the affected binding
|
* @param binding the affected binding
|
||||||
* @return true if the client is in the advancements screen, else false
|
* @return true if the client is in the advancements screen, else false
|
||||||
*/
|
*/
|
||||||
public static boolean inAdvancements(@NotNull ButtonBinding binding) {
|
public static boolean inAdvancements(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
|
||||||
return client.currentScreen instanceof AdvancementsScreen;
|
return client.currentScreen instanceof AdvancementsScreen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,19 +19,16 @@ import net.minecraft.client.MinecraftClient;
|
|||||||
import net.minecraft.client.option.KeyBinding;
|
import net.minecraft.client.option.KeyBinding;
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.client.util.InputUtil;
|
import net.minecraft.client.util.InputUtil;
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import org.aperlambda.lambdacommon.Identifier;
|
||||||
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an input manager for controllers.
|
* Represents an input manager for controllers.
|
||||||
*
|
*
|
||||||
@@ -53,17 +50,17 @@ public class InputManager {
|
|||||||
protected InputManager() {
|
protected InputManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
public void tick(@NotNull MinecraftClient client) {
|
||||||
if (MidnightControlsConfig.autoSwitchMode && !MidnightControlsConfig.isEditing && MidnightControlsConfig.controlsMode != ControlsMode.TOUCHSCREEN)
|
if (MidnightControlsConfig.autoSwitchMode && !MidnightControlsConfig.isEditing && MidnightControlsConfig.controlsMode != ControlsMode.TOUCHSCREEN)
|
||||||
if (MidnightControlsConfig.getController().isConnected() && MidnightControlsConfig.getController().isGamepad())
|
if (MidnightControlsConfig.getController().isConnected() && MidnightControlsConfig.getController().isGamepad())
|
||||||
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER;
|
||||||
else MidnightControlsConfig.controlsMode = ControlsMode.DEFAULT;
|
else MidnightControlsConfig.controlsMode = ControlsMode.DEFAULT;
|
||||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
|
||||||
this.controllerTick();
|
this.controllerTick(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void controllerTick() {
|
public void controllerTick(@NotNull MinecraftClient client) {
|
||||||
this.prevTargetMouseX = this.targetMouseX;
|
this.prevTargetMouseX = this.targetMouseX;
|
||||||
this.prevTargetMouseY = this.targetMouseY;
|
this.prevTargetMouseY = this.targetMouseY;
|
||||||
}
|
}
|
||||||
@@ -76,8 +73,8 @@ public class InputManager {
|
|||||||
public void updateMousePosition(@NotNull MinecraftClient client) {
|
public void updateMousePosition(@NotNull MinecraftClient client) {
|
||||||
Objects.requireNonNull(client, "Client instance cannot be null.");
|
Objects.requireNonNull(client, "Client instance cannot be null.");
|
||||||
if (this.prevTargetMouseX != this.targetMouseX || this.prevTargetMouseY != this.targetMouseY) {
|
if (this.prevTargetMouseX != this.targetMouseX || this.prevTargetMouseY != this.targetMouseY) {
|
||||||
double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getRenderTickCounter().getTickDelta(true) + 0.5;
|
double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getTickDelta() + 0.5;
|
||||||
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getRenderTickCounter().getTickDelta(true) + 0.5;
|
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getTickDelta() + 0.5;
|
||||||
if (!MidnightControlsConfig.virtualMouse)
|
if (!MidnightControlsConfig.virtualMouse)
|
||||||
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
||||||
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
((MouseAccessor) client.mouse).midnightcontrols$onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
|
||||||
@@ -129,7 +126,7 @@ public class InputManager {
|
|||||||
* @return true if the binding is registered, else false
|
* @return true if the binding is registered, else false
|
||||||
*/
|
*/
|
||||||
public static boolean hasBinding(@NotNull Identifier identifier) {
|
public static boolean hasBinding(@NotNull Identifier identifier) {
|
||||||
return hasBinding(identifier.getNamespace() + "." + identifier.getPath());
|
return hasBinding(identifier.getNamespace() + "." + identifier.getName());
|
||||||
}
|
}
|
||||||
private static ButtonBinding tempBinding;
|
private static ButtonBinding tempBinding;
|
||||||
/**
|
/**
|
||||||
@@ -168,24 +165,22 @@ public class InputManager {
|
|||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull org.aperlambda.lambdacommon.Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull Predicate<ButtonBinding> filter, boolean hasCooldown) {
|
return registerBinding(new ButtonBinding(id.getNamespace() + "." + id.getName(), defaultButton, actions, filter, hasCooldown));
|
||||||
return registerBinding(Identifier.of(id.getNamespace(), id.getName()), defaultButton, actions, filter, hasCooldown);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull org.aperlambda.lambdacommon.Identifier id, int[] defaultButton, boolean hasCooldown) {
|
|
||||||
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull Predicate<ButtonBinding> filter, boolean hasCooldown) {
|
|
||||||
return registerBinding(new ButtonBinding(id.getNamespace() + "." + id.getPath(), defaultButton, actions, filter, hasCooldown));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, boolean hasCooldown) {
|
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, boolean hasCooldown) {
|
||||||
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
|
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static @NotNull ButtonBinding registerBinding(@NotNull net.minecraft.util.Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
|
||||||
|
return registerBinding(new Identifier(id.getNamespace(), id.getPath()), defaultButton, actions, filter, hasCooldown);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull ButtonBinding registerBinding(@NotNull net.minecraft.util.Identifier id, int[] defaultButton, boolean hasCooldown) {
|
||||||
|
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts bindings to get bindings with the higher button counts first.
|
* Sorts bindings to get bindings with the higher button counts first.
|
||||||
*/
|
*/
|
||||||
@@ -208,13 +203,6 @@ public class InputManager {
|
|||||||
CATEGORIES.add(category);
|
CATEGORIES.add(category);
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
public static ButtonCategory registerCategory(@NotNull org.aperlambda.lambdacommon.Identifier identifier, int priority) {
|
|
||||||
return registerCategory(Identifier.of(identifier.getNamespace(), identifier.getName()), priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ButtonCategory registerCategory(@NotNull org.aperlambda.lambdacommon.Identifier identifier) {
|
|
||||||
return registerCategory(Identifier.of(identifier.getNamespace(), identifier.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ButtonCategory registerCategory(@NotNull Identifier identifier, int priority) {
|
public static ButtonCategory registerCategory(@NotNull Identifier identifier, int priority) {
|
||||||
return registerCategory(new ButtonCategory(identifier, priority));
|
return registerCategory(new ButtonCategory(identifier, priority));
|
||||||
@@ -225,7 +213,7 @@ public class InputManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static ButtonCategory registerDefaultCategory(@NotNull String key, @NotNull Consumer<ButtonCategory> keyAdder) {
|
protected static ButtonCategory registerDefaultCategory(@NotNull String key, @NotNull Consumer<ButtonCategory> keyAdder) {
|
||||||
var category = registerCategory(Identifier.of("minecraft", key), CATEGORIES.size());
|
var category = registerCategory(new Identifier("minecraft", key), CATEGORIES.size());
|
||||||
keyAdder.accept(category);
|
keyAdder.accept(category);
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
@@ -342,27 +330,27 @@ public class InputManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateBindings() {
|
public static void updateBindings(@NotNull MinecraftClient client) {
|
||||||
var skipButtons = new IntArrayList();
|
var skipButtons = new IntArrayList();
|
||||||
record ButtonStateValue(ButtonState state, float value) {
|
record ButtonStateValue(ButtonState state, float value) {
|
||||||
}
|
}
|
||||||
var states = new Object2ObjectOpenHashMap<ButtonBinding, ButtonStateValue>();
|
var states = new Object2ObjectOpenHashMap<ButtonBinding, ButtonStateValue>();
|
||||||
for (var binding : BINDINGS) {
|
for (var binding : BINDINGS) {
|
||||||
var state = binding.isAvailable() ? getBindingState(binding) : ButtonState.NONE;
|
var state = binding.isAvailable(client) ? getBindingState(binding) : ButtonState.NONE;
|
||||||
if (skipButtons.intStream().anyMatch(btn -> containsButton(binding.getButton(), btn))) {
|
if (skipButtons.intStream().anyMatch(btn -> containsButton(binding.getButton(), btn))) {
|
||||||
if (binding.isPressed())
|
if (binding.pressed)
|
||||||
state = ButtonState.RELEASE;
|
state = ButtonState.RELEASE;
|
||||||
else
|
else
|
||||||
state = ButtonState.NONE;
|
state = ButtonState.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == ButtonState.RELEASE && !binding.isPressed()) {
|
if (state == ButtonState.RELEASE && !binding.pressed) {
|
||||||
state = ButtonState.NONE;
|
state = ButtonState.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.setPressed(state.isPressed());
|
binding.pressed = state.isPressed();
|
||||||
binding.update();
|
binding.update();
|
||||||
if (binding.isPressed())
|
if (binding.pressed)
|
||||||
Arrays.stream(binding.getButton()).forEach(skipButtons::add);
|
Arrays.stream(binding.getButton()).forEach(skipButtons::add);
|
||||||
|
|
||||||
float value = getBindingValue(binding, state);
|
float value = getBindingValue(binding, state);
|
||||||
@@ -404,7 +392,21 @@ public class InputManager {
|
|||||||
* @return the key binding
|
* @return the key binding
|
||||||
* @see #makeKeyBinding(Identifier, InputUtil.Type, int, String)
|
* @see #makeKeyBinding(Identifier, InputUtil.Type, int, String)
|
||||||
*/
|
*/
|
||||||
|
public static @NotNull KeyBinding makeKeyBinding(@NotNull net.minecraft.util.Identifier id, InputUtil.Type type, int code, @NotNull String category) {
|
||||||
|
return makeKeyBinding(new Identifier(id.getNamespace(), id.getPath()), type, code, category);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new key binding instance.
|
||||||
|
*
|
||||||
|
* @param id the identifier of the key binding
|
||||||
|
* @param type the type
|
||||||
|
* @param code the code
|
||||||
|
* @param category the category of the key binding
|
||||||
|
* @return the key binding
|
||||||
|
* @see #makeKeyBinding(net.minecraft.util.Identifier, InputUtil.Type, int, String)
|
||||||
|
*/
|
||||||
public static @NotNull KeyBinding makeKeyBinding(@NotNull Identifier id, InputUtil.Type type, int code, @NotNull String category) {
|
public static @NotNull KeyBinding makeKeyBinding(@NotNull Identifier id, InputUtil.Type type, int code, @NotNull String category) {
|
||||||
return new KeyBinding(String.format("key.%s.%s", id.getNamespace(), id.getPath()), type, code, category);
|
return new KeyBinding(String.format("key.%s.%s", id.getNamespace(), id.getName()), type, code, category);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,8 +14,7 @@ import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|||||||
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
|
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
import net.minecraft.entity.attribute.EntityAttributes;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.util.PlayerInput;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ public final class MovementHandler implements PressAction {
|
|||||||
private float slowdownFactor = 1.f;
|
private float slowdownFactor = 1.f;
|
||||||
private float movementForward = 0.f;
|
private float movementForward = 0.f;
|
||||||
private float movementSideways = 0.f;
|
private float movementSideways = 0.f;
|
||||||
private final MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil();
|
private MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil();
|
||||||
|
|
||||||
private MovementHandler() {
|
private MovementHandler() {
|
||||||
}
|
}
|
||||||
@@ -49,8 +48,10 @@ public final class MovementHandler implements PressAction {
|
|||||||
public void applyMovement(@NotNull ClientPlayerEntity player) {
|
public void applyMovement(@NotNull ClientPlayerEntity player) {
|
||||||
if (!this.shouldOverrideMovement)
|
if (!this.shouldOverrideMovement)
|
||||||
return;
|
return;
|
||||||
player.input.playerInput = new PlayerInput(this.pressingForward, this.pressingBack, this.pressingLeft, this.pressingRight,
|
player.input.pressingForward = this.pressingForward;
|
||||||
player.input.playerInput.jump(), player.input.playerInput.sneak(), player.input.playerInput.sprint());
|
player.input.pressingBack = this.pressingBack;
|
||||||
|
player.input.pressingLeft = this.pressingLeft;
|
||||||
|
player.input.pressingRight = this.pressingRight;
|
||||||
|
|
||||||
polarUtil.calculate(this.movementSideways, this.movementForward, this.slowdownFactor);
|
polarUtil.calculate(this.movementSideways, this.movementForward, this.slowdownFactor);
|
||||||
player.input.movementForward = polarUtil.polarY;
|
player.input.movementForward = polarUtil.polarY;
|
||||||
@@ -80,7 +81,7 @@ public final class MovementHandler implements PressAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.slowdownFactor = client.player.shouldSlowDown() ? (MathHelper.clamp(
|
this.slowdownFactor = client.player.shouldSlowDown() ? (MathHelper.clamp(
|
||||||
0.3F + (float) client.player.getAttributeValue(EntityAttributes.SNEAKING_SPEED),
|
0.3F + EnchantmentHelper.getSwiftSneakSpeedBoost(client.player),
|
||||||
0.0F,
|
0.0F,
|
||||||
1.0F
|
1.0F
|
||||||
)) : 1.f;
|
)) : 1.f;
|
||||||
@@ -29,9 +29,9 @@ public interface PressAction {
|
|||||||
return false;
|
return false;
|
||||||
button.asKeyBinding().ifPresent(binding -> {
|
button.asKeyBinding().ifPresent(binding -> {
|
||||||
if (binding instanceof StickyKeyBinding)
|
if (binding instanceof StickyKeyBinding)
|
||||||
binding.setPressed(button.isPressed());
|
binding.setPressed(button.pressed);
|
||||||
else
|
else
|
||||||
((KeyBindingAccessor) binding).midnightcontrols$handlePressState(button.isPressed());
|
((KeyBindingAccessor) binding).midnightcontrols$handlePressState(button.isButtonDown());
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.enums;
|
package eu.midnightdust.midnightcontrols.client.enums;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -22,7 +23,7 @@ import java.util.Optional;
|
|||||||
* @version 1.4.3
|
* @version 1.4.3
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum ControllerType {
|
public enum ControllerType implements Nameable {
|
||||||
DEFAULT(0),
|
DEFAULT(0),
|
||||||
DUALSHOCK(1),
|
DUALSHOCK(1),
|
||||||
DUALSENSE(2),
|
DUALSENSE(2),
|
||||||
@@ -77,6 +78,7 @@ public enum ControllerType {
|
|||||||
return this.text;
|
return this.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.name().toLowerCase();
|
return this.name().toLowerCase();
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ import java.util.Optional;
|
|||||||
* @version 1.4.0
|
* @version 1.4.0
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum HudSide {
|
public enum HudSide implements Nameable {
|
||||||
LEFT,
|
LEFT,
|
||||||
RIGHT;
|
RIGHT;
|
||||||
|
|
||||||
@@ -63,8 +63,9 @@ public enum HudSide {
|
|||||||
return this.text;
|
return this.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.name();
|
return this.name().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +74,6 @@ public enum HudSide {
|
|||||||
* @param id the identifier of the hud side
|
* @param id the identifier of the hud side
|
||||||
* @return the hud side if found, else empty
|
* @return the hud side if found, else empty
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public static @NotNull Optional<HudSide> byId(@NotNull String id) {
|
public static @NotNull Optional<HudSide> byId(@NotNull String id) {
|
||||||
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.enums;
|
package eu.midnightdust.midnightcontrols.client.enums;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
import org.aperlambda.lambdacommon.utils.Nameable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -21,7 +22,7 @@ import java.util.Optional;
|
|||||||
* @version 1.7.0
|
* @version 1.7.0
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
public enum VirtualMouseSkin {
|
public enum VirtualMouseSkin implements Nameable {
|
||||||
DEFAULT_LIGHT("default_light"),
|
DEFAULT_LIGHT("default_light"),
|
||||||
DEFAULT_DARK("default_dark"),
|
DEFAULT_DARK("default_dark"),
|
||||||
SECOND_LIGHT("second_light"),
|
SECOND_LIGHT("second_light"),
|
||||||
@@ -65,6 +66,7 @@ public enum VirtualMouseSkin {
|
|||||||
return this.text;
|
return this.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public @NotNull String getName() {
|
public @NotNull String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
@@ -75,16 +77,7 @@ public enum VirtualMouseSkin {
|
|||||||
* @param id the identifier of the virtual mouse skin
|
* @param id the identifier of the virtual mouse skin
|
||||||
* @return the virtual mouse skin if found, else empty
|
* @return the virtual mouse skin if found, else empty
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public static @NotNull Optional<VirtualMouseSkin> byId(@NotNull String id) {
|
public static @NotNull Optional<VirtualMouseSkin> byId(@NotNull String id) {
|
||||||
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
|
||||||
}
|
}
|
||||||
public String getSpritePath() {
|
|
||||||
return switch (this) {
|
|
||||||
case DEFAULT_LIGHT -> "cursor/light/default";
|
|
||||||
case DEFAULT_DARK -> "cursor/dark/default";
|
|
||||||
case SECOND_LIGHT -> "cursor/light/secondary";
|
|
||||||
case SECOND_DARK -> "cursor/dark/secondary";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -10,15 +10,11 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import dev.lambdaurora.spruceui.option.SpruceOption;
|
||||||
import org.thinkingstudio.obsidianui.Position;
|
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||||
import org.thinkingstudio.obsidianui.option.SpruceOption;
|
import dev.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
|
||||||
import org.thinkingstudio.obsidianui.option.SpruceSimpleActionOption;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.text.SpruceTextAreaWidget;
|
|
||||||
import net.minecraft.client.toast.SystemToast;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
@@ -34,18 +30,17 @@ import java.nio.file.Files;
|
|||||||
* @since 1.4.3
|
* @since 1.4.3
|
||||||
*/
|
*/
|
||||||
public class MappingsStringInputWidget extends SpruceContainerWidget {
|
public class MappingsStringInputWidget extends SpruceContainerWidget {
|
||||||
private final SpruceOption copyGuidOption;
|
|
||||||
private final SpruceOption reloadMappingsOption;
|
private final SpruceOption reloadMappingsOption;
|
||||||
private String mappings;
|
private String mappings;
|
||||||
private SpruceTextAreaWidget textArea;
|
private SpruceTextAreaWidget textArea;
|
||||||
|
|
||||||
protected MappingsStringInputWidget(Position position, int width, int height) {
|
protected MappingsStringInputWidget(Position position, int width, int height) {
|
||||||
super(position, width, height);
|
super(position, width, height);
|
||||||
|
//super(new TranslatableText("midnightcontrols.menu.title.mappings.string"));
|
||||||
|
|
||||||
this.reloadMappingsOption = ReloadControllerMappingsOption.newOption(btn -> {
|
this.reloadMappingsOption = ReloadControllerMappingsOption.newOption(btn -> {
|
||||||
this.writeMappings();
|
this.writeMappings();
|
||||||
});
|
});
|
||||||
this.copyGuidOption = SpruceSimpleActionOption.of("midnightcontrols.menu.copy_controller_guid", button -> client.keyboard.setClipboard(MidnightControlsConfig.getController().getGuid()));
|
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
@@ -70,7 +65,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
|||||||
if (this.client != null)
|
if (this.client != null)
|
||||||
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.PERIODIC_NOTIFICATION,
|
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.PERIODIC_NOTIFICATION,
|
||||||
Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty()));
|
Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty()));
|
||||||
e.fillInStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,14 +95,10 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
|
|||||||
this.textArea.setDisplayedLines(this.textArea.getInnerHeight() / this.client.textRenderer.fontHeight);
|
this.textArea.setDisplayedLines(this.textArea.getInnerHeight() / this.client.textRenderer.fontHeight);
|
||||||
this.addChild(this.textArea);
|
this.addChild(this.textArea);
|
||||||
|
|
||||||
this.addChild(this.reloadMappingsOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 257));
|
this.addChild(this.reloadMappingsOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 310));
|
||||||
this.addChild(this.copyGuidOption.createWidget(Position.of(this.width / 2 + 105, this.height - 29), 65));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/*public void renderTitle(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||||
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
|
drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 8, 16777215);
|
||||||
super.renderWidget(context, mouseX, mouseY, delta);
|
}*/
|
||||||
context.drawCenteredTextWithShadow(this.client.textRenderer, Text.translatable("midnightcontrols.menu.multiple_mapping_tip"), this.textArea.getX() + this.textArea.getWidth() / 2, this.textArea.getY() + this.textArea.getHeight() - 12, 0x888888);
|
|
||||||
context.drawCenteredTextWithShadow(this.client.textRenderer, Text.translatable("midnightcontrols.menu.current_controller_guid", MidnightControlsConfig.getController().getGuid()), this.textArea.getX() + this.textArea.getWidth() / 2, this.height - 21, 0xFFFFFF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -16,8 +16,7 @@ import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
|||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import net.minecraft.client.render.RenderTickCounter;
|
import dev.lambdaurora.spruceui.hud.Hud;
|
||||||
import org.thinkingstudio.obsidianui.hud.Hud;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
@@ -30,8 +29,6 @@ import net.minecraft.util.hit.HitResult;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the midnightcontrols HUD.
|
* Represents the midnightcontrols HUD.
|
||||||
*
|
*
|
||||||
@@ -40,6 +37,7 @@ import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public class MidnightControlsHud extends Hud {
|
public class MidnightControlsHud extends Hud {
|
||||||
|
private final MidnightControlsClient mod;
|
||||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||||
private int attackWidth = 0;
|
private int attackWidth = 0;
|
||||||
private int attackButtonWidth = 0;
|
private int attackButtonWidth = 0;
|
||||||
@@ -52,13 +50,15 @@ public class MidnightControlsHud extends Hud {
|
|||||||
private boolean showSwapHandsAction = false;
|
private boolean showSwapHandsAction = false;
|
||||||
private int useWidth = 0;
|
private int useWidth = 0;
|
||||||
private int useButtonWidth = 0;
|
private int useButtonWidth = 0;
|
||||||
|
private BlockHitResult placeHitResult;
|
||||||
private String attackAction = "";
|
private String attackAction = "";
|
||||||
private String placeAction = "";
|
private String placeAction = "";
|
||||||
private int ticksDisplayedCrosshair = 0;
|
private int ticksDisplayedCrosshair = 0;
|
||||||
private static boolean isCrammed = false;
|
private static boolean isCrammed = false;
|
||||||
|
|
||||||
public MidnightControlsHud() {
|
public MidnightControlsHud(@NotNull MidnightControlsClient mod) {
|
||||||
super(id("hud/button_indicator"));
|
super(new Identifier(MidnightControlsConstants.NAMESPACE, "hud/button_indicator"));
|
||||||
|
this.mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,7 +79,7 @@ public class MidnightControlsHud extends Hud {
|
|||||||
* Renders the MidnightControls HUD.
|
* Renders the MidnightControls HUD.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void render(DrawContext context, RenderTickCounter tickCounter) {
|
public void render(DrawContext context, float tickDelta) {
|
||||||
if (this.client == null) return;
|
if (this.client == null) return;
|
||||||
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && this.client.currentScreen == null) {
|
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && this.client.currentScreen == null) {
|
||||||
isCrammed = client.getWindow().getScaledWidth() < 520;
|
isCrammed = client.getWindow().getScaledWidth() < 520;
|
||||||
@@ -93,12 +93,12 @@ public class MidnightControlsHud extends Hud {
|
|||||||
matrices.pop();
|
matrices.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MidnightControlsClient.reacharound.isLastReacharoundVertical()) {
|
if (this.mod.reacharound.isLastReacharoundVertical()) {
|
||||||
// Render crosshair indicator.
|
// Render crosshair indicator.
|
||||||
var window = this.client.getWindow();
|
var window = this.client.getWindow();
|
||||||
var text = "[ ]";
|
var text = "[ ]";
|
||||||
|
|
||||||
float scale = Math.min(5, this.ticksDisplayedCrosshair + tickCounter.getTickDelta(true)) / 5F;
|
float scale = Math.min(5, this.ticksDisplayedCrosshair + tickDelta) / 5F;
|
||||||
scale *= scale;
|
scale *= scale;
|
||||||
int opacity = ((int) (255 * scale)) << 24;
|
int opacity = ((int) (255 * scale)) << 24;
|
||||||
|
|
||||||
@@ -119,8 +119,7 @@ public class MidnightControlsHud extends Hud {
|
|||||||
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.dropItemButtonWidth;
|
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.dropItemButtonWidth;
|
||||||
y -= 20;
|
y -= 20;
|
||||||
}
|
}
|
||||||
if (!ButtonBinding.DROP_ITEM.isNotBound() && client.player != null)
|
if (!ButtonBinding.DROP_ITEM.isNotBound()) this.drawButton(context, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
||||||
this.drawButton(context, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderSecondIcons(DrawContext context, int x, int y) {
|
public void renderSecondIcons(DrawContext context, int x, int y) {
|
||||||
@@ -164,7 +163,7 @@ public class MidnightControlsHud extends Hud {
|
|||||||
y -= 20;
|
y -= 20;
|
||||||
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x + this.dropItemButtonWidth + 2 : x - this.dropItemButtonWidth - 2 - this.dropItemWidth;
|
currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x + this.dropItemButtonWidth + 2 : x - this.dropItemButtonWidth - 2 - this.dropItemWidth;
|
||||||
}
|
}
|
||||||
if (!ButtonBinding.DROP_ITEM.isNotBound() && client.player != null) this.drawTip(context, 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(DrawContext context, int x, int y) {
|
public void renderSecondSection(DrawContext context, int x, int y) {
|
||||||
@@ -207,29 +206,28 @@ public class MidnightControlsHud extends Hud {
|
|||||||
String placeAction;
|
String placeAction;
|
||||||
|
|
||||||
// Update "Use" tip status.
|
// Update "Use" tip status.
|
||||||
BlockHitResult placeHitResult;
|
|
||||||
if (this.client.crosshairTarget.getType() == HitResult.Type.MISS) {
|
if (this.client.crosshairTarget.getType() == HitResult.Type.MISS) {
|
||||||
placeHitResult = MidnightControlsClient.reacharound.getLastReacharoundResult();
|
this.placeHitResult = this.mod.reacharound.getLastReacharoundResult();
|
||||||
this.attackAction = "";
|
this.attackAction = "";
|
||||||
this.attackWidth = 0;
|
this.attackWidth = 0;
|
||||||
} else {
|
} else {
|
||||||
if (this.client.crosshairTarget.getType() == HitResult.Type.BLOCK)
|
if (this.client.crosshairTarget.getType() == HitResult.Type.BLOCK)
|
||||||
placeHitResult = (BlockHitResult) this.client.crosshairTarget;
|
this.placeHitResult = (BlockHitResult) this.client.crosshairTarget;
|
||||||
else
|
else
|
||||||
placeHitResult = null;
|
this.placeHitResult = null;
|
||||||
|
|
||||||
this.attackAction = this.client.crosshairTarget.getType() == HitResult.Type.BLOCK ? "midnightcontrols.action.hit" : ButtonBinding.ATTACK.getTranslationKey();
|
this.attackAction = this.client.crosshairTarget.getType() == HitResult.Type.BLOCK ? "midnightcontrols.action.hit" : ButtonBinding.ATTACK.getTranslationKey();
|
||||||
this.attackWidth = this.width(attackAction);
|
this.attackWidth = this.width(attackAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MidnightControlsClient.reacharound.isLastReacharoundVertical()) {
|
if (this.mod.reacharound.isLastReacharoundVertical()) {
|
||||||
if (this.ticksDisplayedCrosshair < 5)
|
if (this.ticksDisplayedCrosshair < 5)
|
||||||
this.ticksDisplayedCrosshair++;
|
this.ticksDisplayedCrosshair++;
|
||||||
} else {
|
} else {
|
||||||
this.ticksDisplayedCrosshair = 0;
|
this.ticksDisplayedCrosshair = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var customAttackAction = MidnightControlsCompat.getAttackActionAt(this.client, placeHitResult);
|
var customAttackAction = MidnightControlsCompat.getAttackActionAt(this.client, this.placeHitResult);
|
||||||
if (customAttackAction != null) {
|
if (customAttackAction != null) {
|
||||||
this.attackAction = customAttackAction;
|
this.attackAction = customAttackAction;
|
||||||
this.attackWidth = this.width(customAttackAction);
|
this.attackWidth = this.width(customAttackAction);
|
||||||
@@ -244,14 +242,14 @@ public class MidnightControlsHud extends Hud {
|
|||||||
if (stack == null || stack.isEmpty()) {
|
if (stack == null || stack.isEmpty()) {
|
||||||
placeAction = "";
|
placeAction = "";
|
||||||
} else {
|
} else {
|
||||||
if (placeHitResult != null && stack.getItem() instanceof BlockItem) {
|
if (this.placeHitResult != null && stack.getItem() instanceof BlockItem) {
|
||||||
placeAction = "midnightcontrols.action.place";
|
placeAction = "midnightcontrols.action.place";
|
||||||
} else {
|
} else {
|
||||||
placeAction = ButtonBinding.USE.getTranslationKey();
|
placeAction = ButtonBinding.USE.getTranslationKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var customUseAction = MidnightControlsCompat.getUseActionAt(this.client, placeHitResult);
|
var customUseAction = MidnightControlsCompat.getUseActionAt(this.client, this.placeHitResult);
|
||||||
if (customUseAction != null)
|
if (customUseAction != null)
|
||||||
placeAction = customUseAction;
|
placeAction = customUseAction;
|
||||||
|
|
||||||
@@ -10,33 +10,21 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import eu.midnightdust.midnightcontrols.ControlsMode;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
|
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
import eu.midnightdust.midnightcontrols.client.MidnightInput;
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.DrawContextAccessor;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.font.TextRenderer;
|
import net.minecraft.client.font.TextRenderer;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.render.*;
|
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.client.texture.Sprite;
|
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.math.ColorHelper;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.joml.Matrix4f;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the midnightcontrols renderer.
|
* Represents the midnightcontrols renderer.
|
||||||
*
|
*
|
||||||
@@ -174,7 +162,7 @@ public class MidnightControlsRenderer {
|
|||||||
int assetSize = axis || (button >= 15 && button <= 18) ? AXIS_SIZE : BUTTON_SIZE;
|
int assetSize = axis || (button >= 15 && button <= 18) ? AXIS_SIZE : BUTTON_SIZE;
|
||||||
|
|
||||||
RenderSystem.setShaderColor(1.f, second ? 0.f : 1.f, 1.f, 1.f);
|
RenderSystem.setShaderColor(1.f, second ? 0.f : 1.f, 1.f, 1.f);
|
||||||
context.drawTexture(RenderLayer::getGuiTextured, axis ? MidnightControlsClient.CONTROLLER_AXIS : button >= 15 && button <= 19 ? MidnightControlsClient.CONTROLLER_EXPANDED :MidnightControlsClient.CONTROLLER_BUTTONS
|
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),
|
, x + (ICON_SIZE / 2 - assetSize / 2), y + (ICON_SIZE / 2 - assetSize / 2),
|
||||||
(float) buttonOffset, (float) (controllerType * assetSize),
|
(float) buttonOffset, (float) (controllerType * assetSize),
|
||||||
assetSize, assetSize,
|
assetSize, assetSize,
|
||||||
@@ -204,28 +192,14 @@ public class MidnightControlsRenderer {
|
|||||||
private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer) {
|
private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer) {
|
||||||
return 15 + 5 + textRenderer.getWidth(action);
|
return 15 + 5 + textRenderer.getWidth(action);
|
||||||
}
|
}
|
||||||
public static void renderWaylandCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
|
|
||||||
if (MidnightControlsConfig.virtualMouse || client.currentScreen == null || MidnightControlsConfig.controlsMode != ControlsMode.CONTROLLER) return;
|
|
||||||
|
|
||||||
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
|
|
||||||
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
|
|
||||||
|
|
||||||
try {
|
|
||||||
Identifier spritePath = MidnightControlsClient.WAYLAND_CURSOR_TEXTURE_LIGHT;
|
|
||||||
if (MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.DEFAULT_DARK || MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.SECOND_DARK)
|
|
||||||
spritePath = MidnightControlsClient.WAYLAND_CURSOR_TEXTURE_DARK;
|
|
||||||
Sprite sprite = client.getGuiAtlasManager().getSprite(spritePath);
|
|
||||||
drawUnalignedTexturedQuad(RenderLayer::getGuiTextured, sprite.getAtlasId(), context, mouseX, mouseX + 8, mouseY, mouseY + 8, 999, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
|
|
||||||
} catch (IllegalStateException ignored) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void renderVirtualCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
|
public static void renderVirtualCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
|
||||||
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|
||||||
|| MidnightInput.isScreenInteractive(client.currentScreen)))
|
|| MidnightInput.isScreenInteractive(client.currentScreen)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
|
int mouseX = (int) (client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
|
||||||
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
|
int mouseY = (int) (client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
|
||||||
|
|
||||||
boolean hoverSlot = false;
|
boolean hoverSlot = false;
|
||||||
|
|
||||||
@@ -242,8 +216,8 @@ public class MidnightControlsRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hoverSlot && client.currentScreen != null) {
|
if (!hoverSlot) {
|
||||||
var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, (int) mouseX, (int) mouseY);
|
var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, mouseX, mouseY);
|
||||||
|
|
||||||
if (slot != null) {
|
if (slot != null) {
|
||||||
mouseX = slot.x();
|
mouseX = slot.x();
|
||||||
@@ -257,22 +231,32 @@ public class MidnightControlsRenderer {
|
|||||||
mouseY -= 8;
|
mouseY -= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
//context.getMatrices().push();
|
||||||
Sprite sprite = client.getGuiAtlasManager().getSprite(id(MidnightControlsConfig.virtualMouseSkin.getSpritePath() + (hoverSlot ? "_slot" : "")));
|
context.getMatrices().translate(0f, 0f, 999f);
|
||||||
drawUnalignedTexturedQuad(RenderLayer::getGuiTextured, sprite.getAtlasId(), context, mouseX, mouseX + 16, mouseY, mouseY + 16, 999, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
|
drawCursor(context, mouseX, mouseY, hoverSlot, client);
|
||||||
} catch (IllegalStateException ignored) {}
|
//context.getMatrices().pop();
|
||||||
}
|
}
|
||||||
private static void drawUnalignedTexturedQuad(Function<Identifier, RenderLayer> renderLayers, Identifier texture, DrawContext context, float x1, float x2, float y1, float y2, float z, float u1, float u2, float v1, float v2) {
|
|
||||||
RenderLayer renderLayer = renderLayers.apply(texture);
|
/**
|
||||||
//RenderSystem.setShaderTexture(0, texture);
|
* Draws the virtual cursor.
|
||||||
Matrix4f matrix4f = context.getMatrices().peek().getPositionMatrix();
|
*
|
||||||
//BufferBuilder bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE);
|
* @param context the context
|
||||||
VertexConsumer vertexConsumer = ((DrawContextAccessor)context).getVertexConsumers().getBuffer(renderLayer);
|
* @param x x coordinate
|
||||||
vertexConsumer.vertex(matrix4f, x1, y1, z).texture(u1, v1).color(ColorHelper.getWhite(1.0f));
|
* @param y y coordinate
|
||||||
vertexConsumer.vertex(matrix4f, x1, y2, z).texture(u1, v2).color(ColorHelper.getWhite(1.0f));
|
* @param hoverSlot true if hovering a slot, else false
|
||||||
vertexConsumer.vertex(matrix4f, x2, y2, z).texture(u2, v2).color(ColorHelper.getWhite(1.0f));
|
* @param client the client instance
|
||||||
vertexConsumer.vertex(matrix4f, x2, y1, z).texture(u2, v1).color(ColorHelper.getWhite(1.0f));
|
*/
|
||||||
|
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);
|
||||||
|
context.fill(1, 1, x, y, 0xFFFFFF);
|
||||||
context.draw();
|
context.draw();
|
||||||
|
//RenderSystem.enableDepthTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ButtonSize(int length, int height) {
|
public record ButtonSize(int length, int height) {
|
||||||
@@ -10,27 +10,24 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
import dev.lambdaurora.spruceui.background.Background;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
import dev.lambdaurora.spruceui.widget.SpruceWidget;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
|
||||||
import org.thinkingstudio.obsidianui.background.Background;
|
|
||||||
import org.thinkingstudio.obsidianui.mixin.DrawContextAccessor;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.SpruceWidget;
|
|
||||||
import eu.midnightdust.lib.util.MidnightColorUtil;
|
import eu.midnightdust.lib.util.MidnightColorUtil;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControls;
|
import eu.midnightdust.midnightcontrols.MidnightControls;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
|
||||||
import org.thinkingstudio.obsidianui.Position;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import org.thinkingstudio.obsidianui.SpruceTexts;
|
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||||
import org.thinkingstudio.obsidianui.option.*;
|
import dev.lambdaurora.spruceui.option.*;
|
||||||
import org.thinkingstudio.obsidianui.screen.SpruceScreen;
|
import dev.lambdaurora.spruceui.screen.SpruceScreen;
|
||||||
import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget;
|
import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget;
|
||||||
import org.thinkingstudio.obsidianui.widget.SpruceLabelWidget;
|
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
|
||||||
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||||
import org.thinkingstudio.obsidianui.widget.container.SpruceOptionListWidget;
|
import dev.lambdaurora.spruceui.widget.container.SpruceOptionListWidget;
|
||||||
import org.thinkingstudio.obsidianui.widget.container.tabbed.SpruceTabbedWidget;
|
import dev.lambdaurora.spruceui.widget.container.tabbed.SpruceTabbedWidget;
|
||||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
@@ -53,6 +50,7 @@ import java.awt.*;
|
|||||||
public class MidnightControlsSettingsScreen extends SpruceScreen {
|
public class MidnightControlsSettingsScreen extends SpruceScreen {
|
||||||
private static final Text SDL2_GAMEPAD_TOOL = Text.literal("SDL2 Gamepad Tool").formatted(Formatting.GREEN);
|
private static final Text SDL2_GAMEPAD_TOOL = Text.literal("SDL2 Gamepad Tool").formatted(Formatting.GREEN);
|
||||||
public static final String GAMEPAD_TOOL_URL = "https://generalarcade.com/gamepadtool/";
|
public static final String GAMEPAD_TOOL_URL = "https://generalarcade.com/gamepadtool/";
|
||||||
|
final MidnightControlsClient mod = MidnightControlsClient.get();
|
||||||
private final Screen parent;
|
private final Screen parent;
|
||||||
// General options
|
// General options
|
||||||
private final SpruceOption inputModeOption;
|
private final SpruceOption inputModeOption;
|
||||||
@@ -94,7 +92,6 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
id = GLFW.GLFW_JOYSTICK_1;
|
id = GLFW.GLFW_JOYSTICK_1;
|
||||||
id = searchNextAvailableController(id, false);
|
id = searchNextAvailableController(id, false);
|
||||||
MidnightControlsConfig.setController(Controller.byId(id));
|
MidnightControlsConfig.setController(Controller.byId(id));
|
||||||
if (MidnightControlsConfig.debug) System.out.println(Controller.byId(id).getName() + "'s Controller GUID: " + Controller.byId(id).getGuid());
|
|
||||||
},
|
},
|
||||||
option -> {
|
option -> {
|
||||||
var controller = MidnightControlsConfig.getController();
|
var controller = MidnightControlsConfig.getController();
|
||||||
@@ -162,9 +159,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
private static int searchNextAvailableController(int newId, boolean allowNone) {
|
private static int searchNextAvailableController(int newId, boolean allowNone) {
|
||||||
if ((allowNone && newId == -1) || newId == 0) return newId;
|
if ((allowNone && newId == -1) || newId == 0) return newId;
|
||||||
|
|
||||||
Controller candidate = Controller.byId(newId);
|
boolean connected = Controller.byId(newId).isConnected();
|
||||||
boolean connected = candidate.isConnected();
|
|
||||||
if (MidnightControlsConfig.excludedControllers.stream().anyMatch(exclusion -> candidate.getName().matches(exclusion))) connected = false;
|
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
newId++;
|
newId++;
|
||||||
}
|
}
|
||||||
@@ -187,7 +182,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
MidnightControlsConfig.save();
|
MidnightControlsConfig.save();
|
||||||
|
|
||||||
if (this.client != null && this.client.player != null) {
|
if (this.client != null && this.client.player != null) {
|
||||||
NetworkUtil.sendPayloadC2S(new ControlsModePayload(next.getName()));
|
ClientPlayNetworking.getSender().sendPacket(MidnightControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next));
|
||||||
}
|
}
|
||||||
}, option -> option.getDisplayText(Text.translatable(MidnightControlsConfig.controlsMode.getTranslationKey())),
|
}, option -> option.getDisplayText(Text.translatable(MidnightControlsConfig.controlsMode.getTranslationKey())),
|
||||||
Text.translatable("midnightcontrols.menu.controls_mode.tooltip"));
|
Text.translatable("midnightcontrols.menu.controls_mode.tooltip"));
|
||||||
@@ -219,7 +214,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
var client = MinecraftClient.getInstance();
|
var client = MinecraftClient.getInstance();
|
||||||
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
|
||||||
});
|
});
|
||||||
this.advancedConfigOption = SpruceSimpleActionOption.of("midnightcontrols.midnightconfig.title", button -> client.setScreen(MidnightControlsConfig.getScreen(this, MidnightControlsConstants.NAMESPACE)));
|
this.advancedConfigOption = SpruceSimpleActionOption.of("midnightcontrols.midnightconfig.title", button -> client.setScreen(MidnightControlsConfig.getScreen(this, "midnightcontrols")));
|
||||||
// Gameplay options
|
// Gameplay options
|
||||||
this.analogMovementOption = new SpruceToggleBooleanOption("midnightcontrols.menu.analog_movement",
|
this.analogMovementOption = new SpruceToggleBooleanOption("midnightcontrols.menu.analog_movement",
|
||||||
() -> MidnightControlsConfig.analogMovement, value -> MidnightControlsConfig.analogMovement = value,
|
() -> MidnightControlsConfig.analogMovement, value -> MidnightControlsConfig.analogMovement = value,
|
||||||
@@ -257,7 +252,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
option -> option.getDisplayText(MidnightControlsConfig.virtualMouseSkin.getTranslatedText()),
|
option -> option.getDisplayText(MidnightControlsConfig.virtualMouseSkin.getTranslatedText()),
|
||||||
null);
|
null);
|
||||||
this.hudEnableOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hud_enable", () -> MidnightControlsConfig.hudEnable,
|
this.hudEnableOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hud_enable", () -> MidnightControlsConfig.hudEnable,
|
||||||
MidnightControlsClient::setHudEnabled, Text.translatable("midnightcontrols.menu.hud_enable.tooltip"));
|
this.mod::setHudEnabled, Text.translatable("midnightcontrols.menu.hud_enable.tooltip"));
|
||||||
this.hudSideOption = new SpruceCyclingOption("midnightcontrols.menu.hud_side",
|
this.hudSideOption = new SpruceCyclingOption("midnightcontrols.menu.hud_side",
|
||||||
amount -> MidnightControlsConfig.hudSide = MidnightControlsConfig.hudSide.next(),
|
amount -> MidnightControlsConfig.hudSide = MidnightControlsConfig.hudSide.next(),
|
||||||
option -> option.getDisplayText(MidnightControlsConfig.hudSide.getTranslatedText()),
|
option -> option.getDisplayText(MidnightControlsConfig.hudSide.getTranslatedText()),
|
||||||
@@ -274,7 +269,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
MidnightControlsConfig.updateBindingsForController(MidnightControlsConfig.getController());
|
MidnightControlsConfig.updateBindingsForController(MidnightControlsConfig.getController());
|
||||||
}
|
}
|
||||||
|
|
||||||
}, Text.empty());
|
}, Text.translatable(""));
|
||||||
this.cameraModeOption = new SpruceCyclingOption("midnightcontrols.menu.camera_mode",
|
this.cameraModeOption = new SpruceCyclingOption("midnightcontrols.menu.camera_mode",
|
||||||
amount -> MidnightControlsConfig.cameraMode = MidnightControlsConfig.cameraMode.next(),
|
amount -> MidnightControlsConfig.cameraMode = MidnightControlsConfig.cameraMode.next(),
|
||||||
option -> option.getDisplayText(MidnightControlsConfig.cameraMode.getTranslatedText()),
|
option -> option.getDisplayText(MidnightControlsConfig.cameraMode.getTranslatedText()),
|
||||||
@@ -502,24 +497,28 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void render(DrawContext context, SpruceWidget widget, int vOffset, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, SpruceWidget widget, int vOffset, int mouseX, int mouseY, float delta) {
|
||||||
fill(context, widget.getX(), widget.getY(), widget.getX() + widget.getWidth(), widget.getY() + widget.getHeight(), Color.black);
|
fill(context.getMatrices(), widget.getX(), widget.getY(), widget.getX() + widget.getWidth(), widget.getY() + widget.getHeight(), MidnightColorUtil.hex2Rgb("#000000"));
|
||||||
}
|
}
|
||||||
private static void fill(DrawContext context, int x2, int y2, int x1, int y1, Color color) {
|
private static void fill(MatrixStack matrixStack, int x2, int y2, int x1, int y1, Color color) {
|
||||||
RenderLayer renderLayer = RenderLayer.getGui();
|
matrixStack.push();
|
||||||
VertexConsumer vertexConsumer = ((DrawContextAccessor)context).getVertexConsumers().getBuffer(renderLayer);
|
|
||||||
|
|
||||||
|
Matrix4f matrix = matrixStack.peek().getPositionMatrix();
|
||||||
float r = (float)(color.getRed()) / 255.0F;
|
float r = (float)(color.getRed()) / 255.0F;
|
||||||
float g = (float)(color.getGreen()) / 255.0F;
|
float g = (float)(color.getGreen()) / 255.0F;
|
||||||
float b = (float)(color.getBlue()) / 255.0F;
|
float b = (float)(color.getBlue()) / 255.0F;
|
||||||
float t = (float)(transparency) / 255.0F;
|
float t = (float)(transparency) / 255.0F;
|
||||||
|
BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
|
||||||
RenderSystem.enableBlend();
|
RenderSystem.enableBlend();
|
||||||
RenderSystem.defaultBlendFunc();
|
RenderSystem.defaultBlendFunc();
|
||||||
vertexConsumer.vertex((float)x1, (float)y2, 0.0F).color(r, g, b, t);
|
RenderSystem.setShader(GameRenderer::getPositionColorProgram);
|
||||||
vertexConsumer.vertex((float)x2, (float)y2, 0.0F).color(r, g, b, t);
|
bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
|
||||||
vertexConsumer.vertex((float)x2, (float)y1, 0.0F).color(r, g, b, t);
|
bufferBuilder.vertex(matrix, (float)x1, (float)y2, 0.0F).color(r, g, b, t).next();
|
||||||
vertexConsumer.vertex((float)x1, (float)y1, 0.0F).color(r, g, b, t);
|
bufferBuilder.vertex(matrix, (float)x2, (float)y2, 0.0F).color(r, g, b, t).next();
|
||||||
|
bufferBuilder.vertex(matrix, (float)x2, (float)y1, 0.0F).color(r, g, b, t).next();
|
||||||
|
bufferBuilder.vertex(matrix, (float)x1, (float)y1, 0.0F).color(r, g, b, t).next();
|
||||||
|
BufferRenderer.drawWithGlobalProgram(bufferBuilder.end());
|
||||||
RenderSystem.disableBlend();
|
RenderSystem.disableBlend();
|
||||||
context.draw();
|
matrixStack.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
import eu.midnightdust.midnightcontrols.client.controller.Controller;
|
||||||
import org.thinkingstudio.obsidianui.option.SpruceSimpleActionOption;
|
import dev.lambdaurora.spruceui.option.SpruceSimpleActionOption;
|
||||||
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.toast.SystemToast;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
@@ -17,8 +17,6 @@ import net.minecraft.client.gui.screen.Screen;
|
|||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.ring;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the controls ring screen.
|
* Represents the controls ring screen.
|
||||||
*
|
*
|
||||||
@@ -27,17 +25,19 @@ import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.rin
|
|||||||
* @since 1.4.3
|
* @since 1.4.3
|
||||||
*/
|
*/
|
||||||
public class RingScreen extends Screen {
|
public class RingScreen extends Screen {
|
||||||
|
protected final MidnightControlsClient mod;
|
||||||
|
|
||||||
public RingScreen() {
|
public RingScreen() {
|
||||||
super(Text.literal("midnightcontrols.menu.title.ring"));
|
super(Text.literal("midnightcontrols.menu.title.ring"));
|
||||||
|
this.mod = MidnightControlsClient.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
super.init();
|
super.init();
|
||||||
if (ring.getMaxPages() > 1) {
|
if (mod.ring.getMaxPages() > 1) {
|
||||||
this.addDrawableChild(ButtonWidget.builder(Text.of("◀"), button -> ring.cyclePage(false)).dimensions(5, 5, 20, 20).build());
|
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 -> ring.cyclePage(true)).dimensions(width - 25, 5, 20, 20).build());
|
this.addDrawableChild(ButtonWidget.builder(Text.of("▶"), button -> this.mod.ring.cyclePage(true)).dimensions(width - 25, 5, 20, 20).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public class RingScreen extends Screen {
|
|||||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
super.render(context, mouseX, mouseY, delta);
|
super.render(context, mouseX, mouseY, delta);
|
||||||
|
|
||||||
RingPage page = ring.getCurrentPage();
|
RingPage page = this.mod.ring.getCurrentPage();
|
||||||
page.render(context, this.textRenderer, this.width, this.height, mouseX, mouseY, delta);
|
page.render(context, this.textRenderer, this.width, this.height, mouseX, mouseY, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ public class RingScreen extends Screen {
|
|||||||
super.close();
|
super.close();
|
||||||
assert client != null;
|
assert client != null;
|
||||||
client.currentScreen = null;
|
client.currentScreen = null;
|
||||||
RingPage page = ring.getCurrentPage();
|
RingPage page = this.mod.ring.getCurrentPage();
|
||||||
if (RingPage.selected >= 0 && page.actions[RingPage.selected] != null)
|
if (RingPage.selected >= 0 && page.actions[RingPage.selected] != null)
|
||||||
page.actions[RingPage.selected].activate(RingButtonMode.PRESS);
|
page.actions[RingPage.selected].activate(RingButtonMode.PRESS);
|
||||||
RingPage.selected = -1;
|
RingPage.selected = -1;
|
||||||
@@ -80,7 +80,7 @@ public class RingScreen extends Screen {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||||
if (ring.getCurrentPage().onClick(width, height, (int) mouseX, (int) mouseY)) {
|
if (mod.ring.getCurrentPage().onClick(width, height, (int) mouseX, (int) mouseY)) {
|
||||||
this.close();
|
this.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -7,48 +7,41 @@
|
|||||||
* see the LICENSE file.
|
* see the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.touch.gui;
|
package eu.midnightdust.midnightcontrols.client.gui;
|
||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
|
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||||
import net.minecraft.client.gui.screen.ChatScreen;
|
|
||||||
import net.minecraft.client.gui.screen.GameMenuScreen;
|
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
|
||||||
import net.minecraft.item.ArmorItem;
|
|
||||||
import net.minecraft.item.consume.UseAction;
|
|
||||||
import net.minecraft.util.Arm;
|
|
||||||
import net.minecraft.util.Hand;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import org.thinkingstudio.obsidianui.Position;
|
|
||||||
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
|
||||||
import eu.midnightdust.lib.util.PlatformFunctions;
|
import eu.midnightdust.lib.util.PlatformFunctions;
|
||||||
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
|
||||||
import eu.midnightdust.midnightcontrols.client.enums.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.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
|
import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.gui.widget.TextIconButtonWidget;
|
||||||
|
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.touch.TouchUtils;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
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.screen.ingame.InventoryScreen;
|
||||||
import net.minecraft.client.gui.widget.TextIconButtonWidget;
|
|
||||||
import net.minecraft.client.option.KeyBinding;
|
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.client.util.InputUtil;
|
||||||
|
import net.minecraft.item.*;
|
||||||
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.*;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.input;
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X;
|
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X;
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
|
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
|
||||||
|
|
||||||
@@ -56,7 +49,8 @@ import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
|
|||||||
* Represents the touchscreen overlay
|
* Represents the touchscreen overlay
|
||||||
*/
|
*/
|
||||||
public class TouchscreenOverlay extends Screen {
|
public class TouchscreenOverlay extends Screen {
|
||||||
public static final Identifier WIDGETS_LOCATION = id("textures/gui/widgets.png");
|
public static final Identifier WIDGETS_LOCATION = new Identifier("midnightcontrols", "textures/gui/widgets.png");
|
||||||
|
private final MidnightControlsClient mod;
|
||||||
private SilentTexturedButtonWidget inventoryButton;
|
private SilentTexturedButtonWidget inventoryButton;
|
||||||
private SilentTexturedButtonWidget swapHandsButton;
|
private SilentTexturedButtonWidget swapHandsButton;
|
||||||
private SilentTexturedButtonWidget dropButton;
|
private SilentTexturedButtonWidget dropButton;
|
||||||
@@ -75,9 +69,11 @@ public class TouchscreenOverlay extends Screen {
|
|||||||
private SilentTexturedButtonWidget endSneakButton;
|
private SilentTexturedButtonWidget endSneakButton;
|
||||||
private int flyButtonEnableTicks = 0;
|
private int flyButtonEnableTicks = 0;
|
||||||
private int forwardButtonTick = 0;
|
private int forwardButtonTick = 0;
|
||||||
|
public static TouchscreenOverlay instance;
|
||||||
|
|
||||||
public TouchscreenOverlay() {
|
public TouchscreenOverlay(@NotNull MidnightControlsClient mod) {
|
||||||
super(Text.literal("Touchscreen Overlay"));
|
super(Text.literal("Touchscreen overlay"));
|
||||||
|
this.mod = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,7 +82,7 @@ public class TouchscreenOverlay extends Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {}
|
public void renderBackground(DrawContext context) {}
|
||||||
|
|
||||||
private void pauseGame() {
|
private void pauseGame() {
|
||||||
assert this.client != null;
|
assert this.client != null;
|
||||||
@@ -167,15 +163,15 @@ public class TouchscreenOverlay extends Screen {
|
|||||||
int emoteOffset = 0;
|
int emoteOffset = 0;
|
||||||
if (PlatformFunctions.isModLoaded("emotecraft")) {
|
if (PlatformFunctions.isModLoaded("emotecraft")) {
|
||||||
emoteOffset = 10;
|
emoteOffset = 10;
|
||||||
TextIconButtonWidget emoteButton = TextIconButtonWidget.builder(Text.empty(), btn -> EmotecraftCompat.openEmotecraftScreen(this), true).width(20).texture(id("touch/emote"), 20, 20).build();
|
TextIconButtonWidget emoteButton = TextIconButtonWidget.builder(Text.empty(), btn -> EmotecraftCompat.openEmotecraftScreen(this), true).width(20).texture(new Identifier(MidnightControlsConstants.NAMESPACE, "touch/emote"), 20, 20).build();
|
||||||
emoteButton.setPosition(scaledWidth / 2 - 30, 0);
|
emoteButton.setPosition(scaledWidth / 2 - 30, 0);
|
||||||
this.addDrawableChild(emoteButton);
|
this.addDrawableChild(emoteButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextIconButtonWidget chatButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.client.setScreen(new ChatScreen("")), true).width(20).texture(id("touch/chat"), 20, 20).build();
|
TextIconButtonWidget chatButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.client.setScreen(new ChatScreen("")), true).width(20).texture(new Identifier(MidnightControlsConstants.NAMESPACE, "touch/chat"), 20, 20).build();
|
||||||
chatButton.setPosition(scaledWidth / 2 - 20 + emoteOffset, 0);
|
chatButton.setPosition(scaledWidth / 2 - 20 + emoteOffset, 0);
|
||||||
this.addDrawableChild(chatButton);
|
this.addDrawableChild(chatButton);
|
||||||
TextIconButtonWidget pauseButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.pauseGame(), true).width(20).texture(id("touch/pause"), 20, 20).build();
|
TextIconButtonWidget pauseButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.pauseGame(), true).width(20).texture(new Identifier(MidnightControlsConstants.NAMESPACE, "touch/pause"), 20, 20).build();
|
||||||
pauseButton.setPosition(scaledWidth / 2 + emoteOffset, 0);
|
pauseButton.setPosition(scaledWidth / 2 + emoteOffset, 0);
|
||||||
this.addDrawableChild(pauseButton);
|
this.addDrawableChild(pauseButton);
|
||||||
// Inventory buttons.
|
// Inventory buttons.
|
||||||
@@ -286,20 +282,20 @@ public class TouchscreenOverlay extends Screen {
|
|||||||
initCustomButtons(false);
|
initCustomButtons(false);
|
||||||
|
|
||||||
this.setButtonProperties(MidnightControlsConfig.touchTransparency / 100f);
|
this.setButtonProperties(MidnightControlsConfig.touchTransparency / 100f);
|
||||||
|
TouchscreenOverlay.instance = this;
|
||||||
}
|
}
|
||||||
private void initCustomButtons(boolean left) {
|
private void initCustomButtons(boolean left) {
|
||||||
assert client != null;
|
assert client != null;
|
||||||
Identifier emptySprite = id("touch/empty");
|
Identifier emptySprite = new Identifier(MidnightControlsConstants.NAMESPACE, "touch/empty");
|
||||||
List<String> list = left ? MidnightControlsConfig.leftTouchBinds : MidnightControlsConfig.rightTouchBinds;
|
List<String> list = left ? MidnightControlsConfig.leftTouchBinds : MidnightControlsConfig.rightTouchBinds;
|
||||||
Sprite missingSprite = client.getGuiAtlasManager().getSprite(MissingSprite.getMissingSpriteId());
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
String bindName = list.get(i);
|
String bindName = list.get(i);
|
||||||
ButtonBinding binding = InputManager.getBinding(bindName);
|
ButtonBinding binding = InputManager.getBinding(bindName);
|
||||||
if (binding == null) continue;
|
if (binding == null) continue;
|
||||||
boolean hasTexture = client.getGuiAtlasManager().getSprite(id("binding/"+bindName)) != missingSprite;
|
boolean hasTexture = client.getTextureManager().getOrDefault(new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName), null) != null;
|
||||||
if (MidnightControlsConfig.debug) System.out.println(left +" "+id("binding/"+bindName)+" "+ hasTexture);
|
if (MidnightControlsConfig.debug) System.out.println(left +" "+new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName)+" "+ hasTexture);
|
||||||
var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> binding.handle(client, 1, ButtonState.PRESS), hasTexture)
|
var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> binding.handle(client, 1, ButtonState.PRESS), hasTexture)
|
||||||
.texture(hasTexture ? id("binding/"+bindName) : emptySprite, 20, 20).dimension(20, 20).build();
|
.texture(hasTexture ? new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName) : emptySprite, 20, 20).dimension(20, 20).build();
|
||||||
button.setPosition(left ? (3+(i*23)) : this.width-(23+(i*23)), 3);
|
button.setPosition(left ? (3+(i*23)) : this.width-(23+(i*23)), 3);
|
||||||
button.setAlpha(MidnightControlsConfig.touchTransparency / 100f);
|
button.setAlpha(MidnightControlsConfig.touchTransparency / 100f);
|
||||||
this.addDrawableChild(button);
|
this.addDrawableChild(button);
|
||||||
@@ -347,15 +343,17 @@ public class TouchscreenOverlay extends Screen {
|
|||||||
@Override
|
@Override
|
||||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||||
if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) {
|
if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) {
|
||||||
if (TouchInput.isDragging) {
|
if (!MidnightControlsConfig.invertTouch) {
|
||||||
if (!MidnightControlsConfig.invertTouch) {
|
deltaX = -deltaX;
|
||||||
deltaX = -deltaX;
|
deltaY = -deltaY;
|
||||||
deltaY = -deltaY;
|
|
||||||
}
|
|
||||||
input.handleTouchscreenLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) deltaY, 0.25d));
|
|
||||||
input.handleTouchscreenLook(AxisStorage.of(GLFW_GAMEPAD_AXIS_RIGHT_X, (float) deltaX, 0.25d));
|
|
||||||
}
|
}
|
||||||
else TouchInput.isDragging = true;
|
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);
|
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||||
}
|
}
|
||||||
@@ -365,4 +363,11 @@ public class TouchscreenOverlay extends Screen {
|
|||||||
super.keyPressed(keyCode,scanCode,modifiers);
|
super.keyPressed(keyCode,scanCode,modifiers);
|
||||||
return true;
|
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,9 +11,9 @@ package eu.midnightdust.midnightcontrols.client.gui.widget;
|
|||||||
|
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
|
||||||
import org.thinkingstudio.obsidianui.Position;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import org.thinkingstudio.obsidianui.SpruceTexts;
|
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||||
import org.thinkingstudio.obsidianui.widget.AbstractSpruceIconButtonWidget;
|
import dev.lambdaurora.spruceui.widget.AbstractSpruceIconButtonWidget;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
@@ -9,13 +9,14 @@
|
|||||||
|
|
||||||
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
package eu.midnightdust.midnightcontrols.client.gui.widget;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||||
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
|
||||||
import org.thinkingstudio.obsidianui.Position;
|
import dev.lambdaurora.spruceui.Position;
|
||||||
import org.thinkingstudio.obsidianui.SpruceTexts;
|
import dev.lambdaurora.spruceui.SpruceTexts;
|
||||||
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
|
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
|
||||||
import org.thinkingstudio.obsidianui.widget.container.SpruceContainerWidget;
|
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
||||||
@@ -30,6 +31,8 @@ import java.util.stream.Collectors;
|
|||||||
* Represents the controls screen.
|
* Represents the controls screen.
|
||||||
*/
|
*/
|
||||||
public class ControllerControlsWidget extends SpruceContainerWidget {
|
public class ControllerControlsWidget extends SpruceContainerWidget {
|
||||||
|
final MidnightControlsClient mod;
|
||||||
|
private ControlsListWidget bindingsListWidget;
|
||||||
private SpruceButtonWidget resetButton;
|
private SpruceButtonWidget resetButton;
|
||||||
public ButtonBinding focusedBinding;
|
public ButtonBinding focusedBinding;
|
||||||
public boolean waiting = false;
|
public boolean waiting = false;
|
||||||
@@ -37,6 +40,7 @@ public class ControllerControlsWidget extends SpruceContainerWidget {
|
|||||||
|
|
||||||
public ControllerControlsWidget(Position position, int width, int height) {
|
public ControllerControlsWidget(Position position, int width, int height) {
|
||||||
super(position, width, height);
|
super(position, width, height);
|
||||||
|
this.mod = MidnightControlsClient.get();
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
@@ -45,9 +49,9 @@ public class ControllerControlsWidget extends SpruceContainerWidget {
|
|||||||
this.addChild(new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, 18), 310, 20,
|
this.addChild(new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, 18), 310, 20,
|
||||||
Text.translatable("midnightcontrols.menu.keyboard_controls"),
|
Text.translatable("midnightcontrols.menu.keyboard_controls"),
|
||||||
btn -> this.client.setScreen(new ControlsOptionsScreen(null, this.client.options))));
|
btn -> this.client.setScreen(new ControlsOptionsScreen(null, this.client.options))));
|
||||||
ControlsListWidget bindingsListWidget = new ControlsListWidget(Position.of(this, 0, 43), this.width, this.height - 43 - 35, this);
|
this.bindingsListWidget = new ControlsListWidget(Position.of(this, 0, 43), this.width, this.height - 43 - 35, this);
|
||||||
bindingsListWidget.setBackground(new MidnightControlsSettingsScreen.MidnightControlsBackground(130));
|
this.bindingsListWidget.setBackground(new MidnightControlsSettingsScreen.MidnightControlsBackground(130));
|
||||||
this.addChild(bindingsListWidget);
|
this.addChild(this.bindingsListWidget);
|
||||||
this.addChild(this.resetButton = new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, this.height - 29), 150, 20,
|
this.addChild(this.resetButton = new SpruceButtonWidget(Position.of(this, this.width / 2 - 155, this.height - 29), 150, 20,
|
||||||
SpruceTexts.CONTROLS_RESET_ALL,
|
SpruceTexts.CONTROLS_RESET_ALL,
|
||||||
btn -> InputManager.streamBindings().collect(Collectors.toSet()).forEach(binding -> MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton()))));
|
btn -> InputManager.streamBindings().collect(Collectors.toSet()).forEach(binding -> MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton()))));
|
||||||