Compare commits

..

3 Commits

Author SHA1 Message Date
LambdAurora
bb19ea4da5 Fix buildscript for Modrinth publishing. 2021-06-23 14:32:20 +02:00
LambdAurora
a1773cc0d9 Quick fix. 2021-06-23 14:24:49 +02:00
LambdAurora
e652390583 LambdaControls 1.7.0: update to 1.17. 2021-06-23 14:18:20 +02:00
69 changed files with 1198 additions and 1118 deletions

26
.github/workflows/gradlebuild.yml vendored Executable file
View File

@@ -0,0 +1,26 @@
name: Gradle Build
on:
push:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 16
uses: actions/setup-java@v1
with:
java-version: 16
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Build with Gradle
run: ./gradlew build
- uses: actions/upload-artifact@v2
with:
name: Artifacts
path: ./build/libs/

40
.github/workflows/gradlepublish.yml vendored Executable file
View File

@@ -0,0 +1,40 @@
name: Gradle Package
on:
push:
tags:
- '*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 16
uses: actions/setup-java@v1
with:
java-version: 16
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Build with Gradle
run: ./gradlew build
- uses: actions/upload-artifact@v2
with:
name: Artifacts
path: ./build/libs/
# The USERNAME and PASSWORD need to correspond to the credentials environment variables used in
# the publishing section of your build.gradle
- name: Publish to GitHub Packages and other Mavens
run: ./gradlew publish
env:
BRANCH_NAME: ${{ github.ref }}
RUN_COUNT: ${{ github.run_number }}
REPO_NAME: ${{ github.repository }}
USERNAME: ${{ github.actor }}
TOKEN: ${{ secrets.GITHUB_TOKEN }}
LAMBDACONTROLS_MAVEN: ${{ secrets.MAVEN_URL }}
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}

23
.github/workflows/modrinth_update.yml vendored Executable file
View File

@@ -0,0 +1,23 @@
name: Gradle Build
on:
release:
types:
- published
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 16
uses: actions/setup-java@v1
with:
java-version: 16
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Build with Gradle
env:
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
run: ./gradlew publishModrinth

7
.gitignore vendored
View File

@@ -1,7 +1,7 @@
#
# LambdAurora's ignore file
#
# v0.13
# v0.15
# JetBrains
.idea/
@@ -53,6 +53,8 @@ __pycache__/
# OS
## Windows
desktop.ini
# MacOS
.DS_Store
# File types
*.dll
@@ -61,10 +63,13 @@ desktop.ini
*.lib
lib*.a
*.png~
*.tar.?z
# Common
bin/
build/
dist/
lib/
obj/
run/
target/

View File

@@ -1,6 +1,6 @@
# Changelog
## v1.0.0
## 1.0.0
:tada: First release! :tada:
@@ -12,11 +12,11 @@
- Added key bindings for look around.
- And more!
### v1.0.1
### 1.0.1
- Fixed tutorial toast to look around not affected by camera movement done with a controller. ([#2](https://github.com/LambdAurora/LambdaControls/issues/2))
### v1.0.2 (Unofficial)
### 1.0.2 (Unofficial)
This update was never pushed but was aiming to fix [#4](https://github.com/LambdAurora/LambdaControls/issues/4).
@@ -24,7 +24,7 @@ This update was never pushed but was aiming to fix [#4](https://github.com/Lambd
- Fixed broken chat arrow keys.
- Optimized a little bit the button indicator. (need more work)
## v1.1.0 - Chording update
## 1.1.0 - Chording update
This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAurora/LambdaControls/issues/9)).
@@ -46,9 +46,9 @@ This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAur
- HUD side affects button indicators now.
- Added support for Advancements tabs.
### v1.1.1
### 1.1.1
## v1.2.0-1.3.0
## 1.2.0-1.3.0
- Improved rotation algorithm ([#11](https://github.com/LambdAurora/LambdaControls/issues/11)).
- Added virtual mouse.
@@ -60,21 +60,21 @@ This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAur
- And more!
- v1.3.0 specific: Updated to Minecraft 1.16.1
### v1.3.1
### 1.3.1
- Fixed broken inventory interactions ([#13](https://github.com/LambdAurora/LambdaControls/issues/13))
- Fixed virtual mouse preventing continuous attack (thus making breaking blocks impossible).
- Added support for [ModUpdater](https://gitea.thebrokenrail.com/TheBrokenRail/ModUpdater) hopefully.
- Updated [SpruceUI](https://github.com/LambdAurora/SpruceUI) to 1.5.2.
### v1.3.2
### 1.3.2
- Added vertical reacharound.
- Added more API for compatibility handlers.
- Improved reacharound API.
- Improved [REI](https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items) compatibility.
## v1.4.0
## 1.4.0
- Added analog movements ([#10](https://github.com/LambdAurora/LambdaControls/issues/10)).
- Improved Ok Zoomer compability.
@@ -90,11 +90,11 @@ This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAur
- Will allow for better compability with other mods.
- Might be interesting for keyboard users too.
### v1.4.1
### 1.4.1
- Fixed crash with [REI](https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items).
## v1.5.0
## 1.5.0
- Added mappings string editor screen.
- Added Simplified Chinese translations ([#18](https://github.com/LambdAurora/LambdaControls/pull/18)).
@@ -104,9 +104,28 @@ This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAur
- Respect toggle setting in Accessibility screen.
- Tweaked rotation speeds.
- Updated to Minecraft 1.16.2.
- Updated [SpruceUI](https://github.com/LambdAurora/SpruceUI) to 1.6.4.
- Updated [SpruceUI] to 1.6.4.
- Overhauled REI compatibility.
- Improved horizontal reach-around.
- Fixed crashes with Ok Zoomer.
- Fixed crashes with key unbinding.
- More WIP on keybind ring.
## 1.6.0
- Reworked entirely the settings screen.
- Added independent stick dead zones. ([#32](https://github.com/LambdAurora/LambdaControls/issues/32))
- Added max values range. ([#41](https://github.com/LambdAurora/LambdaControls/issues/41))
- Updated [SpruceUI] and fix related crashes due to incompatible versions ([#40](https://github.com/LambdAurora/LambdaControls/issues/40), [#48](https://github.com/LambdAurora/LambdaControls/issues/48)).
- Fix boat control issues ([#37](https://github.com/LambdAurora/LambdaControls/issues/37)).
- Fix incompatibilities with mods using night-config. Now shadowing properly night-config. ([#33](https://github.com/LambdAurora/LambdaControls/issues/33), [#39](https://github.com/LambdAurora/LambdaControls/issues/39))
## 1.7.0
- Updated to 1.17.
- Small improvements to the codebase thanks to Java 16.
- Fix controller bindings not being saved ([#31](https://github.com/LambdAurora/LambdaControls/issues/31), [#55](https://github.com/LambdAurora/LambdaControls/issues/55)).
- Dropped entirely Touchscreen Input Mode.
- Dropped Roughly Enough Items compatibility.
[SpruceUI]: https://github.com/LambdAurora/SpruceUI

View File

@@ -26,7 +26,7 @@ By participating, you are expected to uphold this code. Please report unacceptab
[Fabric](https://fabricmc.net/) is the mod loader and the software which allows Gradle to setup the workspace.
### Java 8
### Java 16
Java is the main language used to make LambdaControls alive.
Knowing how to code in Java is necessary if you contribute to the code.
@@ -47,7 +47,7 @@ As it is a Minecraft mod you should know a bit how Minecraft works and how moddi
Git is the control version software we use for LambdaControls, please know how to use it if you consider contributing to the code.
Git commits should be and must be signed.
Git commits should be signed.
## How can I contribute?
@@ -55,17 +55,17 @@ Git commits should be and must be signed.
#### Before submitting a bug report
- Check if you can reproduce it on other platforms, on multiple web browsers.
- Check if you can reproduce it on other platforms.
- Perform a search to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one.
#### How do I submit a bug report?
Go in the issues tab in GitHub and read the [bug report guide](https://github.com/LambdAurora/LambdaControls/blob/master/.github/ISSUE_TEMPLATE/bug_report.md)
Go in the issues tab in GitHub and read the [bug report guide](https://github.com/LambdAurora/LambdaControls/blob/1.17/.github/ISSUE_TEMPLATE/bug_report.md)
### Suggesting enhancements
Enhancement suggestions are tracked as [GitHub issues](https://github.com/LambdAurora/LambdaControls/issues).
Check out the [feature request](https://github.com/LambdAurora/LambdaControls/blob/master/.github/ISSUE_TEMPLATE/feature_request.md) guide.
Check out the [feature request](https://github.com/LambdAurora/LambdaControls/blob/1.17/.github/ISSUE_TEMPLATE/feature_request.md) guide.
### Do pull requests
@@ -81,21 +81,16 @@ Feel free to pull request!
### Git commit messages
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
* Consider starting the commit message with an emote, emotes for your commit can be found at the [gitmoji guide](https://gitmoji.carloscuesta.me/).
* (Not for the message) Don't forget to sign the commit.
### Naming convention
Names in the code should be explicit and always in `snake_case`, `camelCase` will not be allowed.
Names in the code should be explicit and always in `camelCase`, `snake_case` will not be allowed.
`PascalCase` can be used for class name.
We chose `snake_case` because it is more accessible for everyone: for people who don't speak English as their native language it is more easy to see the words when they are separated,
it also allows the correct use of screen reader on the code with `snake_case` due to the absence of upper case characters.
### Brace placement
Every braces should be at the end of the line of function declaration, etc...
The only exception is class declarations: braces must be on the next line.
Every braces should be at the end of the line of function declaration, etc.
### Quick note for users of the Intellij IDEA IDE

View File

@@ -1,11 +1,13 @@
# LambdaControls
![Java 8](https://img.shields.io/badge/language-Java%208-9B599A.svg?style=flat-square)
<!-- modrinth_exclude.start -->
![Java 16](https://img.shields.io/badge/language-Java%2016-9B599A.svg?style=flat-square) <!-- modrinth_exclude.end -->
[![GitHub license](https://img.shields.io/github/license/LambdAurora/LambdaControls?style=flat-square)](https://raw.githubusercontent.com/LambdAurora/LambdaControls/master/LICENSE)
![Environment: Client](https://img.shields.io/badge/environment-client-1976d2?style=flat-square)
[![Mod loader: Fabric]][fabric]
[![Mod loader: Fabric]][fabric] <!-- modrinth_exclude.start -->
![Version](https://img.shields.io/github/v/tag/LambdAurora/LambdaControls?label=version&style=flat-square)
[![CurseForge](http://cf.way2muchnoise.eu/title/354231.svg)](https://www.curseforge.com/minecraft/mc-mods/lambdacontrols)
<!-- modrinth_exclude.end -->
A Fabric Minecraft mod which adds better controls, reach-around and controller support.
@@ -45,9 +47,11 @@ This mod also adds controller support.
![controller_controls]
![controller_options]
<!-- modrinth_exclude.start -->
## Build
Just do `./gradlew shadowRemapJar` and everything should build just fine!
Just do `./gradlew build` and everything should build just fine!
<!-- modrinth_exclude.end -->
[controller_controls]: images/controller_controls.png
[controller_options]: images/controller_options.png

View File

@@ -1,59 +1,77 @@
buildscript {
dependencies {
constraints {
["asm", "asm-util", "asm-tree", "asm-analysis"].each {
classpath("org.ow2.asm:$it") {
version { require("9.1") }
because("Fabric's TinyRemapper requires ASM 9")
}
}
}
}
}
plugins {
id 'fabric-loom' version '0.6-SNAPSHOT'
id 'fabric-loom' version '0.9.+'
id 'java-library'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '6.1.0'
id 'org.cadixdev.licenser' version '0.5.0'
id 'com.github.johnrengelman.shadow' version '7.0.0'
id 'org.cadixdev.licenser' version '0.6.1'
id 'com.modrinth.minotaur' version '1.2.+'
}
import net.fabricmc.loom.task.RemapJarTask
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject
import com.modrinth.minotaur.TaskModrinthUpload
import com.modrinth.minotaur.request.VersionType
import com.modrinth.minotaur.responses.ResponseError
import org.apache.http.client.config.CookieSpecs
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.entity.EntityBuilder
import org.apache.http.client.methods.HttpPatch
import org.apache.http.entity.ContentType
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.util.EntityUtils
group = project.maven_group
version = "${project.mod_version}+${getMCVersionString()}"
archivesBaseName = project.archives_base_name + "-fabric"
archivesBaseName = project.archives_base_name
// This field defines the Java version your mod target.
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too.
def targetJavaVersion = 8
def targetJavaVersion = 16
def getMCVersionString() {
if (project.minecraft_version.matches("\\d\\dw\\d\\d[a-z]")) {
boolean isMCVersionNonRelease() {
return project.minecraft_version.matches('^\\d\\dw\\d\\d[a-z]$')
|| project.minecraft_version.matches('\\d+\\.\\d+-(pre|rc)(\\d+)')
}
String getMCVersionString() {
if (isMCVersionNonRelease()) {
return project.minecraft_version
}
int lastDot = project.minecraft_version.lastIndexOf('.')
return project.minecraft_version.substring(0, lastDot)
def version = project.minecraft_version.split('\\.')
return version[0] + '.' + version[1]
}
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, '')
readme = readme.replaceAll(linkRegex, '![$1](https://raw.githubusercontent.com/LambdAurora/LambdaControls/1.17/$2)')
return readme
}
minecraft {
accessWidener file('src/main/resources/lambdacontrols.accesswidener')
}
repositories {
mavenLocal()
mavenCentral()
maven { url = 'https://aperlambda.github.io/maven' }
maven { url 'https://aperlambda.github.io/maven' }
maven {
name = 'CottonMC'
url = 'http://server.bbkr.space:8081/artifactory/libs-snapshot'
name 'Gegy'
url 'https://maven.gegy.dev'
}
maven {
name = 'Terraformers'
url = 'https://maven.terraformersmc.com/releases'
name 'CottonMC'
url 'https://server.bbkr.space:8081/artifactory/libs-snapshot'
}
maven { url "https://maven.shedaniel.me/" }
maven { url = "https://jitpack.io" }
maven {
name 'Terraformers'
url 'https://maven.terraformersmc.com/releases'
}
maven { url 'https://maven.shedaniel.me/' }
}
configurations {
@@ -70,20 +88,19 @@ dependencies {
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "dev.lambdaurora:spruceui:${project.spruceui_version}"
include "dev.lambdaurora:spruceui:${project.spruceui_version}"
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
modImplementation "com.github.lambdaurora:spruceui:${project.spruceui_version}"
include "com.github.lambdaurora:spruceui:${project.spruceui_version}"
// Compatibility mods
modImplementation("com.github.joaoh1:okzoomer:e13183c59b") {
/*modImplementation("com.github.joaoh1:okzoomer:e13183c59b") {
exclude group: 'me.shedaniel.cloth'
exclude group: 'io.github.prospector'
}
}*/
modImplementation("me.shedaniel:RoughlyEnoughItems:5.10.184")
shadow "com.electronwill.night-config:core:3.6.3"
shadow "com.electronwill.night-config:toml:3.6.3"
shadow 'com.electronwill.night-config:core:3.6.3'
shadow 'com.electronwill.night-config:toml:3.6.3'
}
java {
@@ -94,25 +111,21 @@ java {
}
tasks.withType(JavaCompile).configureEach {
it.options.encoding = "UTF-8"
it.options.encoding = 'UTF-8'
if (JavaVersion.current().isJava9Compatible()) {
if (JavaVersion.current().isJava9Compatible()) {
it.options.release = targetJavaVersion
}
}
it.options.release.set(targetJavaVersion)
}
processResources {
inputs.property "version", project.version
inputs.property 'version', project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
filesMatching('fabric.mod.json') {
expand 'version': project.version
}
}
jar {
from("LICENSE") {
from('LICENSE') {
rename { "${it}_${project.archivesBaseName}" }
}
}
@@ -133,37 +146,118 @@ shadowJar {
exclude 'org/**'
relocate 'com.electronwill.nightconfig', 'dev.lambdaurora.lambdacontrols.shadow.nightconfig'
}
remapJar.dependsOn(shadowJar)
task shadowRemapJar(type: RemapJarTask) {
dependsOn shadowJar
input = file("${project.buildDir}/libs/$archivesBaseName-$version-dev.jar")
archiveName = "${archivesBaseName}-${version}.jar"
addNestedDependencies = true
input.set(file("${project.buildDir}/libs/$archivesBaseName-$version-dev.jar"))
archiveFileName = "${archivesBaseName}-${version}.jar"
addNestedDependencies.set(true)
}
build.dependsOn(shadowRemapJar)
task publishModrinth(type: TaskModrinthUpload) {
dependsOn(build)
onlyIf {
System.getenv('MODRINTH_TOKEN')
}
token = System.getenv('MODRINTH_TOKEN')
projectId = project.modrinth_id
versionNumber = version
versionName = "LambdaControls ${project.mod_version} (${getMCVersionString()})"
uploadFile = shadowRemapJar
addGameVersion((String) project.minecraft_version)
addLoader('fabric')
versionType = isMCVersionNonRelease() ? VersionType.BETA : VersionType.RELEASE
// Changelog fetching
def changelogText = file('CHANGELOG.md').text
def regexVersion = ((String) project.mod_version).replaceAll('\\.', /\\./).replaceAll('\\+', '\\+')
def changelogRegex = ~"###? ${regexVersion}\\n\\n(( *- .+\\n)+)"
def matcher = changelogText =~ changelogRegex
matcher.find()
changelog = matcher.group(1)
// Readme
doFirst {
final def client = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
final def patch = new HttpPatch((String) (apiURL + '/v1/mod/' + projectId))
patch.addHeader("Authorization", token)
var json = new JsonObject()
json.addProperty("body", parseReadme())
patch.setEntity(EntityBuilder.create()
.setText(json.toString())
.setContentType(ContentType.APPLICATION_JSON)
.build())
final def response = client.execute(patch)
final int status = response.getStatusLine().getStatusCode()
final def gson = new GsonBuilder().create()
if (status == 200) {
project.getLogger().lifecycle("Successfully updated readme to ${projectId}.")
} else {
errorInfo = gson.fromJson(EntityUtils.toString(response.getEntity()), ResponseError.class)
project.getLogger().error("Upload failed! Status: ${status} Error: ${errorInfo.getError()} Reason: ${errorInfo.getDescription()}")
throw new GradleException("Upload failed! Status: ${status} Reason: ${errorInfo.getDescription()}")
}
}
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
artifact(shadowRemapJar) {
builtBy shadowRemapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
pom {
name = 'LambdaControls'
description = 'Adds better controls, and controller support.'
}
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.shadow.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', 'compile')
}
}
}
}
repositories {
mavenLocal()
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/LambdAurora/LambdaControls")
name "GithubPackages"
url uri("https://maven.pkg.github.com/LambdAurora/LambdaControls")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
}
}
}
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
def lambdacontrolsMaven = System.getenv('LAMBDACONTROLS_MAVEN')
if (lambdacontrolsMaven) {
maven {
name 'LambdaControlsMaven'
url uri(lambdacontrolsMaven)
credentials {
username = project.findProperty('gpr.user') ?: System.getenv('MAVEN_USERNAME')
password = project.findProperty('gpr.key') ?: System.getenv('MAVEN_PASSWORD')
}
}
}
}

View File

@@ -3,17 +3,18 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.16.5
yarn_mappings=1.16.5+build.5
loader_version=0.11.3
minecraft_version=1.17
yarn_mappings=1.17+build.13
loader_version=0.11.6
# Mod Properties
mod_version = 1.6.0
maven_group = dev.lambdaurora.lambdacontrols
mod_version = 1.7.0
maven_group = dev.lambdaurora
archives_base_name = lambdacontrols
modrinth_id=W1D3UXEc
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.32.0+1.16
spruceui_version=2.1.4-1.16
modmenu_version=1.16.8
fabric_version=0.36.0+1.17
spruceui_version=3.1.0+1.17
modmenu_version=2.0.2

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

0
gradlew vendored Normal file → Executable file
View File

View File

@@ -1,8 +1,8 @@
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
name 'Fabric'
url 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}

View File

@@ -19,21 +19,20 @@ import java.util.Optional;
* Represents the controls mode.
*
* @author LambdAurora
* @version 1.1.0
* @version 1.7.0
* @since 1.0.0
*/
public enum ControlsMode implements Nameable {
DEFAULT,
CONTROLLER,
TOUCHSCREEN;
CONTROLLER;
/**
* Returns the next controls mode available.
*
* @return The next available controls mode.
* @return the next available controls mode
*/
public ControlsMode next() {
ControlsMode[] v = values();
var v = values();
if (v.length == this.ordinal() + 1)
return v[0];
return v[this.ordinal() + 1];
@@ -42,7 +41,7 @@ public enum ControlsMode implements Nameable {
/**
* Gets the translation key of this controls mode.
*
* @return The translated key of this controls mode.
* @return the translated key of this controls mode
* @since 1.1.0
*/
public String getTranslationKey() {
@@ -57,8 +56,8 @@ public enum ControlsMode implements Nameable {
/**
* Gets the controls mode from its identifier.
*
* @param id The identifier of the controls mode.
* @return The controls mode if found, else empty.
* @param id the identifier of the controls mode
* @return the controls mode if found, else empty
*/
public static Optional<ControlsMode> byId(@NotNull String id) {
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();

View File

@@ -12,7 +12,7 @@ package dev.lambdaurora.lambdacontrols;
import dev.lambdaurora.lambdacontrols.event.PlayerChangeControlsModeCallback;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.network.PacketByteBuf;
@@ -29,7 +29,7 @@ import java.util.Optional;
* Represents the LambdaControls mod.
*
* @author LambdAurora
* @version 1.6.0
* @version 1.7.0
* @since 1.0.0
*/
public class LambdaControls implements ModInitializer {
@@ -47,25 +47,25 @@ public class LambdaControls implements ModInitializer {
INSTANCE = this;
this.log("Initializing LambdaControls...");
ServerSidePacketRegistry.INSTANCE.register(HELLO_CHANNEL,
(context, attachedData) -> {
String version = attachedData.readString(32);
ControlsMode.byId(attachedData.readString(32))
.ifPresent(controlsMode -> context.getTaskQueue()
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.getPlayer(), controlsMode)));
context.getTaskQueue().execute(() ->
ServerSidePacketRegistry.INSTANCE.sendToPlayer(context.getPlayer(), FEATURE_CHANNEL, this.makeFeatureBuffer(LambdaControlsFeature.HORIZONTAL_REACHAROUND)));
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(LambdaControlsFeature.HORIZONTAL_REACHAROUND));
});
ServerSidePacketRegistry.INSTANCE.register(CONTROLS_MODE_CHANNEL,
(context, attachedData) -> ControlsMode.byId(attachedData.readString(32))
.ifPresent(controlsMode -> context.getTaskQueue()
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.getPlayer(), controlsMode))));
});
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.
* @param info the message to print
*/
public void log(String info) {
this.logger.info("[LambdaControls] " + info);
@@ -74,7 +74,7 @@ public class LambdaControls implements ModInitializer {
/**
* Prints a warning to the terminal.
*
* @param warning The warning to print.
* @param warning the warning to print
*/
public void warn(String warning) {
this.logger.info("[LambdaControls] " + warning);
@@ -83,8 +83,8 @@ public class LambdaControls implements ModInitializer {
/**
* Returns a packet byte buffer made for the lambdacontrols:controls_mode plugin message.
*
* @param controlsMode The controls mode to send.
* @return The packet byte buffer.
* @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.");
@@ -94,18 +94,23 @@ public class LambdaControls implements ModInitializer {
/**
* Returns a packet byte buffer made for the lambdacontrols:feature plugin message.
*
* @param feature The feature data to send.
* @return The packet byte buffer.
* @param features the features data to send
* @return the packet byte buffer
*/
public PacketByteBuf makeFeatureBuffer(@NotNull LambdaControlsFeature feature) {
Objects.requireNonNull(feature, "Feature cannot be null.");
PacketByteBuf buffer = new PacketByteBuf(Unpooled.buffer()).writeString(feature.getName(), 64);
public PacketByteBuf makeFeatureBuffer(LambdaControlsFeature... 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) {
String version = "";
var version = "";
Optional<ModContainer> container;
if ((container = FabricLoader.getInstance().getModContainer(LambdaControlsConstants.NAMESPACE)).isPresent()) {
version = container.get().getMetadata().getVersion().getFriendlyString();
@@ -116,7 +121,7 @@ public class LambdaControls implements ModInitializer {
/**
* Gets the LambdaControls instance.
*
* @return The LambdaControls instance.
* @return the LambdaControls instance
*/
public static LambdaControls get() {
return INSTANCE;

View File

@@ -57,7 +57,7 @@ public class LambdaControlsFeature implements Nameable {
/**
* Returns whether this feature is allowed.
*
* @return True if this feature is allowed, else false.
* @return {@code true} if this feature is allowed, else {@code false}
*/
public boolean isAllowed() {
return this.allowed;
@@ -66,7 +66,7 @@ public class LambdaControlsFeature implements Nameable {
/**
* Sets whether this feature is allowed.
*
* @param allowed True if this feature is allowed, else false.
* @param allowed {@code true} if this feature is allowed, else {@code false}
*/
public void setAllowed(boolean allowed) {
this.allowed = allowed;
@@ -82,7 +82,7 @@ public class LambdaControlsFeature implements Nameable {
/**
* Returns whether this feature is enabled.
*
* @return True if this feature is enabled, else false.
* @return {@code true} if this feature is enabled, else {@code false}
*/
public boolean isEnabled() {
return this.enabled;
@@ -91,7 +91,7 @@ public class LambdaControlsFeature implements Nameable {
/**
* Returns whether this feature is enabled.
*
* @param enabled True if this feature is enabled, else false.
* @param enabled {@code true} if this feature is enabled, else {@code false}
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
@@ -100,7 +100,7 @@ public class LambdaControlsFeature implements Nameable {
/**
* Returns whether this feature is available or not.
*
* @return True if this feature is available, else false.
* @return {@code true} if this feature is available, else {@code false}
* @see #isAllowed()
* @see #isEnabled()
*/

View File

@@ -31,7 +31,7 @@ public enum ButtonState {
/**
* Returns whether this state is a pressed state.
*
* @return True if this state is a pressed state, else false.
* @return true if this state is a pressed state, else false
*/
public boolean isPressed() {
return this == PRESS || this == REPEAT;
@@ -40,7 +40,7 @@ public enum ButtonState {
/**
* Returns whether this state is an unpressed state.
*
* @return True if this state is an unpressed state, else false.
* @return true if this state is an unpressed state, else false
*/
public boolean isUnpressed() {
return this == RELEASE || this == NONE;

View File

@@ -50,7 +50,7 @@ public enum ControllerType implements Nameable {
/**
* Returns the controller type's identifier.
*
* @return The controller type's identifier.
* @return the controller type's identifier
*/
public int getId() {
return this.id;
@@ -59,10 +59,10 @@ public enum ControllerType implements Nameable {
/**
* Returns the next controller type available.
*
* @return The next available controller type.
* @return the next available controller type
*/
public @NotNull ControllerType next() {
ControllerType[] v = values();
var v = values();
if (v.length == this.ordinal() + 1)
return v[0];
return v[this.ordinal() + 1];
@@ -71,7 +71,7 @@ public enum ControllerType implements Nameable {
/**
* Gets the translated text of this controller type.
*
* @return The translated text of this controller type.
* @return the translated text of this controller type
*/
public @NotNull Text getTranslatedText() {
return this.text;
@@ -85,8 +85,8 @@ public enum ControllerType implements Nameable {
/**
* Gets the controller type from its identifier.
*
* @param id The identifier of the controller type.
* @return The controller type if found, else empty.
* @param id the identifier of the controller type
* @return the controller type if found, else empty
*/
public static @NotNull Optional<ControllerType> byId(@NotNull String id) {
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();

View File

@@ -37,10 +37,10 @@ public enum HudSide implements Nameable {
/**
* Returns the next side available.
*
* @return The next available side.
* @return the next available side
*/
public @NotNull HudSide next() {
HudSide[] v = values();
var v = values();
if (v.length == this.ordinal() + 1)
return v[0];
return v[this.ordinal() + 1];
@@ -49,7 +49,7 @@ public enum HudSide implements Nameable {
/**
* Returns the translation key of this hud side.
*
* @return The translation key of this hude side.
* @return the translation key of this hude side
*/
public @NotNull String getTranslationKey() {
return "lambdacontrols.hud_side." + this.getName();
@@ -58,7 +58,7 @@ public enum HudSide implements Nameable {
/**
* Gets the translated text of this hud side.
*
* @return The translated text of this hud side.
* @return the translated text of this hud side
*/
public @NotNull Text getTranslatedText() {
return this.text;
@@ -72,8 +72,8 @@ public enum HudSide implements Nameable {
/**
* Gets the hud side from its identifier.
*
* @param id The identifier of the hud side.
* @return The hud side if found, else empty.
* @param id the identifier of the hud side
* @return the hud side if found, else empty
*/
public static @NotNull Optional<HudSide> byId(@NotNull String id) {
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();

View File

@@ -18,11 +18,9 @@ import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsHud;
import dev.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
import dev.lambdaurora.lambdacontrols.client.ring.KeyBindingRingAction;
import dev.lambdaurora.lambdacontrols.client.ring.LambdaRing;
import me.lambdaurora.spruceui.event.OpenScreenCallback;
import me.lambdaurora.spruceui.hud.HudManager;
import dev.lambdaurora.spruceui.hud.HudManager;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
@@ -30,7 +28,7 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.toast.SystemToast;
import net.minecraft.client.util.InputUtil;
import net.minecraft.text.LiteralText;
@@ -45,7 +43,7 @@ import java.io.File;
* Represents the LambdaControls client mod.
*
* @author LambdAurora
* @version 1.6.0
* @version 1.7.0
* @since 1.1.0
*/
public class LambdaControlsClient extends LambdaControls implements ClientModInitializer {
@@ -86,9 +84,12 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
responseSender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(this.config.getControlsMode()));
});
ClientPlayNetworking.registerGlobalReceiver(FEATURE_CHANNEL, (client, handler, buf, responseSender) -> {
String name = buf.readString(64);
int features = buf.readVarInt();
for (int i = 0; i < features; i++) {
var name = buf.readString(64);
boolean allowed = buf.readBoolean();
LambdaControlsFeature.fromName(name).ifPresent(feature -> client.execute(() -> feature.setAllowed(allowed)));
}
});
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
sender.sendPacket(HELLO_CHANNEL, this.makeHello(this.config.getControlsMode()));
@@ -99,7 +100,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
ClientTickEvents.START_CLIENT_TICK.register(this.reacharound::tick);
ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
OpenScreenCallback.EVENT.register((client, screen) -> {
/*OpenScreenCallback.EVENT.register((client, screen) -> {
if (screen == null && this.config.getControlsMode() == ControlsMode.TOUCHSCREEN) {
screen = new TouchscreenOverlay(this);
screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
@@ -108,7 +109,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
} else if (screen != null) {
this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight());
}
});
});*/
HudManager.register(this.hud = new LambdaControlsHud(this));
}
@@ -123,7 +124,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
Controller.updateMappings();
GLFW.glfwSetJoystickCallback((jid, event) -> {
if (event == GLFW.GLFW_CONNECTED) {
Controller controller = Controller.byId(jid);
var controller = Controller.byId(jid);
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.connected", jid),
new LiteralText(controller.getName())));
} else if (event == GLFW.GLFW_DISCONNECTED) {
@@ -184,7 +185,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
/**
* Sets whether the HUD is enabled or not.
*
* @param enabled True if the HUD is enabled, else false.
* @param enabled true if the HUD is enabled, else false
*/
public void setHudEnabled(boolean enabled) {
this.config.setHudEnabled(enabled);
@@ -194,7 +195,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
/**
* Gets the LambdaControls client instance.
*
* @return The LambdaControls client instance.
* @return the LambdaControls client instance
*/
public static LambdaControlsClient get() {
return INSTANCE;

View File

@@ -21,7 +21,6 @@ import org.lwjgl.glfw.GLFW;
import java.util.Arrays;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -144,8 +143,8 @@ public class LambdaControlsConfig {
public void checkAndFix() {
InputManager.streamBindings().forEach(binding -> {
String path = "controller.controls." + binding.getName();
Object raw = this.config.getRaw(path);
var path = "controller.controls." + binding.getName();
var raw = this.config.getRaw(path);
if (raw instanceof Number) {
this.mod.warn("Invalid data at \"" + path + "\", fixing...");
this.config.set(path, String.valueOf(raw));
@@ -175,7 +174,7 @@ public class LambdaControlsConfig {
private void renamed(String oldPath, String newPath) {
if (!this.config.contains(oldPath))
return;
Object raw = this.config.getRaw(oldPath);
var raw = this.config.getRaw(oldPath);
this.config.remove(oldPath);
this.config.set(newPath, raw);
}
@@ -218,7 +217,7 @@ public class LambdaControlsConfig {
/**
* Gets the controls mode from the configuration.
*
* @return The controls mode.
* @return the controls mode
*/
public @NotNull ControlsMode getControlsMode() {
return this.controlsMode;
@@ -227,7 +226,7 @@ public class LambdaControlsConfig {
/**
* Sets the controls mode in the configuration.
*
* @param controlsMode The controls mode.
* @param controlsMode the controls mode
*/
public void setControlsMode(@NotNull ControlsMode controlsMode) {
this.controlsMode = controlsMode;
@@ -237,7 +236,7 @@ public class LambdaControlsConfig {
/**
* Returns whether the auto switch mode is enabled or not.
*
* @return True if the auto switch mode is enabled, else false.
* @return true if the auto switch mode is enabled, else false
*/
public boolean hasAutoSwitchMode() {
return this.config.getOrElse("auto_switch_mode", DEFAULT_AUTO_SWITCH_MODE);
@@ -246,7 +245,7 @@ public class LambdaControlsConfig {
/**
* Sets whether the auto switch mode is enabled or not.
*
* @param autoSwitchMode True if the auto switch mode is enabled, else false.
* @param autoSwitchMode true if the auto switch mode is enabled, else false
*/
public void setAutoSwitchMode(boolean autoSwitchMode) {
this.config.set("auto_switch_mode", autoSwitchMode);
@@ -255,7 +254,7 @@ public class LambdaControlsConfig {
/**
* Returns whether the mod has debug enabled or not.
*
* @return True if debug is enabled, else false.
* @return true if debug is enabled, else false
*/
public boolean hasDebug() {
return this.config.getOrElse("debug", DEFAULT_DEBUG);
@@ -264,7 +263,7 @@ public class LambdaControlsConfig {
/**
* Sets whether the mod has debug enabled or not.
*
* @param debug True if debug is enabled, else false.
* @param debug true if debug is enabled, else false
*/
protected void setDebug(boolean debug) {
this.config.set("debug", debug);
@@ -277,7 +276,7 @@ public class LambdaControlsConfig {
/**
* Returns whether the HUD is enabled.
*
* @return True if the HUD is enabled, else false.
* @return true if the HUD is enabled, else false
*/
public boolean isHudEnabled() {
return this.hudEnable;
@@ -286,7 +285,7 @@ public class LambdaControlsConfig {
/**
* Sets whether the HUD is enabled.
*
* @param enable True if the HUD is enabled, else false.
* @param enable true if the HUD is enabled, else false
*/
public void setHudEnabled(boolean enable) {
this.hudEnable = enable;
@@ -296,7 +295,7 @@ public class LambdaControlsConfig {
/**
* Gets the HUD side from the configuration.
*
* @return The HUD side.
* @return the HUD side
*/
public @NotNull HudSide getHudSide() {
return this.hudSide;
@@ -305,7 +304,7 @@ public class LambdaControlsConfig {
/**
* Sets the HUD side in the configuration.
*
* @param hudSide The HUD side.
* @param hudSide the HUD side
*/
public void setHudSide(@NotNull HudSide hudSide) {
this.hudSide = hudSide;
@@ -337,7 +336,7 @@ public class LambdaControlsConfig {
/**
* Gets whether fast block placing is enabled or not.
*
* @return True if fast block placing is enabled, else false.
* @return true if fast block placing is enabled, else false
*/
public boolean hasFastBlockPlacing() {
return LambdaControlsFeature.FAST_BLOCK_PLACING.isEnabled();
@@ -346,7 +345,7 @@ public class LambdaControlsConfig {
/**
* Sets whether fast block placing is enabled or not.
*
* @param enable True if fast block placing is enabled, else false.
* @param enable true if fast block placing is enabled, else false
*/
public void setFastBlockPlacing(boolean enable) {
LambdaControlsFeature.FAST_BLOCK_PLACING.setEnabled(enable);
@@ -356,7 +355,7 @@ public class LambdaControlsConfig {
/**
* Returns whether fly drifting is enabled or not.
*
* @return True if fly drifting is enabled, else false.
* @return true if fly drifting is enabled, else false
*/
public boolean hasFlyDrifting() {
return this.config.getOrElse("gameplay.fly.drifting", DEFAULT_FLY_DRIFTING);
@@ -365,7 +364,7 @@ public class LambdaControlsConfig {
/**
* Sets whether fly drifting is enabled or not.
*
* @param flyDrifting True if fly drifting is enabled, else false.
* @param flyDrifting true if fly drifting is enabled, else false
*/
public void setFlyDrifting(boolean flyDrifting) {
this.config.set("gameplay.fly.drifting", flyDrifting);
@@ -374,7 +373,7 @@ public class LambdaControlsConfig {
/**
* Returns whether vertical fly drifting is enabled or not.
*
* @return True if vertical fly drifting is enabled, else false.
* @return true if vertical fly drifting is enabled, else false
*/
public boolean hasFlyVerticalDrifting() {
return this.config.getOrElse("gameplay.fly.vertical_drifting", DEFAULT_FLY_VERTICAL_DRIFTING);
@@ -383,7 +382,7 @@ public class LambdaControlsConfig {
/**
* Sets whether vertical fly drifting is enabled or not.
*
* @param flyDrifting True if vertical fly drifting is enabled, else false.
* @param flyDrifting true if vertical fly drifting is enabled, else false
*/
public void setFlyVerticalDrifting(boolean flyDrifting) {
this.config.set("gameplay.fly.vertical_drifting", flyDrifting);
@@ -392,7 +391,7 @@ public class LambdaControlsConfig {
/**
* Returns whether front block placing is enabled or not.
*
* @return True if front block placing is enabled, else false.
* @return true if front block placing is enabled, else false
*/
public boolean hasFrontBlockPlacing() {
return LambdaControlsFeature.HORIZONTAL_REACHAROUND.isEnabled();
@@ -401,7 +400,7 @@ public class LambdaControlsConfig {
/**
* Sets whether front block placing is enabled or not.
*
* @param enable True if front block placing is enabled, else false.
* @param enable true if front block placing is enabled, else false
*/
public void setFrontBlockPlacing(boolean enable) {
LambdaControlsFeature.HORIZONTAL_REACHAROUND.setEnabled(enable);
@@ -411,7 +410,7 @@ public class LambdaControlsConfig {
/**
* Returns whether vertical reacharound is enabled or not.
*
* @return True if vertical reacharound is enabled, else false.
* @return true if vertical reacharound is enabled, else false
*/
public boolean hasVerticalReacharound() {
return LambdaControlsFeature.VERTICAL_REACHAROUND.isEnabled();
@@ -420,7 +419,7 @@ public class LambdaControlsConfig {
/**
* Sets whether vertical reacharound is enabled or not.
*
* @param enable True if vertical reacharound is enabled, else false.
* @param enable true if vertical reacharound is enabled, else false
*/
public void setVerticalReacharound(boolean enable) {
LambdaControlsFeature.VERTICAL_REACHAROUND.setEnabled(enable);
@@ -430,7 +429,7 @@ public class LambdaControlsConfig {
/**
* Returns whether front block placing outline is enabled or not.
*
* @return True if front block placing outline is enabled, else false.
* @return true if front block placing outline is enabled, else false
*/
public boolean shouldRenderReacharoundOutline() {
return this.shouldRenderReacharoundOutline;
@@ -439,7 +438,7 @@ public class LambdaControlsConfig {
/**
* Sets whether front block placing outline is enabled or not.
*
* @param render True if front block placing outline is enabled, else false.
* @param render true if front block placing outline is enabled, else false
*/
public void setRenderReacharoundOutline(boolean render) {
this.config.set("gameplay.reacharound.outline", this.shouldRenderReacharoundOutline = render);
@@ -450,7 +449,7 @@ public class LambdaControlsConfig {
* <p>
* The integer array has 4 elements: red, green, blue and alpha.
*
* @return The color as a RGBA integer array.
* @return the color as a RGBA integer array
*/
public int[] getReacharoundOutlineColor() {
return this.reacharoundOutlineColor;
@@ -466,7 +465,7 @@ public class LambdaControlsConfig {
* @return the controller
*/
public Controller getController() {
Object raw = this.config.getRaw("controller.id");
var raw = this.config.getRaw("controller.id");
if (raw instanceof Number) {
return Controller.byId((Integer) raw);
} else if (raw instanceof String) {
@@ -481,7 +480,7 @@ public class LambdaControlsConfig {
* @param controller the controller
*/
public void setController(Controller controller) {
this.config.set("controller.id", controller.getId());
this.config.set("controller.id", controller.id());
}
/**
@@ -490,7 +489,7 @@ public class LambdaControlsConfig {
* @return the second controller
*/
public Optional<Controller> getSecondController() {
Object raw = this.config.getRaw("controller.id2");
var raw = this.config.getRaw("controller.id2");
if (raw instanceof Number) {
if ((int) raw == -1)
return Optional.empty();
@@ -507,13 +506,13 @@ public class LambdaControlsConfig {
* @param controller the second controller
*/
public void setSecondController(@Nullable Controller controller) {
this.config.set("controller.id2", controller == null ? -1 : controller.getId());
this.config.set("controller.id2", controller == null ? -1 : controller.id());
}
/**
* Gets the controller's type.
*
* @return The controller's type.
* @return the controller's type
*/
public @NotNull ControllerType getControllerType() {
return this.controllerType;
@@ -522,7 +521,7 @@ public class LambdaControlsConfig {
/**
* Sets the controller's type.
*
* @param controllerType The controller's type.
* @param controllerType the controller's type
*/
public void setControllerType(@NotNull ControllerType controllerType) {
this.controllerType = controllerType;
@@ -568,7 +567,7 @@ public class LambdaControlsConfig {
/**
* Gets the controller's rotation speed.
*
* @return The rotation speed.
* @return the rotation speed
*/
public double getRotationSpeed() {
return this.rotationSpeed;
@@ -577,7 +576,7 @@ public class LambdaControlsConfig {
/**
* Sets the controller's rotation speed.
*
* @param rotationSpeed The rotation speed.
* @param rotationSpeed the rotation speed
*/
public void setRotationSpeed(double rotationSpeed) {
this.rotationSpeed = rotationSpeed;
@@ -586,7 +585,7 @@ public class LambdaControlsConfig {
/**
* Gets the controller's mouse speed.
*
* @return The mouse speed.
* @return the mouse speed
*/
public double getMouseSpeed() {
return this.mouseSpeed;
@@ -595,7 +594,7 @@ public class LambdaControlsConfig {
/**
* Sets the controller's mouse speed.
*
* @param mouseSpeed The mouse speed.
* @param mouseSpeed the mouse speed
*/
public void setMouseSpeed(double mouseSpeed) {
this.mouseSpeed = mouseSpeed;
@@ -604,7 +603,7 @@ public class LambdaControlsConfig {
/**
* Returns whether the right X axis is inverted or not.
*
* @return True if the right X axis is inverted, else false.
* @return true if the right X axis is inverted, else false
*/
public boolean doesInvertRightXAxis() {
return this.config.getOrElse("controller.invert_right_x_axis", false);
@@ -613,7 +612,7 @@ public class LambdaControlsConfig {
/**
* Sets whether the right X axis is inverted or not.
*
* @param invert True if the right X axis is inverted, else false.
* @param invert true if the right X axis is inverted, else false
*/
public void setInvertRightXAxis(boolean invert) {
this.config.set("controller.invert_right_x_axis", invert);
@@ -622,7 +621,7 @@ public class LambdaControlsConfig {
/**
* Returns whether the right Y axis is inverted or not.
*
* @return True if the right Y axis is inverted, else false.
* @return true if the right Y axis is inverted, else false
*/
public boolean doesInvertRightYAxis() {
return this.config.getOrElse("controller.invert_right_y_axis", false);
@@ -631,7 +630,7 @@ public class LambdaControlsConfig {
/**
* Sets whether the right Y axis is inverted or not.
*
* @param invert True if the right Y axis is inverted, else false.
* @param invert true if the right Y axis is inverted, else false
*/
public void setInvertRightYAxis(boolean invert) {
this.config.set("controller.invert_right_y_axis", invert);
@@ -640,7 +639,7 @@ public class LambdaControlsConfig {
/**
* Returns whether unfocused controller input is allowed or not.
*
* @return True if unfocused controller input is allowed, else false.
* @return true if unfocused controller input is allowed, else false
*/
public boolean hasUnfocusedInput() {
return this.unfocusedInput;
@@ -649,7 +648,7 @@ public class LambdaControlsConfig {
/**
* Sets whether unfocused controller input is allowed or not.
*
* @param unfocusedInput True if unfocused controller input is allowed, else false.
* @param unfocusedInput true if unfocused controller input is allowed, else false
*/
public void setUnfocusedInput(boolean unfocusedInput) {
this.unfocusedInput = unfocusedInput;
@@ -658,7 +657,7 @@ public class LambdaControlsConfig {
/**
* Returns whether the mouse is virtual or not.
*
* @return True if the mouse is virtual, else false.
* @return true if the mouse is virtual, else false
*/
public boolean hasVirtualMouse() {
return this.virtualMouse;
@@ -667,7 +666,7 @@ public class LambdaControlsConfig {
/**
* Sets whether the mouse is virtual or not.
*
* @param virtualMouse True if the mouse is virtual, else false.
* @param virtualMouse true if the mouse is virtual, else false
*/
public void setVirtualMouse(boolean virtualMouse) {
this.virtualMouse = virtualMouse;
@@ -676,7 +675,7 @@ public class LambdaControlsConfig {
/**
* Gets the virtual mouse skin.
*
* @return The virtual mouse skin.
* @return the virtual mouse skin
*/
public VirtualMouseSkin getVirtualMouseSkin() {
return this.virtualMouseSkin;
@@ -685,7 +684,7 @@ public class LambdaControlsConfig {
/**
* Sets the virtual mouse skin.
*
* @param skin The virtual mouse skin.
* @param skin the virtual mouse skin
*/
public void setVirtualMouseSkin(VirtualMouseSkin skin) {
this.virtualMouseSkin = skin;
@@ -695,7 +694,7 @@ public class LambdaControlsConfig {
/**
* Gets the right X axis sign.
*
* @return The right X axis sign.
* @return the right X axis sign
*/
public double getRightXAxisSign() {
return this.doesInvertRightXAxis() ? -1.0 : 1.0;
@@ -704,7 +703,7 @@ public class LambdaControlsConfig {
/**
* Gets the right Y axis sign.
*
* @return The right Y axis sign.
* @return the right Y axis sign
*/
public double getRightYAxisSign() {
return this.doesInvertRightYAxis() ? -1.0 : 1.0;
@@ -724,16 +723,16 @@ public class LambdaControlsConfig {
/**
* Loads the button binding from configuration.
*
* @param button The button binding.
* @param button the button binding
*/
public void loadButtonBinding(@NotNull ButtonBinding button) {
button.setButton(button.getDefaultButton());
String code = this.config.getOrElse("controller.controls." + button.getName(), button.getButtonCode());
var code = this.config.getOrElse("controller.controls." + button.getName(), button.getButtonCode());
Matcher matcher = BUTTON_BINDING_PATTERN.matcher(code);
var matcher = BUTTON_BINDING_PATTERN.matcher(code);
try {
int[] buttons = new int[1];
var buttons = new int[1];
int count = 0;
while (matcher.find()) {
count++;
@@ -768,8 +767,8 @@ public class LambdaControlsConfig {
/**
* Sets the button binding in configuration.
*
* @param binding The button binding.
* @param button The button.
* @param binding the button binding
* @param button the button
*/
public void setButtonBinding(@NotNull ButtonBinding binding, int[] button) {
binding.setButton(button);
@@ -803,8 +802,8 @@ public class LambdaControlsConfig {
/**
* Returns whether the specified axis is an axis used for movements.
*
* @param axis The axis index.
* @return True if the axis is used for movements, else false.
* @param axis the axis index
* @return true if the axis is used for movements, else false
*/
public boolean isMovementAxis(int axis) {
return axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_X;
@@ -813,27 +812,25 @@ public class LambdaControlsConfig {
/**
* Parses a color from a hexadecimal color string.
*
* @param hex The hexadecimal color.
* @return The color instance, null if invalid.
* @param hex the hexadecimal color
* @return the color instance, null if invalid
*/
private static int[] parseColor(String hex) {
hex = hex.replace("#", "");
switch (hex.length()) {
case 6:
return new int[]{
return switch (hex.length()) {
case 6 -> new int[]{
Integer.valueOf(hex.substring(0, 2), 16),
Integer.valueOf(hex.substring(2, 4), 16),
Integer.valueOf(hex.substring(4, 6), 16),
255
};
case 8:
return new int[]{
case 8 -> new int[]{
Integer.valueOf(hex.substring(0, 2), 16),
Integer.valueOf(hex.substring(2, 4), 16),
Integer.valueOf(hex.substring(4, 6), 16),
Integer.valueOf(hex.substring(6, 8), 16)
};
}
return null;
default -> null;
};
}
}

View File

@@ -9,15 +9,15 @@
package dev.lambdaurora.lambdacontrols.client;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen;
import io.github.prospector.modmenu.api.ConfigScreenFactory;
import io.github.prospector.modmenu.api.ModMenuApi;
/**
* Represents the API implementation of ModMenu for LambdaControls.
*
* @author LambdAurora
* @version 1.3.0
* @version 1.7.0
* @since 1.1.0
*/
public class LambdaControlsModMenu implements ModMenuApi {

View File

@@ -21,12 +21,12 @@ import dev.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccess
import dev.lambdaurora.lambdacontrols.client.mixin.EntryListWidgetAccessor;
import dev.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
import dev.lambdaurora.lambdacontrols.client.util.MouseAccessor;
import me.lambdaurora.spruceui.navigation.NavigationDirection;
import me.lambdaurora.spruceui.screen.SpruceScreen;
import me.lambdaurora.spruceui.widget.AbstractSprucePressableButtonWidget;
import me.lambdaurora.spruceui.widget.SpruceElement;
import me.lambdaurora.spruceui.widget.SpruceLabelWidget;
import me.lambdaurora.spruceui.widget.container.SpruceParentWidget;
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 net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.ParentElement;
@@ -39,11 +39,10 @@ import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
import net.minecraft.client.gui.screen.pack.PackScreen;
import net.minecraft.client.gui.screen.world.WorldListWidget;
import net.minecraft.client.gui.widget.AbstractPressableButtonWidget;
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget;
import net.minecraft.client.gui.widget.EntryListWidget;
import net.minecraft.client.gui.widget.PressableWidget;
import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.text.TranslatableText;
@@ -54,8 +53,6 @@ import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWGamepadState;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
@@ -69,7 +66,7 @@ import static org.lwjgl.glfw.GLFW.*;
* Represents the LambdaControls' input handler.
*
* @author LambdAurora
* @version 1.6.0
* @version 1.7.0
* @since 1.0.0
*/
public class LambdaInput {
@@ -97,7 +94,7 @@ public class LambdaInput {
/**
* This method is called every Minecraft tick.
*
* @param client The client instance.
* @param client the client instance
*/
public void tick(@NotNull MinecraftClient client) {
this.targetYaw = 0.F;
@@ -121,19 +118,20 @@ public class LambdaInput {
/**
* This method is called every Minecraft tick for controller input update.
*
* @param client The client instance.
* @param client the client instance
*/
public void tickController(@NotNull MinecraftClient client) {
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0).forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0)
.forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
// Decreases the cooldown for GUI actions.
if (this.actionGuiCooldown > 0)
--this.actionGuiCooldown;
InputManager.updateStates();
Controller controller = this.config.getController();
var controller = this.config.getController();
if (controller.isConnected()) {
GLFWGamepadState state = controller.getState();
var state = controller.getState();
this.fetchButtonInput(client, state, false);
this.fetchAxeInput(client, state, false);
}
@@ -153,13 +151,12 @@ public class LambdaInput {
InputManager.updateBindings(client);
if (this.controlsInput != null
&& InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
&& InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) {
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.focusedBinding = null;
this.controlsInput.finishBindingEdit(buttons);
this.controlsInput = null;
}
}
@@ -171,8 +168,8 @@ public class LambdaInput {
/**
* This method is called before the screen is rendered.
*
* @param client The client instance.
* @param screen The screen to render.
* @param client the client instance
* @param screen the screen to render
*/
public void onPreRenderScreen(@NotNull MinecraftClient client, @NotNull Screen screen) {
if (!isScreenInteractive(screen)) {
@@ -183,21 +180,21 @@ public class LambdaInput {
/**
* This method is called when Minecraft renders.
*
* @param client The client instance.
* @param client the client instance
*/
public void onRender(float tickDelta, @NotNull MinecraftClient client) {
if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
return;
PlayerEntity player = client.player;
var player = client.player;
if (player == null)
return;
if (this.targetYaw != 0.f || this.targetPitch != 0.f) {
float rotationYaw = (float) (player.prevYaw + (this.targetYaw / 0.10) * tickDelta);
float rotationPitch = (float) (player.prevPitch + (this.targetPitch / 0.10) * tickDelta);
client.player.yaw = rotationYaw;
client.player.pitch = 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().onPassengerLookAround(client.player);
}
@@ -208,9 +205,9 @@ public class LambdaInput {
/**
* This method is called when a Screen is opened.
*
* @param client The client instance.
* @param windowWidth The window width.
* @param windowHeight The window height.
* @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) {
@@ -232,12 +229,12 @@ public class LambdaInput {
}
private void fetchButtonInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
ByteBuffer buffer = gamepadState.buttons();
var buffer = gamepadState.buttons();
for (int i = 0; i < buffer.limit(); i++) {
int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i;
boolean btnState = buffer.get() == (byte) 1;
ButtonState state = ButtonState.NONE;
ButtonState previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
var state = ButtonState.NONE;
var previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
if (btnState != previousState.isPressed()) {
state = btnState ? ButtonState.PRESS : ButtonState.RELEASE;
@@ -257,7 +254,7 @@ public class LambdaInput {
}
private void fetchAxeInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
FloatBuffer buffer = gamepadState.axes();
var buffer = gamepadState.axes();
for (int i = 0; i < buffer.limit(); i++) {
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
float value = buffer.get();
@@ -276,7 +273,7 @@ public class LambdaInput {
if (action == 0 && !this.controlsInput.currentButtons.contains(button)) {
this.controlsInput.currentButtons.add(button);
int[] buttons = new int[this.controlsInput.currentButtons.size()];
var buttons = new int[this.controlsInput.currentButtons.size()];
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
buttons[i] = this.controlsInput.currentButtons.get(i);
this.controlsInput.focusedBinding.setButton(buttons);
@@ -295,11 +292,7 @@ public class LambdaInput {
this.changeFocus(client.currentScreen, NavigationDirection.UP);
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN) {
this.changeFocus(client.currentScreen, NavigationDirection.DOWN);
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT) {
this.handleLeftRight(client.currentScreen, false);
} else {
this.handleLeftRight(client.currentScreen, true);
}
} else this.handleLeftRight(client.currentScreen, button != GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT);
}
return;
}
@@ -308,7 +301,7 @@ public class LambdaInput {
if (action == 1) {
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
if (this.actionGuiCooldown == 0) {
Element focused = client.currentScreen.getFocused();
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.
@@ -333,7 +326,8 @@ public class LambdaInput {
}
}
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0) {
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen)
&& this.actionGuiCooldown == 0) {
if (!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();
@@ -354,9 +348,9 @@ public class LambdaInput {
/**
* Handles inventory interaction.
*
* @param client The client instance.
* @param button The button pressed.
* @return True if an inventory interaction was done.
* @param client the client instance
* @param button the button pressed
* @return {@code true} if an inventory interaction was done
*/
private boolean handleInventory(@NotNull MinecraftClient client, int button) {
if (!(client.currentScreen instanceof HandledScreen))
@@ -376,20 +370,20 @@ public class LambdaInput {
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
HandledScreen screen = (HandledScreen) client.currentScreen;
HandledScreenAccessor accessor = (HandledScreenAccessor) screen;
var screen = (HandledScreen) client.currentScreen;
var accessor = (HandledScreenAccessor) screen;
Slot slot = ((HandledScreenAccessor) client.currentScreen).lambdacontrols$getSlotAt(x, y);
int slotId;
if (slot == null) {
if (client.player.inventory.getCursorStack().isEmpty())
if (client.player.currentScreenHandler.getCursorStack().isEmpty())
return false;
slotId = accessor.lambdacontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1;
} else {
slotId = slot.id;
}
SlotActionType actionType = SlotActionType.PICKUP;
var actionType = SlotActionType.PICKUP;
int clickData = GLFW.GLFW_MOUSE_BUTTON_1;
switch (button) {
case GLFW_GAMEPAD_BUTTON_A:
@@ -416,13 +410,13 @@ public class LambdaInput {
/**
* Tries to go back.
*
* @param screen The current screen.
* @return True if successful, else false.
* @param screen the current screen
* @return true if successful, else false
*/
public boolean tryGoBack(@NotNull Screen screen) {
ImmutableSet<String> set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
return screen.children().stream().filter(element -> element instanceof AbstractPressableButtonWidget)
.map(element -> (AbstractPressableButtonWidget) element)
var set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu");
return screen.children().stream().filter(element -> element instanceof PressableWidget)
.map(element -> (PressableWidget) element)
.filter(element -> element.getMessage() instanceof TranslatableText)
.anyMatch(element -> {
if (set.stream().anyMatch(key -> key.equals(((TranslatableText) element.getMessage()).getKey()))) {
@@ -450,8 +444,8 @@ public class LambdaInput {
{
boolean currentPlusState = asButtonState == 1;
boolean currentMinusState = asButtonState == 2;
ButtonState previousPlusState = InputManager.STATES.getOrDefault(axisAsButton(axis, true), ButtonState.NONE);
ButtonState previousMinusState = InputManager.STATES.getOrDefault(axisAsButton(axis, false), ButtonState.NONE);
var previousPlusState = InputManager.STATES.getOrDefault(axisAsButton(axis, true), ButtonState.NONE);
var previousMinusState = InputManager.STATES.getOrDefault(axisAsButton(axis, false), ButtonState.NONE);
if (currentPlusState != previousPlusState.isPressed()) {
InputManager.STATES.put(axisAsButton(axis, true), currentPlusState ? ButtonState.PRESS : ButtonState.RELEASE);
@@ -505,20 +499,18 @@ public class LambdaInput {
this.controlsInput.waiting = false;
}
return;
} else if (client.currentScreen instanceof CreativeInventoryScreen) {
} else if (client.currentScreen instanceof CreativeInventoryScreen creativeInventoryScreen) {
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
CreativeInventoryScreen screen = (CreativeInventoryScreen) client.currentScreen;
CreativeInventoryScreenAccessor accessor = (CreativeInventoryScreenAccessor) screen;
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
// @TODO allow rebinding to left stick
if (accessor.lambdacontrols$hasScrollbar() && absValue >= deadZone) {
screen.mouseScrolled(0.0, 0.0, -value);
creativeInventoryScreen.mouseScrolled(0.0, 0.0, -value);
}
return;
}
} else if (client.currentScreen instanceof AdvancementsScreen) {
} else if (client.currentScreen instanceof AdvancementsScreen advancementsScreen) {
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X || axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
AdvancementsScreen screen = (AdvancementsScreen) client.currentScreen;
AdvancementsScreenAccessor accessor = (AdvancementsScreenAccessor) screen;
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);
@@ -595,36 +587,32 @@ public class LambdaInput {
}
private boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
if (focused instanceof AbstractPressableButtonWidget) {
AbstractPressableButtonWidget widget = (AbstractPressableButtonWidget) focused;
if (focused instanceof PressableWidget widget) {
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
widget.onPress();
return true;
} else if (focused instanceof AbstractSprucePressableButtonWidget) {
AbstractSprucePressableButtonWidget widget = (AbstractSprucePressableButtonWidget) focused;
} else if (focused instanceof AbstractSprucePressableButtonWidget widget) {
widget.playDownSound();
widget.onPress();
return true;
} else if (focused instanceof SpruceLabelWidget) {
((SpruceLabelWidget) focused).onPress();
} else if (focused instanceof SpruceLabelWidget labelWidget) {
labelWidget.onPress();
return true;
} else if (focused instanceof WorldListWidget) {
WorldListWidget list = (WorldListWidget) focused;
} else if (focused instanceof WorldListWidget list) {
list.getSelectedAsOptional().ifPresent(WorldListWidget.Entry::play);
return true;
} else if (focused instanceof MultiplayerServerListWidget) {
MultiplayerServerListWidget list = (MultiplayerServerListWidget) focused;
MultiplayerServerListWidget.Entry entry = list.getSelected();
} 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) {
Element childFocused = ((SpruceParentWidget<?>) focused).getFocused();
var childFocused = ((SpruceParentWidget<?>) focused).getFocused();
if (childFocused != null)
return this.handleAButton(screen, childFocused);
} else if (focused instanceof ParentElement) {
Element childFocused = ((ParentElement) focused).getFocused();
} else if (focused instanceof ParentElement widget) {
var childFocused = widget.getFocused();
if (childFocused != null)
return this.handleAButton(screen, childFocused);
}
@@ -634,16 +622,16 @@ public class LambdaInput {
/**
* Handles the left and right buttons.
*
* @param screen The current screen.
* @param right True if the right button is pressed, else false.
* @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) screen).onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
if (screen instanceof SpruceScreen spruceScreen) {
spruceScreen.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
this.actionGuiCooldown = 5;
return false;
}
Element focused = screen.getFocused();
var focused = screen.getFocused();
if (focused != null)
if (this.handleRightLeftElement(focused, right))
return this.changeFocus(screen, right ? NavigationDirection.RIGHT : NavigationDirection.LEFT);
@@ -651,22 +639,20 @@ public class LambdaInput {
}
private boolean handleRightLeftElement(@NotNull Element element, boolean right) {
if (element instanceof SpruceElement) {
if (((SpruceElement) element).requiresCursor())
if (element instanceof SpruceElement spruceElement) {
if (spruceElement.requiresCursor())
return true;
return !((SpruceElement) element).onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
return !spruceElement.onNavigation(right ? NavigationDirection.RIGHT : NavigationDirection.LEFT, false);
}
if (element instanceof SliderWidget) {
SliderWidget slider = (SliderWidget) element;
if (element instanceof SliderWidget slider) {
slider.keyPressed(right ? 262 : 263, 0, 0);
this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
return false;
} else if (element instanceof AlwaysSelectedEntryListWidget) {
((EntryListWidgetAccessor) element).lambdacontrols$moveSelection(right ? EntryListWidget.MoveDirection.UP : EntryListWidget.MoveDirection.DOWN);
return false;
} else if (element instanceof ParentElement) {
ParentElement entryList = (ParentElement) element;
Element focused = entryList.getFocused();
} else if (element instanceof ParentElement entryList) {
var focused = entryList.getFocused();
if (focused == null)
return true;
return this.handleRightLeftElement(focused, right);
@@ -677,10 +663,10 @@ public class LambdaInput {
/**
* 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.
* @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) {
// Handles the look direction.
@@ -704,8 +690,8 @@ public class LambdaInput {
}
private boolean changeFocus(@NotNull Screen screen, NavigationDirection direction) {
if (screen instanceof SpruceScreen) {
if (((SpruceScreen) screen).onNavigation(direction, false)) {
if (screen instanceof SpruceScreen spruceScreen) {
if (spruceScreen.onNavigation(direction, false)) {
this.actionGuiCooldown = 5;
}
return false;
@@ -731,9 +717,8 @@ public class LambdaInput {
// 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) {
HandledScreen inventoryScreen = (HandledScreen) screen;
HandledScreenAccessor accessor = (HandledScreenAccessor) inventoryScreen;
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());
@@ -752,8 +737,8 @@ public class LambdaInput {
.min(Comparator.comparingDouble(p -> p.value));
if (closestSlot.isPresent()) {
Slot slot = closestSlot.get().key;
if (slot.hasStack() || !client.player.inventory.getMainHandStack().isEmpty()) {
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()));

View File

@@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Represents the reach-around API of LambdaControls.
*
* @version 1.5.0
* @version 1.7.0
* @since 1.3.2
*/
public class LambdaReacharound {
@@ -49,7 +49,7 @@ public class LambdaReacharound {
/**
* Returns the last reach around result.
*
* @return The last reach around result.
* @return the last reach around result
*/
public @Nullable BlockHitResult getLastReacharoundResult() {
return this.lastReacharoundResult;
@@ -58,7 +58,7 @@ public class LambdaReacharound {
/**
* Returns whether the last reach around is vertical.
*
* @return True if the reach around is vertical.
* @return {@code true} if the reach around is vertical
*/
public boolean isLastReacharoundVertical() {
return this.lastReacharoundVertical;
@@ -67,7 +67,7 @@ public class LambdaReacharound {
/**
* Returns whether reacharound is available or not.
*
* @return True if reacharound is available, else false.
* @return {@code true} if reacharound is available, else {@code false}
*/
public boolean isReacharoundAvailable() {
return LambdaControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || LambdaControlsFeature.VERTICAL_REACHAROUND.isAvailable();
@@ -80,22 +80,22 @@ public class LambdaReacharound {
/**
* 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 null.
* @param client the client instance
* @return a block hit result if vertical reach-around is possible, else {@code null}
*/
public @Nullable BlockHitResult tryVerticalReachAround(@NotNull MinecraftClient client) {
if (!LambdaControlsFeature.VERTICAL_REACHAROUND.isAvailable())
return null;
if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.MISS
|| !client.player.isOnGround() || client.player.pitch < 80.0F
|| !client.player.isOnGround() || client.player.getPitch(0.f) < 80.0F
|| client.player.isRiding())
return null;
Vec3d pos = client.player.getCameraPosVec(1.0F);
Vec3d rotationVec = client.player.getRotationVec(1.0F);
float range = getPlayerRange(client);
Vec3d rayVec = pos.add(rotationVec.x * range, rotationVec.y * range, rotationVec.z * range).add(0, 0.75, 0);
BlockHitResult result = client.world.raycast(new RaycastContext(pos, rayVec, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player));
var rayVec = pos.add(rotationVec.x * range, rotationVec.y * range, rotationVec.z * range).add(0, 0.75, 0);
var result = client.world.raycast(new RaycastContext(pos, rayVec, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player));
if (result.getType() == HitResult.Type.BLOCK) {
BlockPos blockPos = result.getBlockPos().down();
@@ -112,33 +112,34 @@ public class LambdaReacharound {
/**
* 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.
* @param client the client instance
* @return a block hit result if horizontal reach-around is possible
*/
public @Nullable BlockHitResult tryHorizontalReachAround(@NotNull MinecraftClient client) {
if (!LambdaControlsFeature.HORIZONTAL_REACHAROUND.isAvailable())
return null;
if (client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS && client.player.isOnGround() && client.player.pitch > 35.0F) {
if (client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS
&& client.player.isOnGround() && client.player.getPitch(0.f) > 35.f) {
if (client.player.isRiding())
return null;
BlockPos playerPos = client.player.getBlockPos().down();
var playerPos = client.player.getBlockPos().down();
if (client.player.getY() - playerPos.getY() - 1.0 >= 0.25) {
playerPos = playerPos.up();
this.onSlab = true;
} else {
this.onSlab = false;
}
BlockPos targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
BlockPos vector = new BlockPos(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
BlockPos blockPos = playerPos.add(vector);
var targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
var vector = new BlockPos.Mutable(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
var blockPos = playerPos.add(vector);
Direction direction = client.player.getHorizontalFacing();
var direction = client.player.getHorizontalFacing();
BlockState state = client.world.getBlockState(blockPos);
var state = client.world.getBlockState(blockPos);
if (!state.isAir())
return null;
BlockState adjacentBlockState = client.world.getBlockState(blockPos.offset(direction.getOpposite()));
var adjacentBlockState = client.world.getBlockState(blockPos.offset(direction.getOpposite()));
if (adjacentBlockState.isAir() || adjacentBlockState.getBlock() instanceof FluidBlock || (vector.getX() == 0 && vector.getZ() == 0)) {
return null;
}

View File

@@ -20,7 +20,7 @@ import java.util.Optional;
/**
* Represents the virtual mouse skins.
*
* @version 1.4.0
* @version 1.7.0
* @since 1.2.0
*/
public enum VirtualMouseSkin implements Nameable {
@@ -40,10 +40,10 @@ public enum VirtualMouseSkin implements Nameable {
/**
* Returns the next virtual mouse skin available.
*
* @return The next available virtual mouse skin.
* @return the next available virtual mouse skin
*/
public @NotNull VirtualMouseSkin next() {
VirtualMouseSkin[] v = values();
var v = values();
if (v.length == this.ordinal() + 1)
return v[0];
return v[this.ordinal() + 1];
@@ -52,7 +52,7 @@ public enum VirtualMouseSkin implements Nameable {
/**
* Returns the translation key of this virtual mouse skin.
*
* @return The virtual mouse skin's translation key.
* @return the virtual mouse skin's translation key
*/
public @NotNull String getTranslationKey() {
return "lambdacontrols.virtual_mouse.skin." + this.getName();
@@ -61,7 +61,7 @@ public enum VirtualMouseSkin implements Nameable {
/**
* Gets the translated text of this virtual mouse skin.
*
* @return The translated text of this virtual mouse skin.
* @return the translated text of this virtual mouse skin
*/
public @NotNull Text getTranslatedText() {
return this.text;
@@ -75,8 +75,8 @@ public enum VirtualMouseSkin implements Nameable {
/**
* Gets the virtual mouse skin from its identifier.
*
* @param id The identifier of the virtual mouse skin.
* @return The virtual mouse skin if found, else empty.
* @param id the identifier of the virtual mouse skin
* @return the virtual mouse skin if found, else empty
*/
public static @NotNull Optional<VirtualMouseSkin> byId(@NotNull String id) {
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();

View File

@@ -15,7 +15,6 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.screen.slot.Slot;
import net.minecraft.util.hit.BlockHitResult;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -23,22 +22,22 @@ import org.jetbrains.annotations.Nullable;
* Represents a compatibility handler for a mod.
*
* @author LambdAurora
* @version 1.5.0
* @version 1.7.0
* @since 1.1.0
*/
public interface CompatHandler {
/**
* Handles compatibility of a mod.
*
* @param mod This mod instance.
* @param mod this mod instance
*/
void handle(@NotNull LambdaControlsClient mod);
/**
* Returns whether the mouse is required on the specified screen.
*
* @param screen The screen.
* @return True if the mouse is required on the specified screen, else false.
* @param screen the screen
* @return true if the mouse is required on the specified screen, else false
*/
default boolean requireMouseOnScreen(Screen screen) {
return false;
@@ -47,22 +46,22 @@ public interface CompatHandler {
/**
* Returns a slot at the specified location if possible.
*
* @param screen The screen.
* @param mouseX The mouse X-coordinate.
* @param mouseY The mouse Y-coordinate.
* @return A slot if present, else null.
* @param screen the screen
* @param mouseX the mouse X-coordinate
* @param mouseY the mouse Y-coordinate
* @return a slot if present, else null
* @since 1.5.0
*/
default @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
default @Nullable CompatHandler.SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
return null;
}
/**
* Returns whether the current slot is a creative slot or not.
*
* @param screen The screen.
* @param slot The slot to check.
* @return True if the slot is a creative slot, else false.
* @param screen the screen
* @param slot the slot to check
* @return true if the slot is a creative slot, else false
*/
default boolean isCreativeSlot(@NotNull HandledScreen screen, @NotNull Slot slot) {
return false;
@@ -71,9 +70,9 @@ public interface CompatHandler {
/**
* Returns a custom translation key to make custom attack action strings on the HUD.
*
* @param client The client instance.
* @param placeResult The last place block result.
* @return Null if untouched, else a translation key.
* @param client the client instance
* @param placeResult the last place block result
* @return null if untouched, else a translation key
*/
default String getAttackActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
return null;
@@ -82,9 +81,9 @@ public interface CompatHandler {
/**
* Returns a custom translation key to make custom use action strings on the HUD.
*
* @param client The client instance.
* @param placeResult The last place block result.
* @return Null if untouched, else a translation key.
* @param client the client instance
* @param placeResult the last place block result
* @return null if untouched, else a translation key
*/
default String getUseActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
return null;
@@ -93,11 +92,15 @@ public interface CompatHandler {
/**
* Handles the menu back button.
*
* @param client The client instance.
* @param screen The screen.
* @return True if the handle was fired and succeed, else false.
* @param client the client instance
* @param screen the screen
* @return true if the handle was fired and succeed, else false
*/
default boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
return false;
}
record SlotPos(int x, int y) {
public static final SlotPos INVALID_SLOT = new SlotPos(-1, -1);
}
}

View File

@@ -16,7 +16,6 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.hit.BlockHitResult;
import org.aperlambda.lambdacommon.utils.LambdaReflection;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,17 +36,17 @@ public class LambdaControlsCompat {
/**
* Initializes compatibility with other mods if needed.
*
* @param mod The mod instance.
* @param mod the mod instance
*/
public static void init(@NotNull LambdaControlsClient mod) {
if (FabricLoader.getInstance().isModLoaded("okzoomer")) {
/*if (FabricLoader.getInstance().isModLoaded("okzoomer")) {
mod.log("Adding okzoomer compatibility...");
HANDLERS.add(new OkZoomerCompat());
}
if (isReiPresent()) {
mod.log("Adding REI compatiblity...");
HANDLERS.add(new ReiCompat());
}
}*/
if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
mod.log("Adding HQM compatibility...");
HANDLERS.add(new HQMCompat());
@@ -59,7 +58,7 @@ public class LambdaControlsCompat {
/**
* Registers a new compatibility handler.
*
* @param handler The compatibility handler to register.
* @param handler the compatibility handler to register
*/
public static void registerCompatHandler(@NotNull CompatHandler handler) {
HANDLERS.add(handler);
@@ -68,7 +67,7 @@ public class LambdaControlsCompat {
/**
* Streams through compatibility handlers.
*
* @return A stream of compatibility handlers.
* @return a stream of compatibility handlers
*/
public static Stream<CompatHandler> streamCompatHandlers() {
return HANDLERS.stream();
@@ -77,8 +76,8 @@ public class LambdaControlsCompat {
/**
* Returns whether the mouse is required on the specified screen.
*
* @param screen The screen.
* @return True if the mouse is requried on the specified screen, else false.
* @param screen the screen
* @return true if the mouse is requried on the specified screen, else false
*/
public static boolean requireMouseOnScreen(Screen screen) {
return HANDLERS.stream().anyMatch(handler -> handler.requireMouseOnScreen(screen));
@@ -87,14 +86,14 @@ public class LambdaControlsCompat {
/**
* Returns a slot at the specified location if possible.
*
* @param screen The screen.
* @param mouseX The mouse X-coordinate.
* @param mouseY The mouse Y-coordinate.
* @return A slot if present, else null.
* @param screen the screen
* @param mouseX the mouse X-coordinate
* @param mouseY the mouse Y-coordinate
* @return a slot if present, else null
*/
public static @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
for (CompatHandler handler : HANDLERS) {
Pair<Integer, Integer> slot = handler.getSlotAt(screen, mouseX, mouseY);
public static @Nullable CompatHandler.SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
for (var handler : HANDLERS) {
var slot = handler.getSlotAt(screen, mouseX, mouseY);
if (slot != null)
return slot;
}
@@ -104,9 +103,9 @@ public class LambdaControlsCompat {
/**
* Returns a custom translation key to make custom attack action strings on the HUD.
*
* @param client The client instance.
* @param placeResult The last place block result.
* @return Null if untouched, else a translation key.
* @param client the client instance
* @param placeResult the last place block result
* @return null if untouched, else a translation key
*/
public static String getAttackActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
for (CompatHandler handler : HANDLERS) {
@@ -121,9 +120,9 @@ public class LambdaControlsCompat {
/**
* Returns a custom translation key to make custom use action strings on the HUD.
*
* @param client The client instance.
* @param placeResult The last place block result.
* @return Null if untouched, else a translation key.
* @param client the client instance
* @param placeResult the last place block result
* @return null if untouched, else a translation key
*/
public static String getUseActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
for (CompatHandler handler : HANDLERS) {
@@ -138,9 +137,9 @@ public class LambdaControlsCompat {
/**
* Handles the menu back button.
*
* @param client The client instance.
* @param screen The screen.
* @return True if the handle was fired and succeed, else false.
* @param client the client instance
* @param screen the screen
* @return true if the handle was fired and succeed, else false
*/
public static boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
for (CompatHandler handler : HANDLERS) {
@@ -153,7 +152,7 @@ public class LambdaControlsCompat {
/**
* Returns whether Roughly Enough Items is present.
*
* @return True if Roughly Enough Items is present, else false.
* @return true if Roughly Enough Items is present, else false
*/
public static boolean isReiPresent() {
return FabricLoader.getInstance().isModLoaded("roughlyenoughitems");

View File

@@ -10,10 +10,7 @@
package dev.lambdaurora.lambdacontrols.client.compat;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import io.github.joaoh1.okzoomer.client.keybinds.ZoomKeybinds;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
/**
* Represents a compatibility handler for OkZoomer.
@@ -25,7 +22,7 @@ import org.lwjgl.glfw.GLFW;
public class OkZoomerCompat implements CompatHandler {
@Override
public void handle(@NotNull LambdaControlsClient mod) {
new ButtonBinding.Builder("zoom")
/*new ButtonBinding.Builder("zoom")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
.onlyInGame()
.cooldown(true)
@@ -54,6 +51,6 @@ public class OkZoomerCompat implements CompatHandler {
.category(ButtonBinding.MISC_CATEGORY)
.linkKeybind(ZoomKeybinds.resetZoomKey)
.register();
}
}*/
}
}

View File

@@ -11,48 +11,26 @@ package dev.lambdaurora.lambdacontrols.client.compat;
import dev.lambdaurora.lambdacontrols.client.ButtonState;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.compat.mixin.EntryListWidgetAccessor;
import dev.lambdaurora.lambdacontrols.client.compat.mixin.EntryWidgetAccessor;
import dev.lambdaurora.lambdacontrols.client.compat.mixin.RecipeViewingScreenAccessor;
import dev.lambdaurora.lambdacontrols.client.compat.mixin.VillagerRecipeViewingScreenAccessor;
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import dev.lambdaurora.lambdacontrols.client.controller.InputHandlers;
import dev.lambdaurora.lambdacontrols.client.controller.PressAction;
import me.shedaniel.rei.api.*;
import me.shedaniel.rei.gui.ContainerScreenOverlay;
import me.shedaniel.rei.gui.PreRecipeViewingScreen;
import me.shedaniel.rei.gui.RecipeViewingScreen;
import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
import me.shedaniel.rei.gui.widget.EntryListEntryWidget;
import me.shedaniel.rei.gui.widget.EntryListWidget;
import me.shedaniel.rei.gui.widget.EntryWidget;
import me.shedaniel.rei.gui.widget.WidgetWithBounds;
import me.shedaniel.rei.impl.ScreenHelper;
import me.shedaniel.rei.impl.widgets.ButtonWidget;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.Identifier;
import org.aperlambda.lambdacommon.utils.LambdaReflection;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Optional;
import static org.lwjgl.glfw.GLFW.*;
/**
* Represents a compatibility handler for REI.
*
* @author LambdAurora
* @version 1.5.0
* @version 1.7.0
* @since 1.2.0
*/
public class ReiCompat implements CompatHandler {
private static final Pair<Integer, Integer> INVALID_SLOT = new Pair<>(-1, -1);
private static EntryListWidget ENTRY_LIST_WIDGET;
//private static EntryListWidget ENTRY_LIST_WIDGET;
@Override
public void handle(@NotNull LambdaControlsClient mod) {
@@ -113,57 +91,57 @@ public class ReiCompat implements CompatHandler {
@Override
public boolean requireMouseOnScreen(Screen screen) {
return isViewingScreen(screen) || screen instanceof PreRecipeViewingScreen;
return isViewingScreen(screen) /*|| screen instanceof PreRecipeViewingScreen*/;
}
@Override
public @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
public @Nullable SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
/*var overlay = ScreenHelper.getOptionalOverlay();
if (overlay.isPresent() && overlay.get().isInside(mouseX, mouseY)) {
EntryListWidget widget = getEntryListWidget();
var widget = getEntryListWidget();
if (widget == null)
return null;
Pair<Integer, Integer> slot = this.getSlotAt(widget, mouseX, mouseY, false);
var slot = this.getSlotAt(widget, mouseX, mouseY, false);
if (slot != null && slot != INVALID_SLOT)
return slot;
} else if (isViewingScreen(screen)) {
for (Element element : screen.children()) {
Pair<Integer, Integer> slot = this.getSlotAt(element, mouseX, mouseY, true);
for (var element : screen.children()) {
var slot = this.getSlotAt(element, mouseX, mouseY, true);
if (slot != null && slot != INVALID_SLOT)
return slot;
}
}
}*/
return null;
}
private @Nullable Pair<Integer, Integer> getSlotAt(@NotNull Element element, int mouseX, int mouseY, boolean allowEmpty) {
if (element instanceof EntryWidget) {
EntryWidget entry = (EntryWidget) element;
/*private @Nullable SlotPos getSlotAt(@NotNull Element element, int mouseX, int mouseY, boolean allowEmpty) {
if (element instanceof EntryWidget entry) {
if (entry.containsMouse(mouseX, mouseY)) {
if (!allowEmpty && entry.entries().isEmpty())
return INVALID_SLOT;
return Pair.of(entry.getBounds().getX() + 1, entry.getBounds().getY() + 1);
return new SlotPos(entry.getBounds().getX() + 1, entry.getBounds().getY() + 1);
}
} else if (element instanceof EntryListWidget) {
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
for (EntryListEntryWidget entry : entries) {
Pair<Integer, Integer> slot = this.getSlotAt(entry, mouseX, mouseY, allowEmpty);
var slot = this.getSlotAt(entry, mouseX, mouseY, allowEmpty);
if (slot != null && slot != INVALID_SLOT)
return slot;
}
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds) {
for (Element child : ((WidgetWithBounds) element).children()) {
Pair<Integer, Integer> slot = this.getSlotAt(child, mouseX, mouseY, allowEmpty);
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds widgetWithBounds) {
for (var child : widgetWithBounds.children()) {
var slot = this.getSlotAt(child, mouseX, mouseY, allowEmpty);
if (slot != null && slot != INVALID_SLOT)
return slot;
}
}
return null;
}
}*/
private static boolean isViewingScreen(Screen screen) {
return screen instanceof RecipeViewingScreen || screen instanceof VillagerRecipeViewingScreen;
return true;
//return screen instanceof DefaultDisplayViewingScreen || screen instanceof CompositeDisplayViewingScreen;
}
@Override
@@ -171,12 +149,12 @@ public class ReiCompat implements CompatHandler {
if (!isViewingScreen(screen))
return false;
MinecraftClient.getInstance().openScreen(REIHelper.getInstance().getPreviousContainerScreen());
ScreenHelper.getLastOverlay().init();
/*MinecraftClient.getInstance().openScreen(REIRuntimeImpl.getInstance().getPreviousContainerScreen());
ScreenHelper.getLastOverlay().init();*/
return true;
}
private static EntryListWidget getEntryListWidget() {
/*private static EntryListWidget getEntryListWidget() {
if (ENTRY_LIST_WIDGET == null) {
ENTRY_LIST_WIDGET = LambdaReflection.getFirstFieldOfType(ContainerScreenOverlay.class, EntryListWidget.class)
.map(field -> (EntryListWidget) LambdaReflection.getFieldValue(null, field))
@@ -190,17 +168,17 @@ public class ReiCompat implements CompatHandler {
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
if (isViewingScreen(client.currentScreen)) {
for (Element element : client.currentScreen.children()) {
EntryStack stack = getCurrentStack(element, x, y);
for (var element : client.currentScreen.children()) {
var stack = getCurrentStack(element, x, y);
if (stack != null)
return stack;
}
}
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
var overlay = ScreenHelper.getOptionalOverlay();
if (!overlay.isPresent())
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
EntryListWidget widget = getEntryListWidget();
var widget = getEntryListWidget();
if (widget == null)
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
@@ -208,33 +186,32 @@ public class ReiCompat implements CompatHandler {
}
private static @Nullable EntryStack getCurrentStack(@NotNull Element element, double mouseX, double mouseY) {
if (element instanceof EntryWidget) {
EntryWidget entry = (EntryWidget) element;
if (element instanceof EntryWidget entry) {
if (entry.containsMouse(mouseX, mouseY))
return ((EntryWidgetAccessor) entry).lambdacontrols_getCurrentEntry();
} else if (element instanceof EntryListWidget) {
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
var entries = ((EntryListWidgetAccessor) element).getEntries();
for (EntryListEntryWidget entry : entries) {
if (entry.containsMouse(mouseX, mouseY)) {
return ((EntryWidgetAccessor) entry).lambdacontrols_getCurrentEntry();
}
}
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds) {
for (Element child : ((WidgetWithBounds) element).children()) {
EntryStack stack = getCurrentStack(child, mouseX, mouseY);
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds widgetWithBounds) {
for (var child : widgetWithBounds.children()) {
var stack = getCurrentStack(child, mouseX, mouseY);
if (stack != null)
return stack;
}
}
return null;
}
}*/
private static PressAction handleShowRecipeUsage(boolean usage) {
return (client, button, value, action) -> {
if (action.isUnpressed())
return false;
EntryStack stack = RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
/*EntryStack stack = RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
if (stack == null) {
stack = getCurrentStack(client);
}
@@ -246,7 +223,7 @@ public class ReiCompat implements CompatHandler {
} else {
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addRecipesFor(stack).setOutputNotice(stack).fillPreferredOpenedCategory());
}
}
}*/
return false;
};
@@ -257,11 +234,11 @@ public class ReiCompat implements CompatHandler {
if (action == ButtonState.RELEASE)
return false;
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
/*Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
if (!overlay.isPresent())
return false;
EntryListWidget widget = getEntryListWidget();
var widget = getEntryListWidget();
if (widget == null)
return false;
@@ -269,7 +246,7 @@ public class ReiCompat implements CompatHandler {
widget.nextPage();
else
widget.previousPage();
widget.updateEntriesPosition();
widget.updateEntriesPosition();*/
return true;
};
@@ -286,14 +263,14 @@ public class ReiCompat implements CompatHandler {
if (action != ButtonState.RELEASE)
return false;
if (client.currentScreen instanceof RecipeViewingScreen) {
/*if (client.currentScreen instanceof DefaultDisplayViewingScreen) {
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
if (next)
screen.getCategoryNext().onClick();
else
screen.getCategoryBack().onClick();
return true;
} else if (client.currentScreen instanceof VillagerRecipeViewingScreen) {
} else if (client.currentScreen instanceof CompositeDisplayViewingScreen) {
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
List<RecipeCategory<?>> categories = screen.getCategories();
int currentTab = screen.getSelectedCategoryIndex();
@@ -301,7 +278,7 @@ public class ReiCompat implements CompatHandler {
screen.setSelectedRecipeIndex(0);
screen.lambdacontrols_init();
return true;
}
}*/
return false;
};
}
@@ -311,15 +288,13 @@ public class ReiCompat implements CompatHandler {
if (action.isUnpressed())
return false;
if (client.currentScreen instanceof RecipeViewingScreen) {
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
/*if (client.currentScreen instanceof RecipeViewingScreenAccessor screen) {
if (next)
screen.getRecipeNext().onClick();
else
screen.getRecipeBack().onClick();
return true;
} else if (client.currentScreen instanceof VillagerRecipeViewingScreen) {
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
} else if (client.currentScreen instanceof VillagerRecipeViewingScreenAccessor screen) {
List<RecipeCategory<?>> categories = screen.getCategories();
int currentTab = screen.getSelectedCategoryIndex();
List<RecipeDisplay> recipes = screen.getCategoryMap().get(categories.get(currentTab));
@@ -343,7 +318,7 @@ public class ReiCompat implements CompatHandler {
screen.lambdacontrols_init();
return true;
}
}*/
return false;
};

View File

@@ -9,13 +9,6 @@
package dev.lambdaurora.lambdacontrols.client.compat.mixin;
import me.shedaniel.rei.gui.widget.EntryListEntryWidget;
import me.shedaniel.rei.gui.widget.EntryListWidget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
/**
* Represents an accessor to REI's EntryListWidget.
*
@@ -23,8 +16,8 @@ import java.util.List;
* @version 1.5.0
* @since 1.5.0
*/
@Mixin(value = EntryListWidget.class, remap = false)
//@Mixin(value = EntryListWidget.class, remap = false)
public interface EntryListWidgetAccessor {
@Accessor(value = "entries")
List<EntryListEntryWidget> getEntries();
/*@Accessor(value = "entries")
List<EntryListEntryWidget> getEntries();*/
}

View File

@@ -9,11 +9,6 @@
package dev.lambdaurora.lambdacontrols.client.compat.mixin;
import me.shedaniel.rei.api.EntryStack;
import me.shedaniel.rei.gui.widget.EntryWidget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
/**
* Represents an accessor to REI's EntryWidget.
*
@@ -21,8 +16,8 @@ import org.spongepowered.asm.mixin.gen.Invoker;
* @version 1.5.0
* @since 1.5.0
*/
@Mixin(value = EntryWidget.class, remap = false)
//@Mixin(value = EntryWidget.class, remap = false)
public interface EntryWidgetAccessor {
@Invoker("getCurrentEntry")
EntryStack lambdacontrols_getCurrentEntry();
/*@Invoker("getCurrentEntry")
EntryStack lambdacontrols_getCurrentEntry();*/
}

View File

@@ -9,21 +9,16 @@
package dev.lambdaurora.lambdacontrols.client.compat.mixin;
import me.shedaniel.rei.api.widgets.Button;
import me.shedaniel.rei.gui.RecipeViewingScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
/**
* Represents an accessor to REI's RecipeViewingScreen.
*
* @author LambdAurora
* @version 1.5.0
* @version 1.7.0
* @since 1.2.0
*/
@Mixin(value = RecipeViewingScreen.class, remap = false)
//@Mixin(value = DefaultDisplayViewingScreen.class, remap = false)
public interface RecipeViewingScreenAccessor {
@Accessor("categoryBack")
/*@Accessor("categoryBack")
Button getCategoryBack();
@Accessor("categoryNext")
@@ -33,5 +28,5 @@ public interface RecipeViewingScreenAccessor {
Button getRecipeBack();
@Accessor("recipeNext")
Button getRecipeNext();
Button getRecipeNext();*/
}

View File

@@ -9,31 +9,20 @@
package dev.lambdaurora.lambdacontrols.client.compat.mixin;
import me.shedaniel.clothconfig2.api.ScrollingContainer;
import me.shedaniel.rei.api.RecipeCategory;
import me.shedaniel.rei.api.RecipeDisplay;
import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.List;
import java.util.Map;
/**
* Represents an accessor to REI's VillagerRecipeViewingScreen.
*
* @author LambdAurora
* @version 1.5.0
* @version 1.7.0
* @since 1.2.0
*/
@Mixin(VillagerRecipeViewingScreen.class)
//@Mixin(CompositeDisplayViewingScreen.class)
public interface VillagerRecipeViewingScreenAccessor {
@Accessor(value = "categoryMap", remap = false)
Map<RecipeCategory<?>, List<RecipeDisplay>> getCategoryMap();
/*@Accessor(value = "categoryMap", remap = false)
Map<DisplayCategory<?>, List<Display>> getCategoryMap();
@Accessor(value = "categories", remap = false)
List<RecipeCategory<?>> getCategories();
List<DisplayCategory<?>> getCategories();
@Accessor(value = "selectedCategoryIndex", remap = false)
int getSelectedCategoryIndex();
@@ -51,5 +40,5 @@ public interface VillagerRecipeViewingScreenAccessor {
ScrollingContainer getScrolling();
@Invoker("init")
void lambdacontrols_init();
void lambdacontrols_init();*/
}

View File

@@ -11,8 +11,8 @@ package dev.lambdaurora.lambdacontrols.client.controller;
import dev.lambdaurora.lambdacontrols.client.ButtonState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.GameOptions;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import org.aperlambda.lambdacommon.Identifier;
@@ -31,7 +31,7 @@ import static org.lwjgl.glfw.GLFW.*;
* Represents a button binding.
*
* @author LambdAurora
* @version 1.5.0
* @version 1.7.0
* @since 1.0.0
*/
public class ButtonBinding implements Nameable {
@@ -89,12 +89,12 @@ public class ButtonBinding implements Nameable {
private final Text text;
private KeyBinding mcKeyBinding = null;
protected PairPredicate<MinecraftClient, ButtonBinding> filter;
private List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
private final List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
private boolean hasCooldown;
private int cooldown = 0;
boolean pressed = false;
public ButtonBinding(@NotNull String key, int[] defaultButton, @NotNull List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
this.setButton(this.defaultButton = defaultButton);
this.key = key;
this.text = new TranslatableText(this.key);
@@ -103,14 +103,14 @@ public class ButtonBinding implements Nameable {
this.hasCooldown = hasCooldown;
}
public ButtonBinding(@NotNull String key, int[] defaultButton, boolean hasCooldown) {
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown) {
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown);
}
/**
* Returns the button bound.
*
* @return The bound button.
* @return the bound button
*/
public int[] getButton() {
return this.button;
@@ -119,7 +119,7 @@ public class ButtonBinding implements Nameable {
/**
* Sets the bound button.
*
* @param button The bound button.
* @param button the bound button
*/
public void setButton(int[] button) {
this.button = button;
@@ -131,8 +131,8 @@ public class ButtonBinding implements Nameable {
/**
* Returns whether the bound button is the specified button or not.
*
* @param button The button to check.
* @return True if the bound button is the specified button, else false.
* @param button the button to check
* @return true if the bound button is the specified button, else false
*/
public boolean isButton(int[] button) {
return InputManager.areButtonsEquivalent(button, this.button);
@@ -141,7 +141,7 @@ public class ButtonBinding implements Nameable {
/**
* Returns whether this button is down or not.
*
* @return True if the button is down, else false.
* @return true if the button is down, else false
*/
public boolean isButtonDown() {
return this.pressed;
@@ -150,7 +150,7 @@ public class ButtonBinding implements Nameable {
/**
* Returns whether this button binding is bound or not.
*
* @return True if this button binding is bound, else false.
* @return true if this button binding is bound, else false
*/
public boolean isNotBound() {
return this.button.length == 0 || this.button[0] == -1;
@@ -159,7 +159,7 @@ public class ButtonBinding implements Nameable {
/**
* Gets the default button assigned to this binding.
*
* @return The default button.
* @return the default button
*/
public int[] getDefaultButton() {
return this.defaultButton;
@@ -168,7 +168,7 @@ public class ButtonBinding implements Nameable {
/**
* Returns whether the assigned button is the default button.
*
* @return True if the assigned button is the default button, else false.
* @return true if the assigned button is the default button, else false
*/
public boolean isDefault() {
return this.button.length == this.defaultButton.length && InputManager.areButtonsEquivalent(this.button, this.defaultButton);
@@ -177,10 +177,9 @@ public class ButtonBinding implements Nameable {
/**
* Returns the button code.
*
* @return The button code.
* @return the button code
*/
public @NotNull
String getButtonCode() {
public String getButtonCode() {
return Arrays.stream(this.button)
.mapToObj(btn -> Integer.valueOf(btn).toString())
.collect(Collectors.joining("+"));
@@ -189,7 +188,7 @@ public class ButtonBinding implements Nameable {
/**
* Sets the key binding to emulate with this button binding.
*
* @param keyBinding The optional key binding.
* @param keyBinding the optional key binding
*/
public void setKeyBinding(@Nullable KeyBinding keyBinding) {
this.mcKeyBinding = keyBinding;
@@ -198,8 +197,8 @@ public class ButtonBinding implements Nameable {
/**
* 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.
* @param client the client instance
* @return true if the button binding is available, else false
*/
public boolean isAvailable(@NotNull MinecraftClient client) {
return this.filter.test(client, this);
@@ -216,8 +215,8 @@ public class ButtonBinding implements Nameable {
/**
* Handles the button binding.
*
* @param client The client instance.
* @param state The state.
* @param client the client instance
* @param state the state
*/
public void handle(@NotNull MinecraftClient client, float value, @NotNull ButtonState state) {
if (state == ButtonState.REPEAT && this.hasCooldown && this.cooldown != 0)
@@ -239,7 +238,7 @@ public class ButtonBinding implements Nameable {
/**
* Returns the translation key of this button binding.
*
* @return The translation key.
* @return the translation key
*/
public @NotNull String getTranslationKey() {
return "lambdacontrols.action." + this.getName();
@@ -252,7 +251,7 @@ public class ButtonBinding implements Nameable {
/**
* Returns the key binding equivalent of this button binding.
*
* @return The key binding equivalent.
* @return the key binding equivalent
*/
public @NotNull Optional<KeyBinding> asKeyBinding() {
return Optional.ofNullable(this.mcKeyBinding);
@@ -268,9 +267,9 @@ public class ButtonBinding implements Nameable {
/**
* Returns the specified axis as a button.
*
* @param axis The axis.
* @param positive True if the axis part is positive, else false.
* @return The axis as a button.
* @param axis the axis
* @param positive true if the axis part is positive, else false
* @return the axis as a button
*/
public static int axisAsButton(int axis, boolean positive) {
return positive ? 100 + axis : 200 + axis;
@@ -279,8 +278,8 @@ public class ButtonBinding implements Nameable {
/**
* Returns whether the specified button is an axis or not.
*
* @param button The button.
* @return True if the button is an axis, else false.
* @param button the button
* @return true if the button is an axis, else false
*/
public static boolean isAxis(int button) {
button %= 500;
@@ -290,8 +289,8 @@ public class ButtonBinding implements Nameable {
/**
* Returns the second Joycon's specified button code.
*
* @param button The raw button code.
* @return The second Joycon's button code.
* @param button the raw button code
* @return the second Joycon's button code
*/
public static int controller2Button(int button) {
return 500 + button;
@@ -321,66 +320,39 @@ public class ButtonBinding implements Nameable {
/**
* Returns the localized name of the specified button.
*
* @param button The button.
* @return The localized name of the button.
* @param button the button
* @return the localized name of the button
*/
public static @NotNull Text getLocalizedButtonName(int button) {
switch (button % 500) {
case -1:
return new TranslatableText("key.keyboard.unknown");
case GLFW_GAMEPAD_BUTTON_A:
return new TranslatableText("lambdacontrols.button.a");
case GLFW_GAMEPAD_BUTTON_B:
return new TranslatableText("lambdacontrols.button.b");
case GLFW_GAMEPAD_BUTTON_X:
return new TranslatableText("lambdacontrols.button.x");
case GLFW_GAMEPAD_BUTTON_Y:
return new TranslatableText("lambdacontrols.button.y");
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
return new TranslatableText("lambdacontrols.button.left_bumper");
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
return new TranslatableText("lambdacontrols.button.right_bumper");
case GLFW_GAMEPAD_BUTTON_BACK:
return new TranslatableText("lambdacontrols.button.back");
case GLFW_GAMEPAD_BUTTON_START:
return new TranslatableText("lambdacontrols.button.start");
case GLFW_GAMEPAD_BUTTON_GUIDE:
return new TranslatableText("lambdacontrols.button.guide");
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
return new TranslatableText("lambdacontrols.button.left_thumb");
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
return new TranslatableText("lambdacontrols.button.right_thumb");
case GLFW_GAMEPAD_BUTTON_DPAD_UP:
return new TranslatableText("lambdacontrols.button.dpad_up");
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT:
return new TranslatableText("lambdacontrols.button.dpad_right");
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN:
return new TranslatableText("lambdacontrols.button.dpad_down");
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT:
return new TranslatableText("lambdacontrols.button.dpad_left");
case 100:
return new TranslatableText("lambdacontrols.axis.left_x+");
case 101:
return new TranslatableText("lambdacontrols.axis.left_y+");
case 102:
return new TranslatableText("lambdacontrols.axis.right_x+");
case 103:
return new TranslatableText("lambdacontrols.axis.right_y+");
case 104:
return new TranslatableText("lambdacontrols.axis.left_trigger");
case 105:
return new TranslatableText("lambdacontrols.axis.right_trigger");
case 200:
return new TranslatableText("lambdacontrols.axis.left_x-");
case 201:
return new TranslatableText("lambdacontrols.axis.left_y-");
case 202:
return new TranslatableText("lambdacontrols.axis.right_x-");
case 203:
return new TranslatableText("lambdacontrols.axis.right_y-");
default:
return new TranslatableText("lambdacontrols.button.unknown", button);
}
return switch (button % 500) {
case -1 -> new TranslatableText("key.keyboard.unknown");
case GLFW_GAMEPAD_BUTTON_A -> new TranslatableText("lambdacontrols.button.a");
case GLFW_GAMEPAD_BUTTON_B -> new TranslatableText("lambdacontrols.button.b");
case GLFW_GAMEPAD_BUTTON_X -> new TranslatableText("lambdacontrols.button.x");
case GLFW_GAMEPAD_BUTTON_Y -> new TranslatableText("lambdacontrols.button.y");
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER -> new TranslatableText("lambdacontrols.button.left_bumper");
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER -> new TranslatableText("lambdacontrols.button.right_bumper");
case GLFW_GAMEPAD_BUTTON_BACK -> new TranslatableText("lambdacontrols.button.back");
case GLFW_GAMEPAD_BUTTON_START -> new TranslatableText("lambdacontrols.button.start");
case GLFW_GAMEPAD_BUTTON_GUIDE -> new TranslatableText("lambdacontrols.button.guide");
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB -> new TranslatableText("lambdacontrols.button.left_thumb");
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB -> new TranslatableText("lambdacontrols.button.right_thumb");
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> new TranslatableText("lambdacontrols.button.dpad_up");
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> new TranslatableText("lambdacontrols.button.dpad_right");
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> new TranslatableText("lambdacontrols.button.dpad_down");
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> new TranslatableText("lambdacontrols.button.dpad_left");
case 100 -> new TranslatableText("lambdacontrols.axis.left_x+");
case 101 -> new TranslatableText("lambdacontrols.axis.left_y+");
case 102 -> new TranslatableText("lambdacontrols.axis.right_x+");
case 103 -> new TranslatableText("lambdacontrols.axis.right_y+");
case 104 -> new TranslatableText("lambdacontrols.axis.left_trigger");
case 105 -> new TranslatableText("lambdacontrols.axis.right_trigger");
case 200 -> new TranslatableText("lambdacontrols.axis.left_x-");
case 201 -> new TranslatableText("lambdacontrols.axis.left_y-");
case 202 -> new TranslatableText("lambdacontrols.axis.right_x-");
case 203 -> new TranslatableText("lambdacontrols.axis.right_y-");
default -> new TranslatableText("lambdacontrols.button.unknown", button);
};
}
static {
@@ -416,8 +388,8 @@ public class ButtonBinding implements Nameable {
/**
* Returns a builder instance.
*
* @param identifier The identifier of the button binding.
* @return The builder instance
* @param identifier the identifier of the button binding
* @return the builder instanc
* @since 1.5.0
*/
public static Builder builder(@NotNull Identifier identifier) {
@@ -427,8 +399,8 @@ public class ButtonBinding implements Nameable {
/**
* Returns a builder instance.
*
* @param identifier The identifier of the button binding.
* @return The builder instance.
* @param identifier the identifier of the button binding
* @return the builder instance
* @since 1.5.0
*/
public static Builder builder(@NotNull net.minecraft.util.Identifier identifier) {
@@ -446,7 +418,7 @@ public class ButtonBinding implements Nameable {
public static class Builder {
private final String key;
private int[] buttons = new int[0];
private List<PressAction> actions = new ArrayList<>();
private final List<PressAction> actions = new ArrayList<>();
private PairPredicate<MinecraftClient, ButtonBinding> filter = Predicates.pairAlwaysTrue();
private boolean cooldown = false;
private ButtonCategory category = null;
@@ -455,7 +427,7 @@ public class ButtonBinding implements Nameable {
/**
* This constructor shouldn't be used for other mods.
*
* @param key The key with format {@code "<namespace>.<name>"}.
* @param key the key with format {@code "<namespace>.<name>"}
*/
public Builder(@NotNull String key) {
this.key = key;
@@ -473,8 +445,8 @@ public class ButtonBinding implements Nameable {
/**
* Defines the default buttons of the {@link ButtonBinding}.
*
* @param buttons The default buttons.
* @return The builder instance.
* @param buttons the default buttons
* @return the builder instance
*/
public Builder buttons(int... buttons) {
this.buttons = buttons;
@@ -484,7 +456,7 @@ public class ButtonBinding implements Nameable {
/**
* Sets the {@link ButtonBinding} to unbound.
*
* @return The builder instance.
* @return the builder instance
*/
public Builder unbound() {
return this.buttons(-1);
@@ -493,8 +465,8 @@ public class ButtonBinding implements Nameable {
/**
* Adds the actions to the {@link ButtonBinding}.
*
* @param actions The actions to add.
* @return The builder instance.
* @param actions the actions to add
* @return the builder instance
*/
public Builder actions(@NotNull PressAction... actions) {
this.actions.addAll(Arrays.asList(actions));
@@ -504,8 +476,8 @@ public class ButtonBinding implements Nameable {
/**
* Adds an action to the {@link ButtonBinding}.
*
* @param action The action to add.
* @return The builder instance.
* @param action the action to add
* @return the builder instance
*/
public Builder action(@NotNull PressAction action) {
this.actions.add(action);
@@ -515,8 +487,8 @@ public class ButtonBinding implements Nameable {
/**
* Sets a filter for the {@link ButtonBinding}.
*
* @param filter The filter.
* @return The builder instance.
* @param filter the filter
* @return the builder instance
*/
public Builder filter(@NotNull PairPredicate<MinecraftClient, ButtonBinding> filter) {
this.filter = filter;
@@ -526,7 +498,7 @@ public class ButtonBinding implements Nameable {
/**
* Sets the filter of {@link ButtonBinding} to only in game.
*
* @return The builder instance.
* @return the builder instance
* @see #filter(PairPredicate)
* @see InputHandlers#inGame(MinecraftClient, ButtonBinding)
*/
@@ -537,7 +509,7 @@ public class ButtonBinding implements Nameable {
/**
* Sets the filter of {@link ButtonBinding} to only in inventory.
*
* @return The builder instance.
* @return the builder instance
* @see #filter(PairPredicate)
* @see InputHandlers#inInventory(MinecraftClient, ButtonBinding)
*/
@@ -548,8 +520,8 @@ public class ButtonBinding implements Nameable {
/**
* Sets whether the {@link ButtonBinding} has a cooldown or not.
*
* @param cooldown True if the {@link ButtonBinding} has a cooldown, else false.
* @return The builder instance.
* @param cooldown true if the {@link ButtonBinding} has a cooldown, else false
* @return the builder instance
*/
public Builder cooldown(boolean cooldown) {
this.cooldown = cooldown;
@@ -559,7 +531,7 @@ public class ButtonBinding implements Nameable {
/**
* Puts a cooldown on the {@link ButtonBinding}.
*
* @return The builder instance.
* @return the builder instance
* @since 1.5.0
*/
public Builder cooldown() {
@@ -569,8 +541,8 @@ public class ButtonBinding implements Nameable {
/**
* Sets the category of the {@link ButtonBinding}.
*
* @param category The category.
* @return The builder instance.
* @param category the category
* @return the builder instance
*/
public Builder category(@Nullable ButtonCategory category) {
this.category = category;
@@ -580,8 +552,8 @@ public class ButtonBinding implements Nameable {
/**
* Sets the keybinding linked to the {@link ButtonBinding}.
*
* @param binding The keybinding to link.
* @return The builder instance.
* @param binding the keybinding to link
* @return the builder instance
*/
public Builder linkKeybind(@Nullable KeyBinding binding) {
this.mcBinding = binding;
@@ -591,10 +563,10 @@ public class ButtonBinding implements Nameable {
/**
* Builds the {@link ButtonBinding}.
*
* @return The built {@link ButtonBinding}.
* @return the built {@link ButtonBinding}
*/
public ButtonBinding build() {
ButtonBinding binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown);
var binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown);
if (this.category != null)
this.category.registerBinding(binding);
if (this.mcBinding != null)
@@ -605,7 +577,7 @@ public class ButtonBinding implements Nameable {
/**
* Builds and registers the {@link ButtonBinding}.
*
* @return The built {@link ButtonBinding}.
* @return the built {@link ButtonBinding}
* @see #build()
*/
public ButtonBinding register() {

View File

@@ -29,7 +29,7 @@ import java.util.List;
public class ButtonCategory implements Identifiable {
private final List<ButtonBinding> bindings = new ArrayList<>();
private final Identifier id;
private int priority;
private final int priority;
public ButtonCategory(@NotNull Identifier id, int priority) {
this.id = id;
@@ -57,7 +57,7 @@ public class ButtonCategory implements Identifiable {
/**
* Gets the bindings assigned to this category.
*
* @return The bindings assigned to this category.
* @return the bindings assigned to this category
*/
public @NotNull List<ButtonBinding> getBindings() {
return Collections.unmodifiableList(this.bindings);
@@ -68,7 +68,7 @@ public class ButtonCategory implements Identifiable {
* <p>
* The translation key should be `modid.identifier_name`.
*
* @return The translated name.
* @return the translated name
*/
public @NotNull String getTranslatedName() {
if (this.id.getNamespace().equals("minecraft"))
@@ -81,7 +81,7 @@ public class ButtonCategory implements Identifiable {
* Gets the priority display of this category.
* It will defines in which order the categories will display on the controls screen.
*
* @return The priority of this category.
* @return the priority of this category
*/
public int getPriority() {
return this.priority;

View File

@@ -17,18 +17,14 @@ import net.minecraft.text.LiteralText;
import net.minecraft.text.TranslatableText;
import org.aperlambda.lambdacommon.utils.Nameable;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWGamepadState;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.HashMap;
@@ -41,30 +37,16 @@ import static org.lwjgl.BufferUtils.createByteBuffer;
* Represents a controller.
*
* @author LambdAurora
* @version 1.4.3
* @version 1.7.0
* @since 1.0.0
*/
public class Controller implements Nameable {
public record Controller(int id) implements Nameable {
private static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
private final int id;
public Controller(int id) {
this.id = id;
}
/**
* Gets the identifier of this controller.
*
* @return The identifier of this controller.
*/
public int getId() {
return this.id;
}
/**
* Gets the controller's globally unique identifier.
*
* @return The controller's GUID.
* @return the controller's GUID
*/
public String getGuid() {
String guid = GLFW.glfwGetJoystickGUID(this.id);
@@ -74,7 +56,7 @@ public class Controller implements Nameable {
/**
* Returns whether this controller is connected or not.
*
* @return True if this controller is connected, else false.
* @return true if this controller is connected, else false
*/
public boolean isConnected() {
return GLFW.glfwJoystickPresent(this.id);
@@ -83,7 +65,7 @@ public class Controller implements Nameable {
/**
* Returns whether this controller is a gamepad or not.
*
* @return True if this controller is a gamepad, else false.
* @return true if this controller is a gamepad, else false
*/
public boolean isGamepad() {
return this.isConnected() && GLFW.glfwJoystickIsGamepad(this.id);
@@ -92,27 +74,27 @@ public class Controller implements Nameable {
/**
* Gets the name of the controller.
*
* @return The controller's name.
* @return the controller's name
*/
@Override
public @NotNull String getName() {
String name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
return name == null ? String.valueOf(this.getId()) : name;
public String getName() {
var name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
return name == null ? String.valueOf(this.id()) : name;
}
/**
* Gets the state of the controller.
*
* @return The state of the controller input.
* @return the state of the controller input
*/
public GLFWGamepadState getState() {
GLFWGamepadState state = GLFWGamepadState.create();
var state = GLFWGamepadState.create();
if (this.isGamepad())
GLFW.glfwGetGamepadState(this.id, state);
return state;
}
public static @NotNull Controller byId(int id) {
public static Controller byId(int id) {
if (id > GLFW.GLFW_JOYSTICK_LAST) {
LambdaControlsClient.get().log("Controller '" + id + "' doesn't exist.");
id = GLFW.GLFW_JOYSTICK_LAST;
@@ -127,33 +109,33 @@ public class Controller implements Nameable {
}
}
public static @NotNull Optional<Controller> byGuid(@NotNull String guid) {
public static Optional<Controller> byGuid(@NotNull String guid) {
return CONTROLLERS.values().stream().filter(Controller::isConnected)
.filter(controller -> controller.getGuid().equals(guid))
.max(Comparator.comparingInt(Controller::getId));
.max(Comparator.comparingInt(Controller::id));
}
/**
* Reads the specified resource and returns the raw data as a ByteBuffer.
*
* @param resource The resource to read.
* @param bufferSize The initial buffer size.
* @return The resource data.
* @param resource the resource to read
* @param bufferSize the initial buffer size
* @return the resource data
* @throws IOException If an IO error occurs.
*/
private static ByteBuffer ioResourceToBuffer(String resource, int bufferSize) throws IOException {
ByteBuffer buffer = null;
Path path = Paths.get(resource);
var path = Paths.get(resource);
if (Files.isReadable(path)) {
try (SeekableByteChannel fc = Files.newByteChannel(path)) {
try (var fc = Files.newByteChannel(path)) {
buffer = createByteBuffer((int) fc.size() + 2);
while (fc.read(buffer) != -1) ;
buffer.put((byte) 0);
}
}
((Buffer) buffer).flip(); // Force Java 8 >.<
buffer.flip(); // Force Java 8 >.<
return buffer;
}
@@ -165,20 +147,19 @@ public class Controller implements Nameable {
if (!LambdaControlsClient.MAPPINGS_FILE.exists())
return;
LambdaControlsClient.get().log("Updating controller mappings...");
ByteBuffer buffer = ioResourceToBuffer(LambdaControlsClient.MAPPINGS_FILE.getPath(), 1024);
var buffer = ioResourceToBuffer(LambdaControlsClient.MAPPINGS_FILE.getPath(), 1024);
GLFW.glfwUpdateGamepadMappings(buffer);
} catch (IOException e) {
e.printStackTrace();
}
MemoryStack memoryStack = MemoryStack.stackPush();
try {
PointerBuffer pointerBuffer = memoryStack.mallocPointer(1);
try (var memoryStack = MemoryStack.stackPush()) {
var pointerBuffer = memoryStack.mallocPointer(1);
int i = GLFW.glfwGetError(pointerBuffer);
if (i != 0) {
long l = pointerBuffer.get();
String string = l == 0L ? "" : MemoryUtil.memUTF8(l);
MinecraftClient client = MinecraftClient.getInstance();
var string = l == 0L ? "" : MemoryUtil.memUTF8(l);
var client = MinecraftClient.getInstance();
if (client != null) {
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
new TranslatableText("lambdacontrols.controller.mappings.error"), new LiteralText(string)));
@@ -186,13 +167,11 @@ public class Controller implements Nameable {
}
} catch (Throwable e) {
/* Ignored :concern: */
} finally {
memoryStack.close();
}
if (LambdaControlsClient.get().config.hasDebug()) {
for (int i = GLFW.GLFW_JOYSTICK_1; i <= GLFW.GLFW_JOYSTICK_16; i++) {
Controller controller = byId(i);
var controller = byId(i);
if (!controller.isConnected())
continue;

View File

@@ -16,20 +16,16 @@ import dev.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccess
import dev.lambdaurora.lambdacontrols.client.mixin.RecipeBookWidgetAccessor;
import dev.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
import net.minecraft.client.MinecraftClient;
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.InventoryScreen;
import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget;
import net.minecraft.client.util.ScreenshotUtils;
import net.minecraft.client.util.ScreenshotRecorder;
import net.minecraft.item.ItemGroup;
import net.minecraft.screen.slot.Slot;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -38,7 +34,7 @@ import java.util.stream.Collectors;
* Represents some input handlers.
*
* @author LambdAurora
* @version 1.4.3
* @version 1.7.0
* @since 1.1.0
*/
public class InputHandlers {
@@ -53,12 +49,11 @@ public class InputHandlers {
// When ingame
if (client.currentScreen == null && client.player != null) {
if (next)
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 8 ? 0 : client.player.inventory.selectedSlot + 1;
client.player.getInventory().selectedSlot = client.player.getInventory().selectedSlot == 8 ? 0 : client.player.getInventory().selectedSlot + 1;
else
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 0 ? 8 : client.player.inventory.selectedSlot - 1;
client.player.getInventory().selectedSlot = client.player.getInventory().selectedSlot == 0 ? 8 : client.player.getInventory().selectedSlot - 1;
return true;
} else if (client.currentScreen instanceof CreativeInventoryScreen) {
CreativeInventoryScreenAccessor inventory = (CreativeInventoryScreenAccessor) client.currentScreen;
} else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) {
int currentTab = inventory.getSelectedTab();
int nextTab = currentTab + (next ? 1 : -1);
if (nextTab < 0)
@@ -67,10 +62,10 @@ public class InputHandlers {
nextTab = 0;
inventory.lambdacontrols$setSelectedTab(ItemGroup.GROUPS[nextTab]);
return true;
} else if (client.currentScreen instanceof InventoryScreen) {
RecipeBookWidgetAccessor recipeBook = (RecipeBookWidgetAccessor) ((InventoryScreen) client.currentScreen).getRecipeBookWidget();
List<RecipeGroupButtonWidget> tabs = recipeBook.getTabButtons();
RecipeGroupButtonWidget currentTab = recipeBook.getCurrentTab();
} else if (client.currentScreen instanceof InventoryScreen inventoryScreen) {
var recipeBook = (RecipeBookWidgetAccessor) inventoryScreen.getRecipeBookWidget();
var tabs = recipeBook.getTabButtons();
var currentTab = recipeBook.getCurrentTab();
if (currentTab == null)
return false;
int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1);
@@ -83,10 +78,9 @@ public class InputHandlers {
currentTab.setToggled(true);
recipeBook.lambdacontrols$refreshResults(true);
return true;
} else if (client.currentScreen instanceof AdvancementsScreen) {
AdvancementsScreenAccessor screen = (AdvancementsScreenAccessor) client.currentScreen;
List<AdvancementTab> tabs = screen.getTabs().values().stream().distinct().collect(Collectors.toList());
AdvancementTab tab = screen.getSelectedTab();
} else if (client.currentScreen instanceof AdvancementsScreenAccessor screen) {
var tabs = screen.getTabs().values().stream().distinct().collect(Collectors.toList());
var tab = screen.getSelectedTab();
if (tab == null)
return false;
for (int i = 0; i < tabs.size(); i++) {
@@ -122,14 +116,14 @@ public class InputHandlers {
/**
* Handles the screenshot action.
*
* @param client The client instance.
* @param binding The binding which fired the action.
* @param action The action done on the binding.
* @return True if handled, else false.
* @param client the client instance
* @param binding the binding which fired the action
* @param action the action done on the binding
* @return true if handled, else false
*/
public static boolean handleScreenshot(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) {
if (action == ButtonState.RELEASE)
ScreenshotUtils.saveScreenshot(client.runDirectory, client.getWindow().getFramebufferWidth(), client.getWindow().getFramebufferHeight(), client.getFramebuffer(),
ScreenshotRecorder.saveScreenshot(client.runDirectory, client.getWindow().getFramebufferWidth(), client.getWindow().getFramebufferHeight(), client.getFramebuffer(),
text -> client.execute(() -> client.inGameHud.getChatHud().addMessage(text)));
return true;
}
@@ -137,10 +131,10 @@ public class InputHandlers {
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action) {
button.asKeyBinding().ifPresent(binding -> {
boolean sneakToggled = client.options.sneakToggled;
if (client.player.abilities.flying && sneakToggled)
if (client.player.getAbilities().flying && sneakToggled)
client.options.sneakToggled = false;
binding.setPressed(button.pressed);
if (client.player.abilities.flying && sneakToggled)
if (client.player.getAbilities().flying && sneakToggled)
client.options.sneakToggled = true;
});
return true;
@@ -148,18 +142,17 @@ public class InputHandlers {
public static PressAction handleInventorySlotPad(int direction) {
return (client, binding, value, action) -> {
if (!(client.currentScreen instanceof HandledScreen && action != ButtonState.RELEASE))
if (!(client.currentScreen instanceof HandledScreen inventory && action != ButtonState.RELEASE))
return false;
HandledScreen inventory = (HandledScreen) client.currentScreen;
HandledScreenAccessor 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();
// Finds the hovered slot.
Slot mouseSlot = accessor.lambdacontrols$getSlotAt(mouseX, mouseY);
var mouseSlot = accessor.lambdacontrols$getSlotAt(mouseX, mouseY);
// Finds the closest slot in the GUI within 14 pixels.
Optional<Slot> closestSlot = inventory.getScreenHandler().slots.parallelStream()
@@ -179,7 +172,7 @@ public class InputHandlers {
double distance = Math.sqrt(Math.pow(posX - otherPosX, 2) + Math.pow(posY - otherPosY, 2));
return Pair.of(slot, distance);
}).filter(entry -> {
Slot slot = entry.key;
var slot = entry.key;
int posX = guiLeft + slot.x + 8;
int posY = guiTop + slot.y + 8;
int otherPosX = (int) mouseX;
@@ -203,7 +196,7 @@ public class InputHandlers {
.map(p -> p.key);
if (closestSlot.isPresent()) {
Slot slot = closestSlot.get();
var slot = closestSlot.get();
int x = guiLeft + slot.x + 8;
int y = guiTop + slot.y + 8;
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
@@ -217,9 +210,9 @@ public class InputHandlers {
/**
* Returns always true to the filter.
*
* @param client The client instance.
* @param binding The affected binding.
* @return True.
* @param client the client instance
* @param binding the affected binding
* @return true
*/
public static boolean always(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
return true;
@@ -228,9 +221,9 @@ public class InputHandlers {
/**
* Returns whether the client is in game or not.
*
* @param client The client instance.
* @param binding The affected binding.
* @return True if the client is in game, else false.
* @param client the client instance
* @param binding the affected binding
* @return true if the client is in game, else false
*/
public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
return client.currentScreen == null;
@@ -239,9 +232,9 @@ public class InputHandlers {
/**
* 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.
* @return True if the client is in a non-interactive screen, else false.
* @param client the client instance
* @param binding the affected binding
* @return true if the client is in a non-interactive screen, else false
*/
public static boolean inNonInteractiveScreens(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
if (client.currentScreen == null)
@@ -252,9 +245,9 @@ public class InputHandlers {
/**
* Returns whether the client is in an inventory or not.
*
* @param client The client instance.
* @param binding The affected binding.
* @return True if the client is in an inventory, else false.
* @param client the client instance
* @param binding the affected binding
* @return true if the client is in an inventory, else false
*/
public static boolean inInventory(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
return client.currentScreen instanceof HandledScreen;
@@ -263,9 +256,9 @@ public class InputHandlers {
/**
* Returns whether the client is in the advancements screen or not.
*
* @param client The client instance.
* @param binding The affected binding.
* @return True if the client is in the advancements screen, else false.
* @param client the client instance
* @param binding the affected binding
* @return true if the client is in the advancements screen, else false
*/
public static boolean inAdvancements(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
return client.currentScreen instanceof AdvancementsScreen;

View File

@@ -14,12 +14,13 @@ import dev.lambdaurora.lambdacontrols.client.ButtonState;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
import dev.lambdaurora.lambdacontrols.client.util.MouseAccessor;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.util.math.MathHelper;
import org.aperlambda.lambdacommon.Identifier;
import org.aperlambda.lambdacommon.utils.Pair;
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
@@ -33,15 +34,15 @@ import java.util.stream.Stream;
* Represents an input manager for controllers.
*
* @author LambdAurora
* @version 1.4.0
* @version 1.7.0
* @since 1.1.0
*/
public class InputManager {
public static final InputManager INPUT_MANAGER = new InputManager();
private static final List<ButtonBinding> BINDINGS = new ArrayList<>();
private static final List<ButtonCategory> CATEGORIES = new ArrayList<>();
public static final Map<Integer, ButtonState> STATES = new HashMap<>();
public static final Map<Integer, Float> BUTTON_VALUES = new HashMap<>();
public static final Int2ObjectMap<ButtonState> STATES = new Int2ObjectOpenHashMap<>();
public static final Int2FloatMap BUTTON_VALUES = new Int2FloatOpenHashMap();
private int prevTargetMouseX = 0;
private int prevTargetMouseY = 0;
private int targetMouseX = 0;
@@ -64,7 +65,7 @@ public class InputManager {
/**
* Updates the mouse position. Should only be called on pre render of a screen.
*
* @param client The client instance.
* @param client the client instance
*/
public void updateMousePosition(@NotNull MinecraftClient client) {
Objects.requireNonNull(client, "Client instance cannot be null.");
@@ -80,8 +81,8 @@ public class InputManager {
/**
* Resets the mouse position.
*
* @param windowWidth The window width.
* @param windowHeight The window height.
* @param windowWidth the window width
* @param windowHeight the window height
*/
public void resetMousePosition(int windowWidth, int windowHeight) {
this.targetMouseX = this.prevTargetMouseX = (int) (windowWidth / 2.F);
@@ -98,8 +99,8 @@ public class InputManager {
/**
* Returns whether the specified binding is registered or not.
*
* @param binding The binding to check.
* @return True if the binding is registered, else false.
* @param binding the binding to check
* @return true if the binding is registered, else false
*/
public static boolean hasBinding(@NotNull ButtonBinding binding) {
return BINDINGS.contains(binding);
@@ -108,8 +109,8 @@ public class InputManager {
/**
* Returns whether the specified binding is registered or not.
*
* @param name The name of the binding to check.
* @return True if the binding is registered, else false.
* @param name the name of the binding to check
* @return true if the binding is registered, else false
*/
public static boolean hasBinding(@NotNull String name) {
return BINDINGS.parallelStream().map(ButtonBinding::getName).anyMatch(binding -> binding.equalsIgnoreCase(name));
@@ -118,8 +119,8 @@ public class InputManager {
/**
* Returns whether the specified binding is registered or not.
*
* @param identifier The identifier of the binding to check.
* @return True if the binding is registered, else false.
* @param identifier the identifier of the binding to check
* @return true if the binding is registered, else false
*/
public static boolean hasBinding(@NotNull Identifier identifier) {
return hasBinding(identifier.getNamespace() + "." + identifier.getName());
@@ -128,8 +129,8 @@ public class InputManager {
/**
* Registers a button binding.
*
* @param binding The binding to register.
* @return The registered binding.
* @param binding the binding to register
* @return the registered binding
*/
public static @NotNull ButtonBinding registerBinding(@NotNull ButtonBinding binding) {
if (hasBinding(binding))
@@ -159,7 +160,8 @@ public class InputManager {
*/
public static void sortBindings() {
synchronized (BINDINGS) {
List<ButtonBinding> sorted = BINDINGS.stream().sorted(Collections.reverseOrder(Comparator.comparingInt(binding -> binding.getButton().length)))
var sorted = BINDINGS.stream()
.sorted(Collections.reverseOrder(Comparator.comparingInt(binding -> binding.getButton().length)))
.collect(Collectors.toList());
BINDINGS.clear();
BINDINGS.addAll(sorted);
@@ -169,8 +171,8 @@ public class InputManager {
/**
* Registers a category of button bindings.
*
* @param category The category to register.
* @return The registered category.
* @param category the category to register
* @return the registered category
*/
public static ButtonCategory registerCategory(@NotNull ButtonCategory category) {
CATEGORIES.add(category);
@@ -186,7 +188,7 @@ public class InputManager {
}
protected static ButtonCategory registerDefaultCategory(@NotNull String key, @NotNull Consumer<ButtonCategory> keyAdder) {
ButtonCategory category = registerCategory(new Identifier("minecraft", key), CATEGORIES.size());
var category = registerCategory(new Identifier("minecraft", key), CATEGORIES.size());
keyAdder.accept(category);
return category;
}
@@ -194,23 +196,23 @@ public class InputManager {
/**
* Loads the button bindings from configuration.
*
* @param config The configuration instance.
* @param config the configuration instance
*/
public static void loadButtonBindings(@NotNull LambdaControlsConfig config) {
List<ButtonBinding> queue = new ArrayList<>(BINDINGS);
var queue = new ArrayList<>(BINDINGS);
queue.forEach(config::loadButtonBinding);
}
/**
* Returns the binding state.
*
* @param binding The binding.
* @return The current state of the binding.
* @param binding the binding
* @return the current state of the binding
*/
public static @NotNull ButtonState getBindingState(@NotNull ButtonBinding binding) {
ButtonState state = ButtonState.REPEAT;
var state = ButtonState.REPEAT;
for (int btn : binding.getButton()) {
ButtonState btnState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
var btnState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
if (btnState == ButtonState.PRESS)
state = ButtonState.PRESS;
else if (btnState == ButtonState.RELEASE) {
@@ -243,8 +245,8 @@ public class InputManager {
/**
* Returns whether the button has duplicated bindings.
*
* @param button The button to check.
* @return True if the button has duplicated bindings, else false.
* @param button the button to check
* @return true if the button has duplicated bindings, else false
*/
public static boolean hasDuplicatedBindings(int[] button) {
return BINDINGS.parallelStream().filter(binding -> areButtonsEquivalent(binding.getButton(), button)).count() > 1;
@@ -253,8 +255,8 @@ public class InputManager {
/**
* Returns whether the button has duplicated bindings.
*
* @param binding The binding to check.
* @return True if the button has duplicated bindings, else false.
* @param binding the binding to check
* @return true if the button has duplicated bindings, else false
*/
public static boolean hasDuplicatedBindings(ButtonBinding binding) {
return BINDINGS.parallelStream().filter(other -> areButtonsEquivalent(other.getButton(), binding.getButton()) && other.filter.equals(binding.filter)).count() > 1;
@@ -263,9 +265,9 @@ public class InputManager {
/**
* Returns whether the specified buttons are equivalent or not.
*
* @param buttons1 First set of buttons.
* @param buttons2 Second set of buttons.
* @return True if the two sets of buttons are equivalent, else false.
* @param buttons1 first set of buttons
* @param buttons2 second set of buttons
* @return true if the two sets of buttons are equivalent, else false
*/
public static boolean areButtonsEquivalent(int[] buttons1, int[] buttons2) {
if (buttons1.length != buttons2.length)
@@ -285,9 +287,9 @@ public class InputManager {
/**
* Returns whether the button set contains the specified button or not.
*
* @param buttons The button set.
* @param button The button to check.
* @return True if the button set contains the specified button, else false.
* @param buttons the button set
* @param button the button to check
* @return true if the button set contains the specified button, else false
*/
public static boolean containsButton(int[] buttons, int button) {
return Arrays.stream(buttons).anyMatch(btn -> btn == button);
@@ -297,19 +299,21 @@ public class InputManager {
* Updates the button states.
*/
public static void updateStates() {
STATES.forEach((btn, state) -> {
if (state == ButtonState.PRESS)
STATES.put(btn, ButtonState.REPEAT);
else if (state == ButtonState.RELEASE)
STATES.put(btn, ButtonState.NONE);
});
for (var entry : STATES.int2ObjectEntrySet()) {
if (entry.getValue() == ButtonState.PRESS)
STATES.put(entry.getIntKey(), ButtonState.REPEAT);
else if (entry.getValue() == ButtonState.RELEASE)
STATES.put(entry.getIntKey(), ButtonState.NONE);
}
}
public static void updateBindings(@NotNull MinecraftClient client) {
List<Integer> skipButtons = new ArrayList<>();
Map<ButtonBinding, Pair<ButtonState, Float>> states = new HashMap<>();
for (ButtonBinding binding : BINDINGS) {
ButtonState state = binding.isAvailable(client) ? getBindingState(binding) : ButtonState.NONE;
var skipButtons = new IntArrayList();
record ButtonStateValue(ButtonState state, float value) {
}
var states = new Object2ObjectOpenHashMap<ButtonBinding, ButtonStateValue>();
for (var binding : BINDINGS) {
var state = binding.isAvailable(client) ? getBindingState(binding) : ButtonState.NONE;
if (skipButtons.stream().anyMatch(btn -> containsButton(binding.getButton(), btn))) {
if (binding.pressed)
state = ButtonState.RELEASE;
@@ -328,12 +332,12 @@ public class InputManager {
float value = getBindingValue(binding, state);
states.put(binding, Pair.of(state, value));
states.put(binding, new ButtonStateValue(state, value));
}
states.forEach((binding, state) -> {
if (state.key != ButtonState.NONE) {
binding.handle(client, state.value, state.key);
if (state.state() != ButtonState.NONE) {
binding.handle(client, state.value(), state.state());
}
});
}
@@ -358,11 +362,11 @@ public class InputManager {
/**
* 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.
* @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(Identifier, InputUtil.Type, int, String)
*/
public static @NotNull KeyBinding makeKeyBinding(@NotNull net.minecraft.util.Identifier id, InputUtil.Type type, int code, @NotNull String category) {
@@ -372,11 +376,11 @@ public class InputManager {
/**
* Returns a new key binding instance.
*
* @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.
* @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) {

View File

@@ -12,14 +12,14 @@ package dev.lambdaurora.lambdacontrols.client.controller;
import dev.lambdaurora.lambdacontrols.client.ButtonState;
import dev.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.StickyKeyBinding;
import net.minecraft.client.option.StickyKeyBinding;
import org.jetbrains.annotations.NotNull;
/**
* Represents a press action callback.
*
* @author LambdAurora
* @version 1.4.3
* @version 1.7.0
* @since 1.0.0
*/
@FunctionalInterface
@@ -31,7 +31,7 @@ public interface PressAction {
if (binding instanceof StickyKeyBinding)
binding.setPressed(button.pressed);
else
((KeyBindingAccessor) binding).lambdacontrols_handlePressState(button.isButtonDown());
((KeyBindingAccessor) binding).lambdacontrols$handlePressState(button.isButtonDown());
});
return true;
};
@@ -39,8 +39,8 @@ public interface PressAction {
/**
* Handles when there is a press action.
*
* @param client The client instance.
* @param action The action done.
* @param client the client instance
* @param action the action done
*/
boolean press(@NotNull MinecraftClient client, @NotNull ButtonBinding button, float value, @NotNull ButtonState action);
}

View File

@@ -15,10 +15,9 @@ import dev.lambdaurora.lambdacontrols.client.HudSide;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.spruceui.hud.Hud;
import dev.lambdaurora.spruceui.hud.Hud;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.Window;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
@@ -32,7 +31,7 @@ import org.jetbrains.annotations.Nullable;
* Represents the LambdaControls HUD.
*
* @author LambdAurora
* @version 1.3.2
* @version 1.7.0
* @since 1.0.0
*/
public class LambdaControlsHud extends Hud {
@@ -87,8 +86,8 @@ public class LambdaControlsHud extends Hud {
if (this.mod.reacharound.isLastReacharoundVertical()) {
// Render crosshair indicator.
Window window = this.client.getWindow();
String text = "[ ]";
var window = this.client.getWindow();
var text = "[ ]";
float scale = Math.min(5, this.ticksDisplayedCrosshair + tickDelta) / 5F;
scale *= scale;
@@ -203,7 +202,7 @@ public class LambdaControlsHud extends Hud {
this.ticksDisplayedCrosshair = 0;
}
String customAttackAction = LambdaControlsCompat.getAttackActionAt(this.client, this.placeHitResult);
var customAttackAction = LambdaControlsCompat.getAttackActionAt(this.client, this.placeHitResult);
if (customAttackAction != null) {
this.attackAction = customAttackAction;
this.attackWidth = this.width(customAttackAction);
@@ -225,7 +224,7 @@ public class LambdaControlsHud extends Hud {
}
}
String customUseAction = LambdaControlsCompat.getUseActionAt(this.client, this.placeHitResult);
var customUseAction = LambdaControlsCompat.getUseActionAt(this.client, this.placeHitResult);
if (customUseAction != null)
placeAction = customUseAction;
@@ -270,7 +269,7 @@ public class LambdaControlsHud extends Hud {
private void drawTip(MatrixStack matrices, int x, int y, @NotNull String action, boolean display) {
if (!display)
return;
String translatedAction = I18n.translate(action);
var translatedAction = I18n.translate(action);
int textY = (LambdaControlsRenderer.ICON_SIZE / 2 - this.client.textRenderer.fontHeight / 2) + 1;
this.client.textRenderer.draw(matrices, translatedAction, (float) x, (float) (y + textY), 14737632);
}

View File

@@ -18,11 +18,9 @@ import dev.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.slot.Slot;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
@@ -30,7 +28,7 @@ import org.lwjgl.glfw.GLFW;
* Represents the LambdaControls renderer.
*
* @author LambdAurora
* @version 1.5.0
* @version 1.7.0
* @since 1.2.0
*/
public class LambdaControlsRenderer {
@@ -39,28 +37,21 @@ public class LambdaControlsRenderer {
private static final int AXIS_SIZE = 18;
public static int getButtonSize(int button) {
switch (button) {
case -1:
return 0;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200:
return AXIS_SIZE;
default:
return BUTTON_SIZE;
}
return switch (button) {
case -1 -> 0;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100, GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200,
GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100, GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200,
GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100, GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200,
GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100, GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200 -> AXIS_SIZE;
default -> BUTTON_SIZE;
};
}
/**
* Gets the binding icon width.
*
* @param binding The binding.
* @return The width.
* @param binding the binding
* @return the width
*/
public static int getBindingIconWidth(@NotNull ButtonBinding binding) {
return getBindingIconWidth(binding.getButton());
@@ -69,8 +60,8 @@ public class LambdaControlsRenderer {
/**
* Gets the binding icon width.
*
* @param buttons The buttons.
* @return The width.
* @param buttons the buttons
* @return the width
*/
public static int getBindingIconWidth(int[] buttons) {
int width = 0;
@@ -83,11 +74,11 @@ public class LambdaControlsRenderer {
return width;
}
public static Pair<Integer, Integer> drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client) {
public static ButtonSize drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client) {
return drawButton(matrices, x, y, button.getButton(), client);
}
public static Pair<Integer, Integer> drawButton(MatrixStack matrices, int x, int y, int[] buttons, @NotNull MinecraftClient client) {
public static ButtonSize drawButton(MatrixStack matrices, int x, int y, int[] buttons, @NotNull MinecraftClient client) {
int height = 0;
int length = 0;
int currentX = x;
@@ -102,7 +93,7 @@ public class LambdaControlsRenderer {
currentX = x + length;
}
}
return Pair.of(length, height);
return new ButtonSize(length, height);
}
@SuppressWarnings("deprecated")
@@ -119,75 +110,55 @@ public class LambdaControlsRenderer {
boolean axis = false;
int buttonOffset = button * 15;
switch (button) {
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
buttonOffset = 7 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
buttonOffset = 8 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_BACK:
buttonOffset = 4 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_START:
buttonOffset = 6 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_GUIDE:
buttonOffset = 5 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
buttonOffset = 15 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
buttonOffset = 16 * 15;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100:
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER -> buttonOffset = 7 * 15;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER -> buttonOffset = 8 * 15;
case GLFW.GLFW_GAMEPAD_BUTTON_BACK -> buttonOffset = 4 * 15;
case GLFW.GLFW_GAMEPAD_BUTTON_START -> buttonOffset = 6 * 15;
case GLFW.GLFW_GAMEPAD_BUTTON_GUIDE -> buttonOffset = 5 * 15;
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB -> buttonOffset = 15 * 15;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB -> buttonOffset = 16 * 15;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100 -> {
buttonOffset = 0;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100:
}
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100 -> {
buttonOffset = 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100:
}
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100 -> {
buttonOffset = 2 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100:
}
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100 -> {
buttonOffset = 3 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200:
}
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200 -> {
buttonOffset = 4 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200:
}
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200 -> {
buttonOffset = 5 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200:
}
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200 -> {
buttonOffset = 6 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200:
}
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200 -> {
buttonOffset = 7 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 100:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 200:
buttonOffset = 9 * 15;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200:
buttonOffset = 10 * 15;
break;
}
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 100, GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 200 -> buttonOffset = 9 * 15;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100, GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200 -> buttonOffset = 10 * 15;
}
client.getTextureManager().bindTexture(axis ? LambdaControlsClient.CONTROLLER_AXIS : LambdaControlsClient.CONTROLLER_BUTTONS);
RenderSystem.setShaderTexture(0, axis ? LambdaControlsClient.CONTROLLER_AXIS : LambdaControlsClient.CONTROLLER_BUTTONS);
RenderSystem.disableDepthTest();
int assetSize = axis ? AXIS_SIZE : BUTTON_SIZE;
RenderSystem.color4f(1.0F, second ? 0.0F : 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderColor(1.f, second ? 0.f : 1.f, 1.f, 1.f);
DrawableHelper.drawTexture(matrices, x + (ICON_SIZE / 2 - assetSize / 2), y + (ICON_SIZE / 2 - assetSize / 2),
(float) buttonOffset, (float) (controllerType * (axis ? AXIS_SIZE : BUTTON_SIZE)),
assetSize, assetSize,
@@ -203,9 +174,9 @@ public class LambdaControlsRenderer {
public static int drawButtonTip(MatrixStack matrices, int x, int y, int[] button, @NotNull String action, boolean display, @NotNull MinecraftClient client) {
if (display) {
int buttonWidth = drawButton(matrices, x, y, button, client).key;
int buttonWidth = drawButton(matrices, x, y, button, client).length();
String translatedAction = I18n.translate(action);
var translatedAction = I18n.translate(action);
int textY = (LambdaControlsRenderer.ICON_SIZE / 2 - client.textRenderer.fontHeight / 2) + 1;
return client.textRenderer.drawWithShadow(matrices, translatedAction, (float) (x + buttonWidth + 2), (float) (y + textY), 14737632);
@@ -219,7 +190,8 @@ public class LambdaControlsRenderer {
}
public static void renderVirtualCursor(@NotNull MatrixStack matrices, @NotNull MinecraftClient client) {
if (!LambdaControlsClient.get().config.hasVirtualMouse() || (client.currentScreen == null || LambdaInput.isScreenInteractive(client.currentScreen)))
if (!LambdaControlsClient.get().config.hasVirtualMouse() || (client.currentScreen == null
|| LambdaInput.isScreenInteractive(client.currentScreen)))
return;
int mouseX = (int) (client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
@@ -227,8 +199,7 @@ public class LambdaControlsRenderer {
boolean hoverSlot = false;
if (client.currentScreen instanceof HandledScreen) {
HandledScreenAccessor inventoryScreen = (HandledScreenAccessor) client.currentScreen;
if (client.currentScreen instanceof HandledScreenAccessor inventoryScreen) {
int guiLeft = inventoryScreen.getX();
int guiTop = inventoryScreen.getY();
@@ -242,11 +213,11 @@ public class LambdaControlsRenderer {
}
if (!hoverSlot) {
Pair<Integer, Integer> slot = LambdaControlsCompat.getSlotAt(client.currentScreen, mouseX, mouseY);
var slot = LambdaControlsCompat.getSlotAt(client.currentScreen, mouseX, mouseY);
if (slot != null) {
mouseX = slot.getFirst();
mouseY = slot.getSecond();
mouseX = slot.x();
mouseY = slot.y();
hoverSlot = true;
}
}
@@ -262,19 +233,23 @@ public class LambdaControlsRenderer {
/**
* Draws the virtual cursor.
*
* @param matrices The matrix stack.
* @param x X coordinate.
* @param y Y coordinate.
* @param hoverSlot True if hovering a slot, else false.
* @param client The client instance.
* @param matrices the matrix stack
* @param x x coordinate
* @param y y coordinate
* @param hoverSlot true if hovering a slot, else false
* @param client the client instance
*/
public static void drawCursor(@NotNull MatrixStack matrices, int x, int y, boolean hoverSlot, @NotNull MinecraftClient client) {
client.getTextureManager().bindTexture(LambdaControlsClient.CURSOR_TEXTURE);
RenderSystem.disableDepthTest();
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
DrawableHelper.drawTexture(matrices, x, y, hoverSlot ? 16.F : 0.F, LambdaControlsClient.get().config.getVirtualMouseSkin().ordinal() * 16.F, 16, 16, 32, 64);
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
RenderSystem.setShaderTexture(0, LambdaControlsClient.CURSOR_TEXTURE);
DrawableHelper.drawTexture(matrices, x, y,
hoverSlot ? 16.f : 0.f, LambdaControlsClient.get().config.getVirtualMouseSkin().ordinal() * 16.f,
16, 16, 32, 64);
RenderSystem.enableDepthTest();
}
public record ButtonSize(int length, int height) {
}
}

View File

@@ -9,21 +9,20 @@
package dev.lambdaurora.lambdacontrols.client.gui;
import dev.lambdaurora.lambdacontrols.ControlsMode;
import dev.lambdaurora.lambdacontrols.LambdaControls;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
import dev.lambdaurora.lambdacontrols.client.gui.widget.ControllerControlsWidget;
import me.lambdaurora.spruceui.Position;
import me.lambdaurora.spruceui.SpruceTexts;
import me.lambdaurora.spruceui.option.*;
import me.lambdaurora.spruceui.screen.SpruceScreen;
import me.lambdaurora.spruceui.widget.AbstractSpruceWidget;
import me.lambdaurora.spruceui.widget.SpruceLabelWidget;
import me.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
import me.lambdaurora.spruceui.widget.container.SpruceOptionListWidget;
import me.lambdaurora.spruceui.widget.container.tabbed.SpruceTabbedWidget;
import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.SpruceTexts;
import dev.lambdaurora.spruceui.option.*;
import dev.lambdaurora.spruceui.screen.SpruceScreen;
import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget;
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceOptionListWidget;
import dev.lambdaurora.spruceui.widget.container.tabbed.SpruceTabbedWidget;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
@@ -71,7 +70,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
private final SpruceOption controllerOption =
new SpruceCyclingOption("lambdacontrols.menu.controller",
amount -> {
int id = this.config.getController().getId();
int id = this.config.getController().id();
id += amount;
if (id > GLFW.GLFW_JOYSTICK_LAST)
id = GLFW.GLFW_JOYSTICK_1;
@@ -79,8 +78,8 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
this.config.setController(Controller.byId(id));
},
option -> {
Controller controller = this.config.getController();
String controllerName = controller.getName();
var controller = this.config.getController();
var controllerName = controller.getName();
if (!controller.isConnected())
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.RED));
else if (!controller.isGamepad())
@@ -90,7 +89,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
}, null);
private final SpruceOption secondControllerOption = new SpruceCyclingOption("lambdacontrols.menu.controller2",
amount -> {
int id = this.config.getSecondController().map(Controller::getId).orElse(-1);
int id = this.config.getSecondController().map(Controller::id).orElse(-1);
id += amount;
if (id > GLFW.GLFW_JOYSTICK_LAST)
id = -1;
@@ -98,7 +97,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
this.config.setSecondController(id == -1 ? null : Controller.byId(id));
},
option -> this.config.getSecondController().map(controller -> {
String controllerName = controller.getName();
var controllerName = controller.getName();
if (!controller.isConnected())
return option.getDisplayText(new LiteralText(controllerName).formatted(Formatting.RED));
else if (!controller.isGamepad())
@@ -152,7 +151,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
// General options
this.inputModeOption = new SpruceCyclingOption("lambdacontrols.menu.controls_mode",
amount -> {
ControlsMode next = this.config.getControlsMode().next();
var next = this.config.getControlsMode().next();
this.config.setControlsMode(next);
this.config.save();
@@ -181,7 +180,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
new TranslatableText("lambdacontrols.tooltip.mouse_speed"));
this.resetOption = SpruceSimpleActionOption.reset(btn -> {
this.config.reset();
MinecraftClient client = MinecraftClient.getInstance();
var client = MinecraftClient.getInstance();
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
});
// Gameplay options
@@ -225,7 +224,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
this.config.setRightDeadZone(newValue);
}
}, option -> {
String value = String.valueOf(option.get());
var value = String.valueOf(option.get());
return option.getDisplayText(new LiteralText(value.substring(0, Math.min(value.length(), 5))));
}, new TranslatableText("lambdacontrols.tooltip.right_dead_zone"));
this.leftDeadZoneOption = new SpruceDoubleOption("lambdacontrols.menu.left_dead_zone", 0.05, 1.0, .05f,
@@ -235,7 +234,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
this.config.setLeftDeadZone(newValue);
}
}, option -> {
String value = String.valueOf(option.get());
var value = String.valueOf(option.get());
return option.getDisplayText(new LiteralText(value.substring(0, Math.min(value.length(), 5))));
}, new TranslatableText("lambdacontrols.tooltip.left_dead_zone"));
this.invertsRightXAxis = new SpruceToggleBooleanOption("lambdacontrols.menu.invert_right_x_axis", this.config::doesInvertRightXAxis,
@@ -278,16 +277,16 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
this.buildTabs();
this.addChild(this.resetOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 150));
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, 20, SpruceTexts.GUI_DONE,
this.addDrawableChild(this.resetOption.createWidget(Position.of(this.width / 2 - 155, this.height - 29), 150));
this.addDrawableChild(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, 20, SpruceTexts.GUI_DONE,
btn -> this.client.openScreen(this.parent)));
}
public void buildTabs() {
SpruceTabbedWidget tabs = new SpruceTabbedWidget(Position.of(0, 24), this.width, this.height - 32 - 24,
var tabs = new SpruceTabbedWidget(Position.of(0, 24), this.width, this.height - 32 - 24,
null,
Math.max(116, this.width / 8), 0);
this.addChild(tabs);
this.addDrawableChild(tabs);
tabs.addSeparatorEntry(new TranslatableText("lambdacontrols.menu.separator.general"));
tabs.addTabEntry(new TranslatableText("lambdacontrols.menu.title.general"), null,
@@ -309,7 +308,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
}
public SpruceOptionListWidget buildGeneralTab(int width, int height) {
SpruceOptionListWidget list = new SpruceOptionListWidget(Position.origin(), width, height);
var list = new SpruceOptionListWidget(Position.origin(), width, height);
list.addSingleOptionEntry(this.inputModeOption);
list.addSingleOptionEntry(this.autoSwitchModeOption);
list.addSingleOptionEntry(this.rotationSpeedOption);
@@ -319,7 +318,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
}
public SpruceOptionListWidget buildGameplayTab(int width, int height) {
SpruceOptionListWidget list = new SpruceOptionListWidget(Position.origin(), width, height);
var list = new SpruceOptionListWidget(Position.origin(), width, height);
list.addSingleOptionEntry(this.analogMovementOption);
list.addSingleOptionEntry(this.fastBlockPlacingOption);
list.addSingleOptionEntry(this.frontBlockPlacingOption);
@@ -331,7 +330,7 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
}
public SpruceOptionListWidget buildVisualTab(int width, int height) {
SpruceOptionListWidget list = new SpruceOptionListWidget(Position.origin(), width, height);
var list = new SpruceOptionListWidget(Position.origin(), width, height);
list.addSingleOptionEntry(this.controllerTypeOption);
list.addSingleOptionEntry(this.virtualMouseSkinOption);
list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.hud", true, null));
@@ -345,38 +344,38 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
}
public AbstractSpruceWidget buildControllerTab(int width, int height) {
SpruceContainerWidget root = new SpruceContainerWidget(Position.origin(), width, height);
var root = new SpruceContainerWidget(Position.origin(), width, height);
SpruceLabelWidget aboutMappings1 = new SpruceLabelWidget(Position.of(0, 2),
var aboutMappings1 = new SpruceLabelWidget(Position.of(0, 2),
new TranslatableText("lambdacontrols.controller.mappings.1", SDL2_GAMEPAD_TOOL),
width, true);
SpruceLabelWidget gamepadToolUrlLabel = new SpruceLabelWidget(Position.of(0, aboutMappings1.getHeight() + 4),
var gamepadToolUrlLabel = new SpruceLabelWidget(Position.of(0, aboutMappings1.getHeight() + 4),
this.controllerMappingsUrlText, width,
label -> Util.getOperatingSystem().open(GAMEPAD_TOOL_URL), true);
gamepadToolUrlLabel.setTooltip(new TranslatableText("chat.link.open"));
SpruceLabelWidget aboutMappings3 = new SpruceLabelWidget(Position.of(0,
var aboutMappings3 = new SpruceLabelWidget(Position.of(0,
aboutMappings1.getHeight() + gamepadToolUrlLabel.getHeight() + 6),
new TranslatableText("lambdacontrols.controller.mappings.3", Formatting.GREEN.toString(), Formatting.RESET.toString()),
width, true);
int listHeight = height - 8 - aboutMappings1.getHeight() - aboutMappings3.getHeight() - gamepadToolUrlLabel.getHeight();
SpruceContainerWidget labels = new SpruceContainerWidget(Position.of(0,
var labels = new SpruceContainerWidget(Position.of(0,
listHeight),
width, height - listHeight);
labels.addChild(aboutMappings1);
labels.addChild(gamepadToolUrlLabel);
labels.addChild(aboutMappings3);
SpruceOptionListWidget list = new SpruceOptionListWidget(Position.origin(), width, listHeight);
var list = new SpruceOptionListWidget(Position.origin(), width, listHeight);
list.addSingleOptionEntry(this.controllerOption);
list.addSingleOptionEntry(this.secondControllerOption);
list.addSingleOptionEntry(this.unfocusedInputOption);
list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
list.addSingleOptionEntry(this.rightDeadZoneOption);
list.addSingleOptionEntry(this.leftDeadZoneOption);
for (SpruceOption option : this.maxAnalogValueOptions) {
for (var option : this.maxAnalogValueOptions) {
list.addSingleOptionEntry(option);
}
@@ -391,6 +390,6 @@ public class LambdaControlsSettingsScreen extends SpruceScreen {
@Override
public void renderTitle(MatrixStack matrices, int mouseX, int mouseY, float delta) {
drawCenteredString(matrices, this.textRenderer, I18n.translate("lambdacontrols.menu.title"), this.width / 2, 8, 16777215);
drawCenteredText(matrices, this.textRenderer, I18n.translate("lambdacontrols.menu.title"), this.width / 2, 8, 16777215);
}
}

View File

@@ -11,10 +11,10 @@ package dev.lambdaurora.lambdacontrols.client.gui;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
import me.lambdaurora.spruceui.Position;
import me.lambdaurora.spruceui.option.SpruceOption;
import me.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
import me.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.option.SpruceOption;
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
import dev.lambdaurora.spruceui.widget.text.SpruceTextAreaWidget;
import net.minecraft.client.toast.SystemToast;
import net.minecraft.text.LiteralText;
import net.minecraft.text.TranslatableText;
@@ -27,7 +27,7 @@ import java.nio.file.Files;
* Represents the controller mappings file editor screen.
*
* @author LambdAurora
* @version 1.4.3
* @version 1.7.0
* @since 1.4.3
*/
public class MappingsStringInputWidget extends SpruceContainerWidget {
@@ -59,7 +59,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
if (this.textArea != null) {
this.mappings = this.textArea.getText();
try {
FileWriter fw = new FileWriter(LambdaControlsClient.MAPPINGS_FILE, false);
var fw = new FileWriter(LambdaControlsClient.MAPPINGS_FILE, false);
fw.write(this.mappings);
fw.close();
} catch (IOException e) {
@@ -76,7 +76,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
this.mappings = this.textArea.getText();
}
String mappings = "";
var mappings = "";
if (this.mappings != null)
mappings = this.mappings;

View File

@@ -10,8 +10,8 @@
package dev.lambdaurora.lambdacontrols.client.gui;
import dev.lambdaurora.lambdacontrols.client.controller.Controller;
import me.lambdaurora.spruceui.option.SpruceSimpleActionOption;
import me.lambdaurora.spruceui.widget.SpruceButtonWidget;
import dev.lambdaurora.spruceui.option.SpruceSimpleActionOption;
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.toast.SystemToast;
import net.minecraft.text.LiteralText;
@@ -28,7 +28,7 @@ public class ReloadControllerMappingsOption {
public static SpruceSimpleActionOption newOption(@Nullable Consumer<SpruceButtonWidget> before) {
return SpruceSimpleActionOption.of(KEY, btn -> {
MinecraftClient client = MinecraftClient.getInstance();
var client = MinecraftClient.getInstance();
if (before != null)
before.accept(btn);
Controller.updateMappings();

View File

@@ -11,14 +11,13 @@ package dev.lambdaurora.lambdacontrols.client.gui.widget;
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsRenderer;
import me.lambdaurora.spruceui.Position;
import me.lambdaurora.spruceui.SpruceTexts;
import me.lambdaurora.spruceui.widget.AbstractSpruceIconButtonWidget;
import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.SpruceTexts;
import dev.lambdaurora.spruceui.widget.AbstractSpruceIconButtonWidget;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull;
/**
@@ -52,8 +51,8 @@ public class ControllerButtonWidget extends AbstractSpruceIconButtonWidget {
if (this.binding.getButton().length > 1) {
x += (this.width / 2 - this.iconWidth / 2) - 4;
}
Pair<Integer, Integer> size = LambdaControlsRenderer.drawButton(matrices, x, this.getY(), this.binding, MinecraftClient.getInstance());
this.iconWidth = size.key;
return size.value;
var size = LambdaControlsRenderer.drawButton(matrices, x, this.getY(), this.binding, MinecraftClient.getInstance());
this.iconWidth = size.length();
return size.height();
}
}

View File

@@ -12,11 +12,11 @@ package dev.lambdaurora.lambdacontrols.client.gui.widget;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
import me.lambdaurora.spruceui.Position;
import me.lambdaurora.spruceui.SpruceTexts;
import me.lambdaurora.spruceui.widget.SpruceButtonWidget;
import me.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.SpruceTexts;
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceContainerWidget;
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.TranslatableText;
import org.aperlambda.lambdacommon.utils.function.Predicates;
@@ -61,4 +61,10 @@ public class ControllerControlsWidget extends SpruceContainerWidget {
this.resetButton.setActive(InputManager.streamBindings().anyMatch(Predicates.not(ButtonBinding::isDefault)));
super.renderWidget(matrices, mouseX, mouseY, delta);
}
public void finishBindingEdit(int... buttons) {
if (this.focusedBinding == null) return;
this.mod.config.setButtonBinding(this.focusedBinding, buttons);
this.focusedBinding = null;
}
}

View File

@@ -13,22 +13,20 @@ import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import dev.lambdaurora.lambdacontrols.client.controller.ButtonCategory;
import dev.lambdaurora.lambdacontrols.client.controller.InputManager;
import me.lambdaurora.spruceui.Position;
import me.lambdaurora.spruceui.SpruceTexts;
import me.lambdaurora.spruceui.navigation.NavigationDirection;
import me.lambdaurora.spruceui.navigation.NavigationUtils;
import me.lambdaurora.spruceui.widget.SpruceButtonWidget;
import me.lambdaurora.spruceui.widget.SpruceSeparatorWidget;
import me.lambdaurora.spruceui.widget.SpruceWidget;
import me.lambdaurora.spruceui.widget.container.SpruceEntryListWidget;
import me.lambdaurora.spruceui.widget.container.SpruceParentWidget;
import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.SpruceTexts;
import dev.lambdaurora.spruceui.navigation.NavigationDirection;
import dev.lambdaurora.spruceui.navigation.NavigationUtils;
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
import dev.lambdaurora.spruceui.widget.SpruceSeparatorWidget;
import dev.lambdaurora.spruceui.widget.SpruceWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceEntryListWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Formatting;
@@ -36,7 +34,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
import java.util.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* Represents a control list widget.
@@ -91,8 +91,9 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
gui.focusedBinding = binding;
LambdaControlsClient.get().input.beginControlsInput(gui);
}) {
protected Optional<Text> getNarrationMessage() {
return Optional.of(binding.isNotBound() ? new TranslatableText("narrator.controls.unbound", bindingName) : new TranslatableText("narrator.controls.bound", bindingName, super.getNarrationMessage()));
protected Text getNarrationMessage() {
return binding.isNotBound() ? new TranslatableText("narrator.controls.unbound", bindingName)
: new TranslatableText("narrator.controls.bound", bindingName, super.getNarrationMessage());
}
};
this.children.add(editButton);
@@ -100,8 +101,8 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
this.editButton.getPosition().getRelativeX() + this.editButton.getWidth() + 2, 0),
44, 20, new TranslatableText("controls.reset"),
btn -> LambdaControlsClient.get().config.setButtonBinding(binding, binding.getDefaultButton())) {
protected Optional<Text> getNarrationMessage() {
return Optional.of(new TranslatableText("narrator.controls.reset", bindingName));
protected Text getNarrationMessage() {
return new TranslatableText("narrator.controls.reset", bindingName);
}
};
this.children.add(this.resetButton);
@@ -113,8 +114,8 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
gui.focusedBinding = null;
LambdaControlsClient.get().input.beginControlsInput(null);
}) {
protected Optional<Text> getNarrationMessage() {
return Optional.of(new TranslatableText("lambdacontrols.narrator.unbound", bindingName));
protected Text getNarrationMessage() {
return new TranslatableText("lambdacontrols.narrator.unbound", bindingName);
}
};
this.children.add(this.unbindButton);
@@ -151,7 +152,7 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
@Override
protected boolean onMouseClick(double mouseX, double mouseY, int button) {
Iterator<SpruceWidget> it = this.children().iterator();
var it = this.children().iterator();
SpruceWidget element;
do {
@@ -229,12 +230,11 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
protected void renderWidget(MatrixStack matrices, int mouseX, int mouseY, float delta) {
boolean focused = gui.focusedBinding == this.binding;
TextRenderer textRenderer = ControlsListWidget.this.client.textRenderer;
String bindingName = this.bindingName;
var textRenderer = ControlsListWidget.this.client.textRenderer;
int height = this.getHeight();
//float textX = (float) (this.getX() + 70 - ControlsListWidget.this.maxTextLength);
int textY = this.getY() + height / 2;
textRenderer.draw(matrices, bindingName, this.getX(), (float) (textY - 9 / 2), 16777215);
textRenderer.draw(matrices, this.bindingName, this.getX(), (float) (textY - 9 / 2), 16777215);
this.resetButton.setVisible(!focused);
this.unbindButton.setVisible(focused);
@@ -242,14 +242,14 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
this.editButton.update();
if (focused) {
MutableText text = new LiteralText("> ").formatted(Formatting.WHITE);
var text = new LiteralText("> ").formatted(Formatting.WHITE);
text.append(this.editButton.getMessage().copy().formatted(Formatting.YELLOW));
this.editButton.setMessage(text.append(new LiteralText(" <").formatted(Formatting.WHITE)));
} else if (!this.binding.isNotBound() && InputManager.hasDuplicatedBindings(this.binding)) {
MutableText text = this.editButton.getMessage().copy();
var text = this.editButton.getMessage().copy();
this.editButton.setMessage(text.formatted(Formatting.RED));
} else if (this.binding.isNotBound()) {
MutableText text = this.editButton.getMessage().copy();
var text = this.editButton.getMessage().copy();
this.editButton.setMessage(text.formatted(Formatting.GOLD));
}

View File

@@ -9,12 +9,12 @@
package dev.lambdaurora.lambdacontrols.client.mixin;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.gui.widget.ClickableWidget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(AbstractButtonWidget.class)
public interface AbstractButtonWidgetAccessor {
@Mixin(ClickableWidget.class)
public interface ClickableWidgetAccessor {
@Accessor("height")
int getHeight();
}

View File

@@ -52,9 +52,9 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
@Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
public void onMove(MovementType type, Vec3d movement, CallbackInfo ci) {
LambdaControlsClient mod = LambdaControlsClient.get();
var mod = LambdaControlsClient.get();
if (type == MovementType.SELF) {
if (this.abilities.flying && (!mod.config.hasFlyDrifting() || !mod.config.hasFlyVerticalDrifting())) {
if (this.getAbilities().flying && (!mod.config.hasFlyDrifting() || !mod.config.hasFlyVerticalDrifting())) {
if (!this.hasMovementInput()) {
if (!this.lambdacontrols$driftingPrevented) {
if (!mod.config.hasFlyDrifting())
@@ -74,7 +74,7 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z"))
public void onTickMovement(CallbackInfo ci) {
if (this.abilities.flying && this.isCamera()) {
if (this.getAbilities().flying && this.isCamera()) {
if (LambdaControlsClient.get().config.hasFlyVerticalDrifting())
return;
int moving = 0;

View File

@@ -10,12 +10,15 @@
package dev.lambdaurora.lambdacontrols.client.mixin;
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
import net.minecraft.client.gui.screen.options.GameOptionsScreen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
import net.minecraft.client.gui.screen.option.GameOptionsScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.options.GameOptions;
import net.minecraft.client.gui.widget.CyclingButtonWidget;
import net.minecraft.client.option.GameOptions;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import org.spongepowered.asm.mixin.Mixin;
@@ -31,12 +34,25 @@ public class ControlsOptionsScreenMixin extends GameOptionsScreen {
super(parent, gameOptions, text);
}
@Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/ControlsOptionsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 1))
private AbstractButtonWidget onInit(ControlsOptionsScreen screen, AbstractButtonWidget btn) {
@SuppressWarnings("unchecked")
@Redirect(
method = "init",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;",
ordinal = 1
)
)
private <T extends Element & Drawable & Selectable, R extends Element & Drawable & Selectable> R onInit(ControlsOptionsScreen screen, T element) {
/*if (this.parent instanceof ControllerControlsWidget)
return this.addButton(btn);
else*/
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).getHeight(), new TranslatableText("menu.options"),
if (element instanceof CyclingButtonWidget btn) {
return (R) this.addDrawableChild(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((ClickableWidgetAccessor) btn).getHeight(),
new TranslatableText("menu.options"),
b -> this.client.openScreen(new LambdaControlsSettingsScreen(this, true))));
} else {
return (R) this.addDrawableChild(element);
}
}
}

View File

@@ -26,7 +26,7 @@ public interface CreativeInventoryScreenAccessor {
/**
* Gets the selected tab.
*
* @return The selected tab index.
* @return the selected tab index
*/
@Accessor("selectedTab")
int getSelectedTab();
@@ -34,7 +34,7 @@ public interface CreativeInventoryScreenAccessor {
/**
* Sets the selected tab.
*
* @param group The tab's item group.
* @param group the tab's item group
*/
@Invoker("setSelectedTab")
void lambdacontrols$setSelectedTab(@NotNull ItemGroup group);
@@ -42,8 +42,8 @@ public interface CreativeInventoryScreenAccessor {
/**
* Returns whether the slot belongs to the creative inventory or not.
*
* @param slot The slot to check.
* @return True if the slot is from the creative inventory, else false.
* @param slot the slot to check
* @return true if the slot is from the creative inventory, else false
*/
@Invoker("isCreativeInventorySlot")
boolean lambdacontrols$isCreativeInventorySlot(@Nullable Slot slot);
@@ -51,7 +51,7 @@ public interface CreativeInventoryScreenAccessor {
/**
* Returns whether the current tab has a scrollbar or not.
*
* @return True if the current tab has a scrollbar, else false.
* @return true if the current tab has a scrollbar, else false
*/
@Invoker("hasScrollbar")
boolean lambdacontrols$hasScrollbar();

View File

@@ -9,7 +9,7 @@
package dev.lambdaurora.lambdacontrols.client.mixin;
import net.minecraft.client.options.GameOptions;
import net.minecraft.client.option.GameOptions;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;

View File

@@ -51,7 +51,7 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor {
@Inject(method = "render", at = @At("RETURN"))
public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) {
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
MinecraftClient client = MinecraftClient.getInstance();
var client = MinecraftClient.getInstance();
int x = 2, y = client.getWindow().getScaledHeight() - 2 - LambdaControlsRenderer.ICON_SIZE;
x = LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "lambdacontrols.action.pickup_all", true, client) + 2;

View File

@@ -10,7 +10,7 @@
package dev.lambdaurora.lambdacontrols.client.mixin;
import dev.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.option.KeyBinding;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;

View File

@@ -13,7 +13,6 @@ import dev.lambdaurora.lambdacontrols.LambdaControlsFeature;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsRenderer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.render.GameRenderer;
@@ -83,10 +82,10 @@ public abstract class MinecraftClientMixin {
int cooldown = this.itemUseCooldown;
BlockHitResult hitResult;
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.BLOCK && this.player.abilities.flying) {
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.BLOCK && this.player.getAbilities().flying) {
hitResult = (BlockHitResult) this.crosshairTarget;
BlockPos targetPos = hitResult.getBlockPos();
Direction side = hitResult.getSide();
var targetPos = hitResult.getBlockPos();
var side = hitResult.getSide();
boolean sidewaysBlockPlacing = this.lambdacontrols$lastTargetPos == null || !targetPos.equals(this.lambdacontrols$lastTargetPos.offset(this.lambdacontrols$lastTargetSide));
boolean backwardsBlockPlacing = this.player.input.movementForward < 0.0f && (this.lambdacontrols$lastTargetPos == null || targetPos.equals(this.lambdacontrols$lastTargetPos.offset(this.lambdacontrols$lastTargetSide)));
@@ -123,11 +122,11 @@ public abstract class MinecraftClientMixin {
@Inject(method = "doItemUse()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
private void onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand) {
LambdaControlsClient mod = LambdaControlsClient.get();
if (!stackInHand.isEmpty() && this.player.pitch > 35.0F && mod.reacharound.isReacharoundAvailable()) {
var mod = LambdaControlsClient.get();
if (!stackInHand.isEmpty() && this.player.getPitch(0.f) > 35.0F && mod.reacharound.isReacharoundAvailable()) {
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.MISS && this.player.isOnGround()) {
if (!stackInHand.isEmpty() && stackInHand.getItem() instanceof BlockItem) {
BlockHitResult hitResult = mod.reacharound.getLastReacharoundResult();
var hitResult = mod.reacharound.getLastReacharoundResult();
if (hitResult == null)
return;
@@ -135,7 +134,7 @@ public abstract class MinecraftClientMixin {
hitResult = mod.reacharound.withSideForReacharound(hitResult, stackInHand);
int previousStackCount = stackInHand.getCount();
ActionResult result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult);
var result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult);
if (result.isAccepted()) {
if (result.shouldSwingHand()) {
this.player.swingHand(hand);

View File

@@ -15,6 +15,7 @@ import dev.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
import dev.lambdaurora.lambdacontrols.client.util.MouseAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Mouse;
import net.minecraft.client.gui.screen.Screen;
import org.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -29,8 +30,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
* Adds extra access to the mouse.
*/
@Mixin(Mouse.class)
public abstract class MouseMixin implements MouseAccessor
{
public abstract class MouseMixin implements MouseAccessor {
@Shadow
@Final
private MinecraftClient client;
@@ -39,20 +39,18 @@ public abstract class MouseMixin implements MouseAccessor
public abstract void lambdacontrols$onCursorPos(long window, double x, double y);
@Inject(method = "method_1605", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/Screen;mouseReleased(DDI)Z"))
private void onMouseBackButton(boolean[] result, double mouseX, double mouseY, int button, CallbackInfo ci)
{
if (!result[0] && button == GLFW.GLFW_MOUSE_BUTTON_4 && this.client.currentScreen != null) {
if (LambdaControlsClient.get().input.tryGoBack(this.client.currentScreen)) {
private static void onMouseBackButton(boolean[] result, Screen screen, double mouseX, double mouseY, int button, CallbackInfo ci) {
if (!result[0] && button == GLFW.GLFW_MOUSE_BUTTON_4 && screen != null) {
if (LambdaControlsClient.get().input.tryGoBack(screen)) {
result[0] = true;
}
}
}
@Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true)
private void isCursorLocked(CallbackInfoReturnable<Boolean> ci)
{
private void isCursorLocked(CallbackInfoReturnable<Boolean> ci) {
if (this.client.currentScreen == null) {
LambdaControlsConfig config = LambdaControlsClient.get().config;
var config = LambdaControlsClient.get().config;
if (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse()) {
ci.setReturnValue(true);
ci.cancel();
@@ -61,11 +59,10 @@ public abstract class MouseMixin implements MouseAccessor
}
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
private void onCursorLocked(CallbackInfo ci)
{
private void onCursorLocked(CallbackInfo ci) {
LambdaControlsConfig config = LambdaControlsClient.get().config;
if (config.getControlsMode() == ControlsMode.TOUCHSCREEN
|| (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse()))
if (/*config.getControlsMode() == ControlsMode.TOUCHSCREEN
||*/ (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse()))
ci.cancel();
}
}

View File

@@ -12,9 +12,11 @@ package dev.lambdaurora.lambdacontrols.client.mixin;
import dev.lambdaurora.lambdacontrols.ControlsMode;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import dev.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.options.OptionsScreen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.gui.screen.option.OptionsScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
@@ -30,13 +32,22 @@ public class OptionsScreenMixin extends Screen {
super(title);
}
@Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/OptionsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 7))
private AbstractButtonWidget lambdacontrols$onInit(OptionsScreen screen, AbstractButtonWidget btn) {
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).getHeight(), btn.getMessage(),
@SuppressWarnings("unchecked")
@Redirect(
method = "init",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/gui/screen/option/OptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;",
ordinal = 7
)
)
private <T extends Element & Drawable & Selectable> T lambdacontrols$onInit(OptionsScreen screen, T element) {
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER && element instanceof ButtonWidget btn) {
return (T) this.addDrawableChild(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((ClickableWidgetAccessor) btn).getHeight(),
btn.getMessage(),
b -> this.client.openScreen(new LambdaControlsSettingsScreen(this, false))));
} else {
return this.addButton(btn);
return this.addDrawableChild(element);
}
}
}

View File

@@ -10,8 +10,6 @@
package dev.lambdaurora.lambdacontrols.client.mixin;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*;
@@ -19,14 +17,10 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -70,30 +64,30 @@ public abstract class WorldRendererMixin {
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !LambdaControlsClient.get().config.shouldRenderReacharoundOutline())
return;
BlockHitResult result = LambdaControlsClient.get().reacharound.getLastReacharoundResult();
var result = LambdaControlsClient.get().reacharound.getLastReacharoundResult();
if (result == null)
return;
BlockPos blockPos = result.getBlockPos();
var blockPos = result.getBlockPos();
if (this.world.getWorldBorder().contains(blockPos)) {
ItemStack stack = this.client.player.getStackInHand(Hand.MAIN_HAND);
var stack = this.client.player.getStackInHand(Hand.MAIN_HAND);
if (stack == null || !(stack.getItem() instanceof BlockItem))
return;
LambdaControlsClient mod = LambdaControlsClient.get();
var mod = LambdaControlsClient.get();
Block block = ((BlockItem) stack.getItem()).getBlock();
var block = ((BlockItem) stack.getItem()).getBlock();
result = mod.reacharound.withSideForReacharound(result, block);
ItemPlacementContext context = new ItemPlacementContext(new ItemUsageContext(this.client.player, Hand.MAIN_HAND, result));
var context = new ItemPlacementContext(new ItemUsageContext(this.client.player, Hand.MAIN_HAND, result));
BlockState placementState = block.getPlacementState(context);
var placementState = block.getPlacementState(context);
if (placementState == null)
return;
Vec3d pos = camera.getPos();
var pos = camera.getPos();
VoxelShape outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
var outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
int[] color = mod.config.getReacharoundOutlineColor();
VertexConsumer vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
drawShapeOutline(matrices, vertexConsumer, outlineShape,
(double) blockPos.getX() - pos.getX(), (double) blockPos.getY() - pos.getY(), (double) blockPos.getZ() - pos.getZ(),
color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);

View File

@@ -31,6 +31,6 @@ public class DummyRingAction extends RingAction {
@Override
public void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) {
drawCenteredString(matrices, textRenderer, this.getName(), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff);
drawCenteredText(matrices, textRenderer, this.getName(), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff);
}
}

View File

@@ -13,7 +13,7 @@ import com.electronwill.nightconfig.core.Config;
import dev.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.TranslatableText;
import org.jetbrains.annotations.NotNull;
@@ -39,14 +39,11 @@ public class KeyBindingRingAction extends RingAction {
public void onAction(@NotNull RingButtonMode mode) {
KeyBindingAccessor accessor = (KeyBindingAccessor) this.binding;
switch (mode) {
case PRESS:
case HOLD:
accessor.lambdacontrols_handlePressState(this.activated);
break;
case TOGGLE:
accessor.lambdacontrols_handlePressState(!this.binding.isPressed());
case PRESS, HOLD -> accessor.lambdacontrols$handlePressState(this.activated);
case TOGGLE -> {
accessor.lambdacontrols$handlePressState(!this.binding.isPressed());
this.activated = !this.binding.isPressed();
break;
}
}
}

View File

@@ -11,25 +11,25 @@ package dev.lambdaurora.lambdacontrols.client.ring;
import com.electronwill.nightconfig.core.Config;
import dev.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Represents a key binding ring.
*
* @author LambdAurora
* @version 1.5.0
* @version 1.7.0
* @since 1.4.0
*/
public final class LambdaRing {
public static final int ELEMENT_SIZE = 50;
private final Object2ObjectMap<String, RingAction.Factory> actionFactories = new Object2ObjectOpenHashMap<>();
private final Map<String, RingAction.Factory> actionFactories = new Object2ObjectOpenHashMap<>();
private final List<RingPage> pages = new ArrayList<>(Collections.singletonList(RingPage.DEFAULT));
private final LambdaControlsClient mod;
private int currentPage = 0;
@@ -49,13 +49,13 @@ public final class LambdaRing {
/**
* Loads the ring from configuration.
*
* @param config The configuration.
* @param config the configuration
*/
public void load(@NotNull Config config) {
List<Config> configPages = config.get("ring.pages");
if (configPages != null) {
this.pages.clear();
for (Config configPage : configPages) {
for (var configPage : configPages) {
RingPage.parseRingPage(configPage).ifPresent(this.pages::add);
}
}

View File

@@ -40,7 +40,7 @@ public abstract class RingAction extends DrawableHelper implements Nameable {
/**
* Gets the text name of the ring action.
*
* @return The text name.
* @return the text name
*/
public Text getTextName() {
return new TranslatableText(this.getName());
@@ -49,7 +49,7 @@ public abstract class RingAction extends DrawableHelper implements Nameable {
/**
* Returns whether the action is activated or not.
*
* @return True if the action is activated, else false.
* @return true if the action is activated, else false
*/
public boolean isActivated() {
return this.activated;

View File

@@ -37,10 +37,10 @@ public enum RingButtonMode implements Nameable {
/**
* Returns the next ring button mode available.
*
* @return The next ring button mode.
* @return the next ring button mode
*/
public @NotNull RingButtonMode next() {
RingButtonMode[] v = values();
var v = values();
if (v.length == this.ordinal() + 1)
return v[0];
return v[this.ordinal() + 1];
@@ -49,7 +49,7 @@ public enum RingButtonMode implements Nameable {
/**
* Returns the translation key of this ring button mode.
*
* @return The translation key of this ring button mode.
* @return the translation key of this ring button mode
*/
public @NotNull String getTranslationKey() {
return "lambdacontrols.ring.button_mode." + this.getName();
@@ -58,7 +58,7 @@ public enum RingButtonMode implements Nameable {
/**
* Gets the translated name of this ring button mode.
*
* @return The translated name of this ring button mode.
* @return the translated name of this ring button mode
*/
public @NotNull Text getTranslatedText() {
return this.text;

View File

@@ -41,12 +41,12 @@ public class RingPage extends DrawableHelper {
/**
* Renders the ring page.
*
* @param matrices The matrices.
* @param width The screen width.
* @param height The screen height.
* @param mouseX The mouse X-coordinate.
* @param mouseY The mouse Y-coordinate.
* @param tickDelta The tick delta.
* @param matrices the matrices
* @param width the screen width
* @param height the screen height
* @param mouseX the mouse X-coordinate
* @param mouseY the mouse Y-coordinate
* @param tickDelta the tick delta
*/
public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int width, int height, int mouseX, int mouseY, float tickDelta) {
int centerX = width / 2;
@@ -57,7 +57,7 @@ public class RingPage extends DrawableHelper {
int y = centerY - offset;
int x = centerX - offset;
for (int i = 0; i < 3; i++) {
RingAction ringAction = this.actions[i];
var ringAction = this.actions[i];
if (ringAction != null)
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
x += 55;
@@ -65,7 +65,7 @@ public class RingPage extends DrawableHelper {
y += 55;
x = centerX - offset;
for (int i = 3; i < 5; i++) {
RingAction ringAction = this.actions[i];
var ringAction = this.actions[i];
if (ringAction != null)
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
x += 55 * 2;
@@ -73,7 +73,7 @@ public class RingPage extends DrawableHelper {
y += 55;
x = centerX - offset;
for (int i = 5; i < 8; i++) {
RingAction ringAction = this.actions[i];
var ringAction = this.actions[i];
if (ringAction != null)
ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY));
x += 55;
@@ -87,15 +87,15 @@ public class RingPage extends DrawableHelper {
/**
* Tries to parse a ring page configuration.
*
* @param config The configuration.
* @return An optional ring page.
* @param config the configuration
* @return an optional ring page
*/
public static @NotNull Optional<RingPage> parseRingPage(@NotNull Config config) {
String name = config.get("name");
if (name == null)
return Optional.empty();
RingPage page = new RingPage(name);
var page = new RingPage(name);
List<Config> actionConfigs = config.get("actions");

View File

@@ -20,35 +20,35 @@ public interface HandledScreenAccessor {
/**
* Gets the left coordinate of the GUI.
*
* @return The left coordinate of the GUI.
* @return the left coordinate of the GUI
*/
int getX();
/**
* Gets the top coordinate of the GUI.
*
* @return The top coordinate of the GUI.
* @return the top coordinate of the GUI
*/
int getY();
/**
* Gets the slot at position.
*
* @param pos_x The X position to check.
* @param pos_y The Y position to check.
* @return The slot at the specified position.
* @param posX the X position to check
* @param posY the Y position to check
* @return the slot at the specified position
*/
Slot lambdacontrols$getSlotAt(double pos_x, double pos_y);
Slot lambdacontrols$getSlotAt(double posX, double posY);
boolean lambdacontrols$isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button);
/**
* Handles a mouse click on the specified slot.
*
* @param slot The slot instance.
* @param slotId The slot id.
* @param clickData The click data.
* @param actionType The action type.
* @param slot the slot instance
* @param slotId the slot id
* @param clickData the click data
* @param actionType the action type
*/
void lambdacontrols$onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
}

View File

@@ -17,7 +17,7 @@ public interface KeyBindingAccessor {
boolean lambdacontrols$unpress();
default boolean lambdacontrols_handlePressState(boolean pressed) {
default boolean lambdacontrols$handlePressState(boolean pressed) {
if (pressed)
return this.lambdacontrols$press();
else

View File

@@ -3,12 +3,12 @@
"id": "lambdacontrols",
"name": "LambdaControls",
"version": "${version}",
"description": "Adds better controls: controller and touchscreen support.",
"description": "Adds better controls, and controller support.",
"authors": [
"LambdAurora"
],
"contact": {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/lambdacontrols",
"homepage": "https://modrinth.com/mod/lambdacontrols",
"sources": "https://github.com/LambdAurora/LambdaControls.git",
"issues": "https://github.com/LambdAurora/LambdaControls/issues"
},
@@ -26,23 +26,23 @@
"dev.lambdaurora.lambdacontrols.client.LambdaControlsModMenu"
]
},
"accessWidener": "lambdacontrols.accesswidener",
"mixins": [
"lambdacontrols.mixins.json",
"lambdacontrols_compat.mixins.json"
],
"depends": {
"fabricloader": ">=0.11.1",
"fabric": ">=0.29.3",
"minecraft": ">=1.16.2",
"spruceui": ">=1.6.3"
"fabricloader": ">=0.11.3",
"fabric": ">=0.36.0",
"minecraft": ">=1.7",
"spruceui": ">=3.1.0",
"java": ">=16"
},
"recommends": {
"modmenu": ">=1.12.2"
},
"suggests": {
"flamingo": "*",
"roughlyenoughitems": ">=4.5.5",
"okzoomer": ">=4.0.0"
"flamingo": "*"
},
"breaks": {
"modmenu": "<1.12.2",

View File

@@ -0,0 +1,3 @@
accessWidener v1 named
accessible class net/minecraft/client/gui/widget/EntryListWidget$MoveDirection

View File

@@ -1,9 +1,9 @@
{
"required": true,
"package": "dev.lambdaurora.lambdacontrols.client.mixin",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_16",
"client": [
"AbstractButtonWidgetAccessor",
"ClickableWidgetAccessor",
"AdvancementsScreenAccessor",
"ClientPlayerEntityMixin",
"ControlsOptionsScreenMixin",

View File

@@ -2,12 +2,8 @@
"required": true,
"package": "dev.lambdaurora.lambdacontrols.client.compat.mixin",
"plugin": "dev.lambdaurora.lambdacontrols.client.compat.LambdaControlsMixinPlugin",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_16",
"client": [
"EntryListWidgetAccessor",
"EntryWidgetAccessor",
"RecipeViewingScreenAccessor",
"VillagerRecipeViewingScreenAccessor"
],
"injectors": {
"defaultRequire": 1