Merge pull request #259 from TeamMidnightDust/1.20.4

Backport changes from 1.9.0+
This commit is contained in:
Martin Prokoph
2024-02-03 13:16:41 +01:00
committed by GitHub
64 changed files with 1144 additions and 763 deletions

View File

@@ -62,6 +62,14 @@ Enter the folder created and run:
``` ```
After this is done, everything should be built just fine! After this is done, everything should be built just fine!
## FAQ:
### The controller does not work, and it's name appears in orange, what can I do?
Orange controller names indicate a missing controller mapping.
Download [GamepadTool](https://generalarcade.com/gamepadtool/), create and copy a mapping, go to MidnightControls' Mappings File Editor and paste the string.
Alternatively, you can use [AntiMicroX](https://github.com/AntiMicroX/antimicroX) to create the mappings, in case the Gamepad Tool is not working for you.
If that works, you might as well consider submitting the mapping by opening a PR in this repo: https://github.com/gabomdq/SDL_GameControllerDB
That will make sure other people using the same controller as you don't have to use gamepad-tool anymore.
[Quilt]: https://quiltmc.org [Quilt]: https://quiltmc.org
[Mod loader: Quilt/Fabric]: https://img.shields.io/badge/modloader-Quilt%2FFabric-blueviolet?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAADGAAAAxgGwdJvFAAAFU0lEQVR4nO1bwW7bOBCdCHtP+wUNxIvhS7yA7kkPOjf9AKPam4/OF2zzB96bblXhH0jPPkS5G1jnIvgib/IFtX/ALoYZemmKtEWRRe3aDzAsURbJGQ6HM4/02Wq1gmNGcNTSnxQA8IdakDK4AOCfJpj3SpiI98r2rAMAbxrWNWFFOMeL1nCJdXQa1gPTbpCbnm34ABIeBThv2hgAfOyVcF+2ZwkAfHGo54kVIRe6NVxiny4d6vpn2g36ugfqFLhwFB6kkUoc67k0XLv0qYKj9wEnBXiqZwEAf/ZKOOuV8BkLWBFesyI8A4C/LOt6AoC39C7HtBvg9Vt65hUnC/BUDzrOf1MGq5S9WkDZnuVle7ZqsBKgw/tO73K0hku8/u64EmhxsoA96MMvxdEroBIKO+CWoshnqqJPYTAGRJ8sql3QO3Op7D19D3z7AV8KeAGArFf+32lWhDwnKNuzuaUCclaE93KBiOU9hMQV+FLAOxz9lPHRR0VkZXs2oBDUNon5ULZnKOgcYwl4FTwna/K+CtRRwIK+dTnCCwkP9I0fkXmh4FcN+6UKqqtHblvtb+18po4TvKaPilsS8qVuYx5havsbJXS1I0ZVAXP1B5jfyzm+hAnN+We1XPluioX03kJtY9oNtG1T+b1aburDxhRAQVMGHw3z9k65F41nktmjUnjjrAj7ZXv27ECIyEKgBd7saBuka7lsPu0GA1MjR0+KVpwgMTlrMkN4YoztlZ/2camTvD0QjcWZF6KxMgcLyKbdAN+HKOb1y6PYH49gEsUwUKw1G48gi2KQZcApkYxH1eldUQBxeKbkRfXEQjDZ21+h2bMiHJDwH2wk1rSX0XWueHZd2yCZ/oVSnilTaA3VAiqjRRahQ0JBjuov3ijfPqAua0kUg67tmyjWCmvsS504wGQRnywjPJ8wtY3xw3827fjMBXziUalL3DcNrIzYRwXcTbvBZ7lgPHoNxKKYky1/+2xsHxXQbw2X/EIoggQHyjC9Yh8VcC6NshDc66jLOHpC5KSAPejDL8U+KuArboTQZgjHeARn+MFnvhvbRyfYaQ2XfNkTVFgUr/mIxlvkJuyjAjCae6BrYQUPW37vhDpT4MnAsCyIgbHBnYbcADJt7/t+deBCiSWsCG8sOv5IgU2FnJh2g+RnBDl1oCpgogqEx1TEURUFokx+tpCYnEzzjg1kh+fq/Ix9OXpG6OjjgI1VIGWcOMhlXh4PPdAz1VTe90rIU8Z/L9JUnALXSK4SjSUzOY+Y1ekyOlzjaamTvf3X8cjunBH1v6OeVtsG1QI66qYEVkoVmyA/O5fYmIHjgSsrskUavAc6q1BLeXXiANMZu0HKwGav7opGv+LticZqHOToLBeZrJRxC97qjOsowCTgZYO9OlNa25haMwgvsFMJPp3gLW1ji8b6dO89fhfYIbzAl23T4adtjyNvD6/mbbs9Xgs1hRcwWoIvCxDb47nQNm5aRDHvoPGcblNYCi+gtQSfU+AdLYfioLXYtHA9eruBhsILVJRwUIGQo/ACG0o4GAV4El5grQSffMA3SqbEnBdb1zeunfYsvAB3jL4UwE92KauA2NnNbLerNKhEqJ6Q+FIAOjpcATAVzjFHoC3qC9OurCW0W9s+6vXpAy4p0hPkSUL3ziNHiY3tqfNdQN4jORgnSEGMLyU8Udbq1QIEdEyRF3hSwlp4vKkwQimrHDuxAR6S4tleFIPzERnhSFXQEtbkD1kbwiMOlhJroISK8IiDpcQsp4NWeMRBc4I1lWAUHnHwpOgOJWwVHvFbsMIGJewUHvFb7QuQYxR/ttgIzbUAgB9KOM3uc+PN7QAAAABJRU5ErkJggg== [Mod loader: Quilt/Fabric]: https://img.shields.io/badge/modloader-Quilt%2FFabric-blueviolet?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAADGAAAAxgGwdJvFAAAFU0lEQVR4nO1bwW7bOBCdCHtP+wUNxIvhS7yA7kkPOjf9AKPam4/OF2zzB96bblXhH0jPPkS5G1jnIvgib/IFtX/ALoYZemmKtEWRRe3aDzAsURbJGQ6HM4/02Wq1gmNGcNTSnxQA8IdakDK4AOCfJpj3SpiI98r2rAMAbxrWNWFFOMeL1nCJdXQa1gPTbpCbnm34ABIeBThv2hgAfOyVcF+2ZwkAfHGo54kVIRe6NVxiny4d6vpn2g36ugfqFLhwFB6kkUoc67k0XLv0qYKj9wEnBXiqZwEAf/ZKOOuV8BkLWBFesyI8A4C/LOt6AoC39C7HtBvg9Vt65hUnC/BUDzrOf1MGq5S9WkDZnuVle7ZqsBKgw/tO73K0hku8/u64EmhxsoA96MMvxdEroBIKO+CWoshnqqJPYTAGRJ8sql3QO3Op7D19D3z7AV8KeAGArFf+32lWhDwnKNuzuaUCclaE93KBiOU9hMQV+FLAOxz9lPHRR0VkZXs2oBDUNon5ULZnKOgcYwl4FTwna/K+CtRRwIK+dTnCCwkP9I0fkXmh4FcN+6UKqqtHblvtb+18po4TvKaPilsS8qVuYx5havsbJXS1I0ZVAXP1B5jfyzm+hAnN+We1XPluioX03kJtY9oNtG1T+b1aburDxhRAQVMGHw3z9k65F41nktmjUnjjrAj7ZXv27ECIyEKgBd7saBuka7lsPu0GA1MjR0+KVpwgMTlrMkN4YoztlZ/2camTvD0QjcWZF6KxMgcLyKbdAN+HKOb1y6PYH49gEsUwUKw1G48gi2KQZcApkYxH1eldUQBxeKbkRfXEQjDZ21+h2bMiHJDwH2wk1rSX0XWueHZd2yCZ/oVSnilTaA3VAiqjRRahQ0JBjuov3ijfPqAua0kUg67tmyjWCmvsS504wGQRnywjPJ8wtY3xw3827fjMBXziUalL3DcNrIzYRwXcTbvBZ7lgPHoNxKKYky1/+2xsHxXQbw2X/EIoggQHyjC9Yh8VcC6NshDc66jLOHpC5KSAPejDL8U+KuArboTQZgjHeARn+MFnvhvbRyfYaQ2XfNkTVFgUr/mIxlvkJuyjAjCae6BrYQUPW37vhDpT4MnAsCyIgbHBnYbcADJt7/t+deBCiSWsCG8sOv5IgU2FnJh2g+RnBDl1oCpgogqEx1TEURUFokx+tpCYnEzzjg1kh+fq/Ix9OXpG6OjjgI1VIGWcOMhlXh4PPdAz1VTe90rIU8Z/L9JUnALXSK4SjSUzOY+Y1ekyOlzjaamTvf3X8cjunBH1v6OeVtsG1QI66qYEVkoVmyA/O5fYmIHjgSsrskUavAc6q1BLeXXiANMZu0HKwGav7opGv+LticZqHOToLBeZrJRxC97qjOsowCTgZYO9OlNa25haMwgvsFMJPp3gLW1ji8b6dO89fhfYIbzAl23T4adtjyNvD6/mbbs9Xgs1hRcwWoIvCxDb47nQNm5aRDHvoPGcblNYCi+gtQSfU+AdLYfioLXYtHA9eruBhsILVJRwUIGQo/ACG0o4GAV4El5grQSffMA3SqbEnBdb1zeunfYsvAB3jL4UwE92KauA2NnNbLerNKhEqJ6Q+FIAOjpcATAVzjFHoC3qC9OurCW0W9s+6vXpAy4p0hPkSUL3ziNHiY3tqfNdQN4jORgnSEGMLyU8Udbq1QIEdEyRF3hSwlp4vKkwQimrHDuxAR6S4tleFIPzERnhSFXQEtbkD1kbwiMOlhJroISK8IiDpcQsp4NWeMRBc4I1lWAUHnHwpOgOJWwVHvFbsMIGJewUHvFb7QuQYxR/ttgIzbUAgB9KOM3uc+PN7QAAAABJRU5ErkJggg==

View File

@@ -3,25 +3,14 @@ plugins {
id 'java-library' id 'java-library'
id 'maven-publish' id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '7.0.0' id 'com.github.johnrengelman.shadow' version '7.0.0'
id 'com.modrinth.minotaur' version '1.2.+' id 'com.modrinth.minotaur' version '2.+'
id 'net.darkhax.curseforgegradle' version '1.+'
} }
import com.google.gson.GsonBuilder import net.darkhax.curseforgegradle.TaskPublishCurseForge
import com.google.gson.JsonObject
import com.modrinth.minotaur.TaskModrinthUpload
import com.modrinth.minotaur.request.VersionType
import com.modrinth.minotaur.responses.ResponseError
import org.apache.http.client.config.CookieSpecs
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.entity.EntityBuilder
import org.apache.http.client.methods.HttpPatch
import org.apache.http.entity.ContentType
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.util.EntityUtils
group = project.maven_group group = project.maven_group
version = "${project.mod_version}+${getMCVersionString()}" version = "${project.mod_version}+${getMCVersionString()}"
archivesBaseName = project.archives_base_name
// This field defines the Java version your mod target. // This field defines the Java version your mod target.
def targetJavaVersion = 17 def targetJavaVersion = 17
@@ -32,7 +21,7 @@ boolean isMCVersionNonRelease() {
} }
String getMCVersionString() { String getMCVersionString() {
if (isMCVersionNonRelease() || project.minecraft_version == "1.19.4") { if (isMCVersionNonRelease() || project.minecraft_version == "1.20.4") {
return project.minecraft_version return project.minecraft_version
} }
def version = project.minecraft_version.split('\\.') def version = project.minecraft_version.split('\\.')
@@ -159,115 +148,39 @@ processResources {
expand 'version': project.version expand 'version': project.version
} }
} }
modrinth {
token = System.getenv("MODRINTH_TOKEN") // Remember to have the MODRINTH_TOKEN environment variable set or else this will fail - just make sure it stays private!
projectId = project.archives_base_name // This can be the project ID or the slug. Either will work!
versionNumber = project.version // You don't need to set this manually. Will fail if Modrinth has this version already
versionName = "MidnightControls " + project.mod_version + " - " + project.minecraft_version
versionType = isMCVersionNonRelease() ? "beta" : "release" // Can also be `beta` or `alpha`
uploadFile = remapJar // With Loom, this MUST be set to `remapJar` instead of `jar`!
gameVersions = [(String) project.minecraft_version] // Must be an array, even with only one version
loaders = ["fabric","quilt"] // Must also be an array - no need to specify this if you're using Loom or ForgeGradle
dependencies { // A special DSL for creating dependencies
// scope.type
// The scope can be `required`, `optional`, `incompatible`, or `embedded`
// The type can either be `project` or `version`
required.project "midnightlib" // Creates a new required dependency on MidnightLib
}
changelog = project.changelog
}
tasks.register('publishCurseForge', TaskPublishCurseForge) {
task publishModrinth(type: TaskModrinthUpload) { // This token is used to authenticate with CurseForge. It should be handled
dependsOn(build) // with the same level of care and security as your actual password. You
onlyIf { // should never share your token with an untrusted source or publish it
System.getenv('MODRINTH_TOKEN') // publicly to GitHub or embed it within a project. The best practice is to
} // store this token in an environment variable or a build secret.
apiToken = System.getenv("CURSEFORGE_TOKEN")
token = System.getenv('MODRINTH_TOKEN') // Tells CurseForgeGradle to publish the output of the jar task. This will
projectId = project.modrinth_id // return a UploadArtifact object that can be used to further configure the
versionNumber = version // file.
versionName = "midnightcontrols ${project.mod_version} (${getMCVersionString()})" def mainFile = upload(project.curseforge_id, remapJar)
addGameVersion((String) project.minecraft_version) mainFile.changelog = project.changelog
addLoader('fabric') mainFile.displayName = "MidnightControls " + project.mod_version + " - " + project.minecraft_version
versionType = isMCVersionNonRelease() ? VersionType.BETA : VersionType.RELEASE mainFile.addModLoader("Fabric", "Quilt")
mainFile.addRequirement("midnightlib")
// Changelog fetching mainFile.releaseType = "release"
def changelogText = file('CHANGELOG.md').text
def regexVersion = ((String) project.mod_version).replaceAll('\\.', /\\./).replaceAll('\\+', '\\+')
def changelogRegex = ~"###? ${regexVersion}\\n\\n(( *- .+\\n)+)"
def matcher = changelogText =~ changelogRegex
if (matcher.find()) {
changelog = matcher.group(1)
def changelogLines = changelogText.split('\n')
def linkRefRegex = ~'^\\[([A-z0-9 _\\-/+.]+)]: '
for (int i = changelogLines.length - 1; i > 0; i--) {
def line = changelogLines[i]
if ((line =~ linkRefRegex).find())
changelog += '\n' + line
else break
}
}
// Readme
doFirst {
final def client = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
final def patch = new HttpPatch((String) (apiURL + '/v1/mod/' + projectId))
patch.addHeader("Authorization", token)
var json = new JsonObject()
json.addProperty("body", parseReadme())
patch.setEntity(EntityBuilder.create()
.setText(json.toString())
.setContentType(ContentType.APPLICATION_JSON)
.build())
final def response = client.execute(patch)
final int status = response.getStatusLine().getStatusCode()
final def gson = new GsonBuilder().create()
if (status == 200) {
project.getLogger().lifecycle("Successfully updated readme to ${projectId}.")
} else {
errorInfo = gson.fromJson(EntityUtils.toString(response.getEntity()), ResponseError.class)
project.getLogger().error("Upload failed! Status: ${status} Error: ${errorInfo.getError()} Reason: ${errorInfo.getDescription()}")
throw new GradleException("Upload failed! Status: ${status} Reason: ${errorInfo.getDescription()}")
}
}
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
artifact(sourcesJar) {
builtBy remapSourcesJar
}
pom {
name = 'midnightcontrols'
description = 'Adds better controls, and controller support.'
}
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.shadow.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', 'compile')
}
}
}
}
repositories {
mavenLocal()
maven {
name 'GithubPackages'
url uri('https://maven.pkg.github.com/LambdAurora/midnightcontrols')
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
}
}
def midnightcontrolsMaven = System.getenv('midnightcontrols_MAVEN')
if (midnightcontrolsMaven) {
maven {
name 'midnightcontrolsMaven'
url uri(midnightcontrolsMaven)
credentials {
username = project.findProperty('gpr.user') ?: System.getenv('MAVEN_USERNAME')
password = project.findProperty('gpr.key') ?: System.getenv('MAVEN_PASSWORD')
}
}
}
}
} }

View File

@@ -3,22 +3,24 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/use # check these on https://fabricmc.net/use
minecraft_version=1.20 minecraft_version=1.20.4
yarn_mappings=1.20+build.1 yarn_mappings=1.20.4+build.3
loader_version=0.14.21 loader_version=0.15.3
# Mod Properties # Mod Properties
mod_version = 1.8.2 mod_version = 1.9.3
maven_group = eu.midnightdust maven_group = eu.midnightdust
archives_base_name = midnightcontrols archives_base_name = midnightcontrols
modrinth_id = bXX9h73M modrinth_id = bXX9h73M
curseforge_id = 621768
changelog = See changes at: https://github.com/TeamMidnightDust/MidnightControls/commits/
# Dependencies # Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.83.0+1.20 fabric_version=0.91.3+1.20.4
sodium_version=mc1.19.2-0.4.4 sodium_version=mc1.19.2-0.4.4
spruceui_version=5.0.0+1.20 spruceui_version=5.0.3+1.20.4
midnightlib_version=1.4.1-fabric midnightlib_version=1.5.3-fabric
modmenu_version=7.0.0 modmenu_version=7.0.0
emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric
bendylib_version=2.0.+ bendylib_version=2.0.+

Binary file not shown.

View File

@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

41
gradlew vendored
View File

@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,13 +80,11 @@ do
esac esac
done done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # This is normally unused
# shellcheck disable=SC2034
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@@ -133,22 +131,29 @@ location of your Java installation."
fi fi
else else
JAVACMD=java JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #( case $MAX_FD in #(
max*) max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) || MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit" warn "Could not query maximum file descriptor limit"
esac esac
case $MAX_FD in #( case $MAX_FD in #(
'' | soft) :;; #( '' | soft) :;; #(
*) *)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" || ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD" warn "Could not set maximum file descriptor limit to $MAX_FD"
esac esac
@@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
done done
fi fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
# shell script including quotes and variable substitutions, so put them in DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded. # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
@@ -205,6 +214,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \ org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args. # Use "xargs" to parse quoted args.
# #
# With -n1 it outputs one arg per line, with the quotes and backslashes removed. # With -n1 it outputs one arg per line, with the quotes and backslashes removed.

11
gradlew.bat vendored
View File

@@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if %ERRORLEVEL% equ 0 goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 set EXIT_CODE=%ERRORLEVEL%
exit /b 1 if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal

View File

@@ -10,12 +10,12 @@
package eu.midnightdust.midnightcontrols.client; package eu.midnightdust.midnightcontrols.client;
import dev.lambdaurora.spruceui.event.OpenScreenCallback; import dev.lambdaurora.spruceui.event.OpenScreenCallback;
import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.MidnightControls; import eu.midnightdust.midnightcontrols.MidnightControls;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants; import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.MidnightControlsFeature; import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
import eu.midnightdust.midnightcontrols.client.compat.VoxelMapCompat;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory; import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.Controller;
@@ -24,10 +24,11 @@ import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsHud;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor; import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingRegistryImplAccessor;
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction; import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing; import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
import dev.lambdaurora.spruceui.hud.HudManager; import dev.lambdaurora.spruceui.hud.HudManager;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
@@ -47,6 +48,7 @@ import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.io.File; import java.io.File;
import java.util.Objects;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@@ -59,7 +61,6 @@ import java.util.TimerTask;
*/ */
public class MidnightControlsClient extends MidnightControls implements ClientModInitializer { public class MidnightControlsClient extends MidnightControls implements ClientModInitializer {
public static boolean lateInitDone = false; public static boolean lateInitDone = false;
public static boolean voxelmapInitDone = false;
private static MidnightControlsClient INSTANCE; private static MidnightControlsClient INSTANCE;
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_up"), public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(new Identifier(MidnightControlsConstants.NAMESPACE, "look_up"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement"); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement");
@@ -122,20 +123,21 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight()); this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight());
} }
}); });
final MinecraftClient client = MinecraftClient.getInstance();
int delay = 0; // delay for 0 sec.
int period = 1; // repeat every 0.001 sec. (100 times a second)
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
input.updateCamera(client);
}
}, delay, period);
HudManager.register(this.hud = new MidnightControlsHud(this)); HudManager.register(this.hud = new MidnightControlsHud(this));
FabricLoader.getInstance().getModContainer("midnightcontrols").ifPresent(modContainer -> { FabricLoader.getInstance().getModContainer("midnightcontrols").ifPresent(modContainer -> {
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","bedrock"), modContainer, ResourcePackActivationType.NORMAL); ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","bedrock"), modContainer, ResourcePackActivationType.NORMAL);
ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","legacy"), modContainer, ResourcePackActivationType.NORMAL); ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","legacy"), modContainer, ResourcePackActivationType.NORMAL);
}); });
int delay = 0; // delay for 0 sec.
int period = 1; // repeat every 0.001 sec. (100 times a second)
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
input.updateCamera(MinecraftClient.getInstance());
}
}, delay, period);
} }
/** /**
@@ -154,18 +156,20 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
} }
this.hud.setVisible(MidnightControlsConfig.hudEnable); this.hud.setVisible(MidnightControlsConfig.hudEnable);
Controller.updateMappings(); Controller.updateMappings();
try {
GLFW.glfwSetJoystickCallback((jid, event) -> { GLFW.glfwSetJoystickCallback((jid, event) -> {
if (event == GLFW.GLFW_CONNECTED) { if (event == GLFW.GLFW_CONNECTED) {
var controller = Controller.byId(jid); var controller = Controller.byId(jid);
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, Text.translatable("midnightcontrols.controller.connected", jid), client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.connected", jid),
Text.literal(controller.getName()))); Text.literal(controller.getName())));
} else if (event == GLFW.GLFW_DISCONNECTED) { } else if (event == GLFW.GLFW_DISCONNECTED) {
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, Text.translatable("midnightcontrols.controller.disconnected", jid), client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.disconnected", jid),
null)); null));
} }
this.switchControlsMode(); this.switchControlsMode();
}); });
} catch (Exception e) {e.fillInStackTrace();}
MidnightControlsCompat.init(this); MidnightControlsCompat.init(this);
} }
@@ -174,16 +178,13 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
* This method is called to initialize keybindings * This method is called to initialize keybindings
*/ */
public void initKeybindings() { public void initKeybindings() {
if (!voxelmapInitDone && FabricLoader.getInstance().isModLoaded("voxelmap") && KeyBindingIDAccessor.getKEYS_BY_ID().containsKey("key.minimap.toggleingamewaypoints")) {
this.log("Adding VoxelMap compatibility...");
new VoxelMapCompat().handle(this);
InputManager.loadButtonBindings();
voxelmapInitDone = true;
}
if (lateInitDone) return; if (lateInitDone) return;
if (KeyBindingRegistryImplAccessor.getMODDED_KEY_BINDINGS() == null || KeyBindingRegistryImplAccessor.getMODDED_KEY_BINDINGS().isEmpty()) return; if (KeyBindingIDAccessor.getKEYS_BY_ID() == null || KeyBindingIDAccessor.getKEYS_BY_ID().isEmpty()) return;
for (int i = 0; i < KeyBindingRegistryImplAccessor.getMODDED_KEY_BINDINGS().size(); ++i) { if (PlatformFunctions.isModLoaded("voxelmap") && !KeyBindingIDAccessor.getKEYS_BY_ID().containsKey("key.minimap.toggleingamewaypoints")) return;
KeyBinding keyBinding = KeyBindingRegistryImplAccessor.getMODDED_KEY_BINDINGS().get(i); if (PlatformFunctions.isModLoaded("wynntils") && KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().noneMatch(b -> Objects.equals(b.getValue().getCategory(), "Wynntils"))) return;
for (int i = 0; i < KeyBindingIDAccessor.getKEYS_BY_ID().size(); ++i) {
KeyBinding keyBinding = KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().toList().get(i).getValue();
if (MidnightControlsConfig.excludedKeybindings.stream().noneMatch(excluded -> keyBinding.getTranslationKey().startsWith(excluded))) {
if (!keyBinding.getTranslationKey().contains("midnightcontrols") && !keyBinding.getTranslationKey().contains("ok_zoomer") && !keyBinding.getTranslationKey().contains("okzoomer")) { if (!keyBinding.getTranslationKey().contains("midnightcontrols") && !keyBinding.getTranslationKey().contains("ok_zoomer") && !keyBinding.getTranslationKey().contains("okzoomer")) {
category = null; category = null;
InputManager.streamCategories().forEach(buttonCategory -> { InputManager.streamCategories().forEach(buttonCategory -> {
@@ -201,6 +202,7 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
} }
} }
} }
}
InputManager.loadButtonBindings(); InputManager.loadButtonBindings();
lateInitDone = true; lateInitDone = true;
} }
@@ -227,9 +229,8 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
MidnightControlsConfig.enableHints = false; MidnightControlsConfig.enableHints = false;
MidnightControlsConfig.save(); MidnightControlsConfig.save();
} }
} RainbowColor.tick();
public void onRender(MinecraftClient client) { TouchInput.tick();
//this.input.onRender(client);
} }
/** /**

View File

@@ -18,8 +18,15 @@ import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.Controller;
import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import eu.midnightdust.midnightcontrols.client.enums.TouchMode;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -33,65 +40,87 @@ import static org.lwjgl.glfw.GLFW.*;
* Represents MidnightControls configuration. * Represents MidnightControls configuration.
*/ */
public class MidnightControlsConfig extends MidnightConfig { public class MidnightControlsConfig extends MidnightConfig {
public static final String CONTROLLER = "controller";
public static final String TOUCH = "touch";
public static final String GAMEPLAY = "gameplay";
public static final String SCREENS = "screens";
public static final String VISUAL = "visual";
public static final String MISC = "misc";
public static boolean isEditing = false; public static boolean isEditing = false;
@Hidden @Entry public static int configVersion = 2; @Hidden @Entry public static int configVersion = 2;
// General // General
@Entry(category = "controller", name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT;
@Entry(category = "controller", name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true;
@Entry(category = "misc", name = "Debug") public static boolean debug = false; @Entry(category = MISC, name = "Debug") public static boolean debug = false;
// HUD // HUD
@Entry(category = "visual", name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true; @Entry(category = VISUAL, name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true;
@Entry(category = "visual", name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT; @Entry(category = VISUAL, name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT;
@Entry(category = "screens", name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false; @Entry(category = SCREENS, name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false;
// Gameplay // Gameplay
@Entry(category = "gameplay", name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true; @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true;
@Entry(category = "gameplay", name = "midnightcontrols.menu.double_tap_to_sprint") public static boolean doubleTapToSprint = true; @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.double_tap_to_sprint") public static boolean doubleTapToSprint = true;
@Entry(category = "gameplay", name = "midnightcontrols.menu.controller_toggle_sneak") public static boolean controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue(); @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.controller_toggle_sneak") public static boolean controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue();
@Entry(category = "gameplay", name = "midnightcontrols.menu.controller_toggle_sprint") public static boolean controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue(); @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.controller_toggle_sprint") public static boolean controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue();
@Entry(category = "gameplay", name = "midnightcontrols.menu.fast_block_placing") public static boolean fastBlockPlacing = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fast_block_placing") public static boolean fastBlockPlacing = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = "gameplay", name = "midnightcontrols.menu.fly_drifting") public static boolean flyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. It can also conflict with some other mods. @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fly_drifting") public static boolean flyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. It can also conflict with some other mods.
@Entry(category = "gameplay", name = "midnightcontrols.menu.fly_drifting_vertical") public static boolean verticalFlyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fly_drifting_vertical") public static boolean verticalFlyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers.
@Entry(category = "gameplay", name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = "gameplay", name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = "visual", name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true; @Entry(category = VISUAL, name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true;
@Entry(category = "visual", name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff"; @Entry(category = VISUAL, name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff";
@Entry(category = "visual", name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102; @Entry(category = VISUAL, name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102;
@Entry(category = "controller", name = "midnightcontrols.menu.right_dead_zone", isSlider = true, min = 0.05, max = 1) public static double rightDeadZone = 0.25; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.right_dead_zone", isSlider = true, min = 0.05, max = 1) public static double rightDeadZone = 0.25;
@Entry(category = "controller", name = "midnightcontrols.menu.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.25; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.25;
@Entry(category = "controller", name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false;
@Entry(category = "controller", name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false;
@Entry(category = "controller", name = "midnightcontrols.menu.rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double rotationSpeed = 40.0; //used for x-axis, name kept for compatibility @Entry(category = CONTROLLER, name = "midnightcontrols.menu.rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double rotationSpeed = 35.0; //used for x-axis, name kept for compatibility
@Entry(category = "controller", name = "midnightcontrols.menu.y_axis_rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double yAxisRotationSpeed = rotationSpeed; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.y_axis_rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double yAxisRotationSpeed = rotationSpeed;
@Entry(category = "screens", name = "midnightcontrols.menu.mouse_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double mouseSpeed = 25.0; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.camera_mode") public static CameraMode cameraMode = CameraMode.FLAT;
@Entry(category = "screens", name = "midnightcontrols.menu.joystick_as_mouse") public static boolean joystickAsMouse = false; @Entry(category = SCREENS, name = "midnightcontrols.menu.mouse_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double mouseSpeed = 25.0;
@Entry(category = "screens", name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false; @Entry(category = SCREENS, name = "midnightcontrols.menu.joystick_as_mouse") public static boolean joystickAsMouse = false;
@Entry(category = "screens", name = "midnightcontrols.menu.eye_tracker_deadzone", isSlider = true, min = 0, max = 0.4) public static double eyeTrackerDeadzone = 0.05; @Entry(category = SCREENS, name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false;
@Entry(category = "controller", name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false; @Entry(category = SCREENS, name = "midnightcontrols.menu.eye_tracker_deadzone", isSlider = true, min = 0, max = 0.4) public static double eyeTrackerDeadzone = 0.05;
@Entry(category = "screens", name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false; @Entry(category = CONTROLLER, name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false;
@Entry(category = "screens", name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT; @Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false;
@Entry(category = "screens", name = "midnightcontrols.menu.hide_cursor") public static boolean hideNormalMouse = false; @Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
@Entry(category = "controller", name = "Controller ID") @Hidden public static Object controllerID = 0; @Entry(category = SCREENS, name = "midnightcontrols.menu.hide_cursor") public static boolean hideNormalMouse = false;
@Entry(category = "controller", name = "2nd Controller ID") @Hidden public static Object secondControllerID = -1; @Entry(category = CONTROLLER, name = "Controller ID") @Hidden public static Object controllerID = 0;
@Entry(category = "visual", name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT; @Entry(category = CONTROLLER, name = "2nd Controller ID") @Hidden public static Object secondControllerID = -1;
@Entry(category = "screens", name = "Mouse screens") public static List<String> mouseScreens = Lists.newArrayList("net.minecraft.client.gui.screen.advancement", @Entry(category = VISUAL, name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT;
@Entry(category = SCREENS, name = "Mouse screens") public static List<String> mouseScreens = Lists.newArrayList("net.minecraft.client.gui.screen.advancement",
"net.minecraft.class_457", "net.minecraft.class_408", "net.minecraft.class_3872", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen", "net.minecraft.class_457", "net.minecraft.class_408", "net.minecraft.class_3872", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen",
"hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen", "hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen",
"me.shedaniel.clothconfig2.gui.ClothConfigScreen", "com.mamiyaotaru.voxelmap.gui.GuiWaypoints", "com.mamiyaotaru.voxelmap.gui.GuiPersistentMap"); "me.shedaniel.clothconfig2.gui.ClothConfigScreen", "com.mamiyaotaru.voxelmap.gui.GuiWaypoints", "com.mamiyaotaru.voxelmap.gui.GuiPersistentMap");
@Entry(category = "screens", name = "Arrow screens") public static List<String> arrowScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName()); @Entry(category = SCREENS, name = "Arrow screens") public static List<String> arrowScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName());
@Entry(category = "screens", name = "WASD screens") public static List<String> wasdScreens = Lists.newArrayList("com.ultreon.devices.core.Laptop"); @Entry(category = SCREENS, name = "WASD screens") public static List<String> wasdScreens = Lists.newArrayList("com.ultreon.devices.core.Laptop");
@Entry(category = TOUCH, name = "Screens with close button") public static List<String> closeButtonScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName(), AdvancementsScreen.class.getCanonicalName(), RingScreen.class.getCanonicalName());
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_with_controller") public static boolean touchInControllerMode = false;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double touchSpeed = 50.0;
@Entry(category = TOUCH, name = "midnightcontrols.menu.invert_touch") public static boolean invertTouch = false;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_mode") public static TouchMode touchMode = TouchMode.CROSSHAIR;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_break_delay", isSlider = true, min = 50, max = 500) public static int touchBreakDelay = 120;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_transparency", isSlider = true, min = 0, max = 100) public static int touchTransparency = 75;
@Entry(category = TOUCH, name = "Touch Outline Color", isColor = true) public static String touchOutlineColorHex = "#ffffff";
@Entry(category = TOUCH, name = "Touch Outline Alpha", isSlider = true, min = 0, max = 255) public static int touchOutlineColorAlpha = 150;
@Entry(category = TOUCH, name = "Left Touch button bindings") public static List<String> leftTouchBinds = Lists.newArrayList("debug_screen", "screenshot","toggle_perspective");
@Entry(category = TOUCH, name = "Right Touch button bindings") public static List<String> rightTouchBinds = Lists.newArrayList("screenshot","toggle_perspective", "use");
@Entry @Hidden public static Map<String, String> BINDING = new HashMap<>(); @Entry @Hidden public static Map<String, String> BINDING = new HashMap<>();
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?"); private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
@Deprecated @Hidden @Entry public static double[] maxAnalogValues = new double[]{1, 1, 1, 1}; @Deprecated @Hidden @Entry public static double[] maxAnalogValues = new double[]{1, 1, 1, 1};
@Entry(category = "controller", name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = maxAnalogValues[0]; @Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = maxAnalogValues[0];
@Entry(category = "controller", name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = maxAnalogValues[1]; @Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = maxAnalogValues[1];
@Entry(category = "controller", name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = maxAnalogValues[2]; @Entry(category = CONTROLLER, name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = maxAnalogValues[2];
@Entry(category = "controller", name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = maxAnalogValues[3]; @Entry(category = CONTROLLER, name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = maxAnalogValues[3];
@Entry(category = "controller", name = "Trigger button fix") public static boolean triggerFix = true; @Entry(category = CONTROLLER, name = "Trigger button fix") public static boolean triggerFix = true;
@Entry(category = "gameplay", name = "Enable Hints") public static boolean enableHints = true; @Entry(category = MISC, name = "Excluded Keybindings") public static List<String> excludedKeybindings = Lists.newArrayList("key.forward", "key.left", "key.back", "key.right", "key.jump", "key.sneak", "key.sprint", "key.inventory",
@Entry(category = "screens", name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true; "key.swapOffhand", "key.drop", "key.use", "key.attack", "key.chat", "key.playerlist", "key.screenshot", "key.togglePerspective", "key.smoothCamera", "key.fullscreen", "key.saveToolbarActivator", "key.loadToolbarActivator",
@Entry(category = "misc", name = "Ring Bindings (WIP)") public static List<String> ringBindings = new ArrayList<>(); "key.pickItem", "key.hotbar.1", "key.hotbar.2", "key.hotbar.3", "key.hotbar.4", "key.hotbar.5", "key.hotbar.6", "key.hotbar.7", "key.hotbar.8", "key.hotbar.9");
@Entry(category = "misc", name = "Ignored Unbound Keys") public static List<String> ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab"); @Entry(category = GAMEPLAY, name = "Enable Hints") public static boolean enableHints = true;
@Entry(category = SCREENS, name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true;
@Entry(category = MISC, name = "Ring Bindings (WIP)") public static List<String> ringBindings = new ArrayList<>();
@Entry(category = MISC, name = "Ignored Unbound Keys") public static List<String> ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab");
@Entry @Hidden public static Map<String, Map<String, String>> controllerBindingProfiles = new HashMap<>(); @Entry @Hidden public static Map<String, Map<String, String>> controllerBindingProfiles = new HashMap<>();
private static Map<String, String> currentBindingProfile = new HashMap<>(); private static Map<String, String> currentBindingProfile = new HashMap<>();
private static Controller prevController; private static Controller prevController;
@@ -375,4 +404,7 @@ public class MidnightControlsConfig extends MidnightConfig {
else if (controller.contains("ouya")) return ControllerType.OUYA; else if (controller.contains("ouya")) return ControllerType.OUYA;
else return ControllerType.DEFAULT; else return ControllerType.DEFAULT;
} }
public static boolean doMixedInput() {
return touchInControllerMode && controlsMode == ControlsMode.CONTROLLER;
}
} }

View File

@@ -17,12 +17,14 @@ import eu.midnightdust.midnightcontrols.client.compat.*;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.Controller;
import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget; import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
import eu.midnightdust.midnightcontrols.client.mixin.*; import eu.midnightdust.midnightcontrols.client.mixin.*;
import eu.midnightdust.midnightcontrols.client.ring.RingPage; import eu.midnightdust.midnightcontrols.client.ring.RingPage;
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
import dev.lambdaurora.spruceui.navigation.NavigationDirection; import dev.lambdaurora.spruceui.navigation.NavigationDirection;
import dev.lambdaurora.spruceui.screen.SpruceScreen; import dev.lambdaurora.spruceui.screen.SpruceScreen;
@@ -30,12 +32,12 @@ import dev.lambdaurora.spruceui.widget.AbstractSprucePressableButtonWidget;
import dev.lambdaurora.spruceui.widget.SpruceElement; import dev.lambdaurora.spruceui.widget.SpruceElement;
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget; import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget; import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.ParentElement; import net.minecraft.client.gui.ParentElement;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.TitleScreen;
import net.minecraft.client.gui.screen.advancement.AdvancementTab; import net.minecraft.client.gui.screen.advancement.AdvancementTab;
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
@@ -46,8 +48,6 @@ import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget; import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
import net.minecraft.client.gui.screen.world.WorldListWidget; import net.minecraft.client.gui.screen.world.WorldListWidget;
import net.minecraft.client.gui.widget.*; import net.minecraft.client.gui.widget.*;
import net.minecraft.client.input.Input;
import net.minecraft.client.util.InputUtil;
import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.Slot;
import net.minecraft.text.TranslatableTextContent; import net.minecraft.text.TranslatableTextContent;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@@ -151,8 +151,13 @@ public class MidnightInput {
if (allowInput) if (allowInput)
InputManager.updateBindings(client); InputManager.updateBindings(client);
if (this.controlsInput != null if (this.controlsInput != null) {
&& InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) { InputManager.STATES.forEach((num, button) -> {
if (button.isPressed()) System.out.println(num);
});
}
if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
System.out.println("finished");
if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) { if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) {
int[] buttons = new int[this.controlsInput.currentButtons.size()]; int[] buttons = new int[this.controlsInput.currentButtons.size()];
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++) for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
@@ -203,18 +208,8 @@ public class MidnightInput {
} }
client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw); client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw);
MidnightControlsCompat.HANDLERS.forEach(handler -> handler.handleCamera(client, targetYaw, targetPitch)); MidnightControlsCompat.HANDLERS.forEach(handler -> handler.handleCamera(client, targetYaw, targetPitch));
this.onRender(client);
} }
} }
/**
* This method is deprecated and will be removed in future versions
* It is just kept, because the current version of 'Do a Barrel Roll' mixins into this method
*
* @param client the client instance
*/
@Deprecated
public void onRender(@NotNull MinecraftClient client) {
}
/** /**
* This method is called when a Screen is opened. * This method is called when a Screen is opened.
@@ -266,12 +261,33 @@ public class MidnightInput {
InputManager.STATES.put(btn, state); InputManager.STATES.put(btn, state);
} }
} }
MathUtil.PolarUtil polarLeft = new MathUtil.PolarUtil();
MathUtil.PolarUtil polarRight = new MathUtil.PolarUtil();
private void fetchAxeInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) { private void fetchAxeInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) {
var buffer = gamepadState.axes(); var buffer = gamepadState.axes();
polarLeft.calculate(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X), buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y), 1, MidnightControlsConfig.leftDeadZone);
float leftX = polarLeft.polarX;
float leftY = polarLeft.polarY;
polarRight.calculate(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X), buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y), 1, MidnightControlsConfig.rightDeadZone);
float rightX = polarRight.polarX;
float rightY = polarRight.polarY;
for (int i = 0; i < buffer.limit(); i++) { for (int i = 0; i < buffer.limit(); i++) {
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i; int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
float value = buffer.get(); float value = buffer.get();
if (MidnightControlsConfig.analogMovement) {
switch (i) {
case GLFW_GAMEPAD_AXIS_LEFT_X -> value = leftX;
case GLFW_GAMEPAD_AXIS_LEFT_Y -> value = leftY;
}
}
switch (i) {
case GLFW_GAMEPAD_AXIS_RIGHT_X -> value = rightX;
case GLFW_GAMEPAD_AXIS_RIGHT_Y -> value = rightY;
}
float absValue = Math.abs(value); float absValue = Math.abs(value);
if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y) if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y)
@@ -281,24 +297,26 @@ public class MidnightInput {
if (!(client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)))) this.handleAxe(client, axis, value, absValue, state); if (!(client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)))) this.handleAxe(client, axis, value, absValue, state);
} }
if (client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen))) { if (client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen))) {
float x = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X)) > MidnightControlsConfig.leftDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X) : 0; float x = leftX;
float y = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y)) > MidnightControlsConfig.leftDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y) : 0; float y = leftY;
if (x == 0 && y == 0) { if (x == 0 && y == 0) {
x = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X)) > MidnightControlsConfig.rightDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X) : 0; x = rightX;
y = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y)) > MidnightControlsConfig.rightDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y) : 0; y = rightY;
} }
int index = -1; int index = -1;
if (x < 0) { float border = 0.3f;
if (y < 0) index = 0; if (x < -border) {
if (y == 0) index = 3; index = 3;
if (y > 0) index = 5; if (y < -border) index = 0;
} else if (x == 0) { else if (y > border) index = 5;
if (y < 0) index = 1; } else if (x > border) {
if (y > 0) index = 6; index = 4;
} else if (x > 0) { if (y < -border) index = 2;
if (y < 0) index = 2; else if (y > border) index = 7;
if (y == 0) index = 4; } else {
if (y > 0) index = 7; if (y < -border) index = 1;
else if (y > border) index = 6;
} }
if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index; if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index;
if (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index); if (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index);
@@ -458,7 +476,6 @@ public class MidnightInput {
private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) { private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) {
int asButtonState = value > .5f ? 1 : (value < -.5f ? 2 : 0); int asButtonState = value > .5f ? 1 : (value < -.5f ? 2 : 0);
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER)
|| axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) { || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) {
@@ -478,8 +495,13 @@ public class MidnightInput {
} }
{ {
boolean currentPlusState = asButtonState == 1; boolean currentPlusState = value > getDeadZoneValue(axis);
boolean currentMinusState = asButtonState == 2; boolean currentMinusState = value < -getDeadZoneValue(axis);
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER) currentMinusState = false;
if (!MidnightControlsConfig.analogMovement && (axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y)) {
currentPlusState = asButtonState == 1;
currentMinusState = asButtonState == 2;
}
var previousPlusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, true), ButtonState.NONE); var previousPlusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, true), ButtonState.NONE);
var previousMinusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, false), ButtonState.NONE); var previousMinusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, false), ButtonState.NONE);
@@ -505,9 +527,13 @@ public class MidnightInput {
} }
} }
float axisValue = absValue;
if (!MidnightControlsConfig.analogMovement) {
double deadZone = this.getDeadZoneValue(axis); double deadZone = this.getDeadZoneValue(axis);
float axisValue = absValue < deadZone ? 0.f : (float) (absValue - deadZone); axisValue = (float) (absValue - deadZone);
axisValue /= (1.0 - deadZone); axisValue /= (1.0 - deadZone);
axisValue *= deadZone;
}
axisValue = (float) Math.min(axisValue / MidnightControlsConfig.getAxisMaxValue(axis), 1); axisValue = (float) Math.min(axisValue / MidnightControlsConfig.getAxisMaxValue(axis), 1);
if (currentPlusState) if (currentPlusState)
@@ -540,7 +566,7 @@ public class MidnightInput {
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen; var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
// @TODO allow rebinding to left stick // @TODO allow rebinding to left stick
if (accessor.midnightcontrols$hasScrollbar() && absValue >= deadZone) { if (accessor.midnightcontrols$hasScrollbar() && absValue >= deadZone) {
creativeInventoryScreen.mouseScrolled(0.0, 0.0, -value); creativeInventoryScreen.mouseScrolled(0.0, 0.0, 0, -value);
} }
return; return;
} }
@@ -548,7 +574,7 @@ public class MidnightInput {
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
// @TODO allow rebinding to left stick // @TODO allow rebinding to left stick
if (absValue >= deadZone) { if (absValue >= deadZone) {
merchantScreen.mouseScrolled(0.0, 0.0, -(value * 1.5f)); merchantScreen.mouseScrolled(0.0, 0.0, 0, -(value * 1.5f));
} }
return; return;
} }
@@ -556,7 +582,7 @@ public class MidnightInput {
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
// @TODO allow rebinding to left stick // @TODO allow rebinding to left stick
if (absValue >= deadZone) { if (absValue >= deadZone) {
stonecutterScreen.mouseScrolled(0.0, 0.0, -(value * 1.5f)); stonecutterScreen.mouseScrolled(0.0, 0.0, 0, -(value * 1.5f));
} }
return; return;
} }
@@ -575,7 +601,7 @@ public class MidnightInput {
.map(element -> (SpruceEntryListWidget<?>) element) .map(element -> (SpruceEntryListWidget<?>) element)
.filter(AbstractSpruceWidget::isFocusedOrHovered) .filter(AbstractSpruceWidget::isFocusedOrHovered)
.noneMatch(element -> { .noneMatch(element -> {
element.mouseScrolled(0.0, 0.0, -finalValue); element.mouseScrolled(0.0, 0.0, 0, -finalValue);
return true; return true;
}) })
&& &&
@@ -583,11 +609,11 @@ public class MidnightInput {
.map(element -> (EntryListWidget<?>) element) .map(element -> (EntryListWidget<?>) element)
.filter(element -> element.getType().isFocused()) .filter(element -> element.getType().isFocused())
.noneMatch(element -> { .noneMatch(element -> {
element.mouseScrolled(0.0, 0.0, -finalValue); element.mouseScrolled(0.0, 0.0, 0, -finalValue);
return true; return true;
})) }))
{ {
client.currentScreen.mouseScrolled(0.0, 0.0, -(value * 1.5f)); client.currentScreen.mouseScrolled(0.0, 0.0, 0, -(value * 1.5f));
} }
else if (isScreenInteractive(client.currentScreen) && absValue >= deadZone) { else if (isScreenInteractive(client.currentScreen) && absValue >= deadZone) {
if (value > 0 && joystickCooldown == 0) { if (value > 0 && joystickCooldown == 0) {
@@ -607,8 +633,6 @@ public class MidnightInput {
} }
} }
absValue -= deadZone;
absValue /= (1.0 - deadZone);
absValue = (float) MathHelper.clamp(absValue / MidnightControlsConfig.getAxisMaxValue(axis), 0.f, 1.f); absValue = (float) MathHelper.clamp(absValue / MidnightControlsConfig.getAxisMaxValue(axis), 0.f, 1.f);
if (client.currentScreen == null) { if (client.currentScreen == null) {
// Handles the look direction. // Handles the look direction.
@@ -756,6 +780,10 @@ public class MidnightInput {
} }
return true; return true;
} }
private double prevX = 0;
private double prevY = 0;
private double xValue;
private int xState;
/** /**
* Handles the look direction input. * Handles the look direction input.
@@ -766,8 +794,9 @@ public class MidnightInput {
* @param state the state * @param state the state
*/ */
public void handleLook(@NotNull MinecraftClient client, int axis, float value, int state) { public void handleLook(@NotNull MinecraftClient client, int axis, float value, int state) {
if (client.player == null) return;
// Handles the look direction. // Handles the look direction.
if (client.player != null) { if (MidnightControlsConfig.cameraMode == CameraMode.FLAT) {
double powValue = Math.pow(value, 2.0); double powValue = Math.pow(value, 2.0);
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
if (state == 2) { if (state == 2) {
@@ -783,6 +812,43 @@ public class MidnightInput {
this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D; this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
} }
} }
return;
}
// Code below runs for adaptive camera mode
// Handles the look direction.
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
xValue = value;
xState = state;
return;
}
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y && client.player != null) {
double yStep = (MidnightControlsConfig.yAxisRotationSpeed / 100) * 0.6000000238418579 + 0.20000000298023224;
double xStep = (MidnightControlsConfig.rotationSpeed / 100) * 0.6000000238418579 + 0.20000000298023224;
double cursorDeltaX = 2 * xValue - this.prevX;
double cursorDeltaY = 2 * value - this.prevY;
boolean slowdown = client.options.getPerspective().isFirstPerson() && client.player.isUsingSpyglass();
double x = cursorDeltaX * xStep * (slowdown ? xStep : 1);
double y = cursorDeltaY * yStep * (slowdown ? yStep : 1);
double powXValue = Math.pow(x, 2.0);
double powYValue = Math.pow(y, 2.0);
if (state == 2) {
this.targetPitch = -MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powYValue) * 0.11D;
} else if (state == 1) {
this.targetPitch = MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powYValue) * 0.11D;
}
if (xState == 2) {
this.targetYaw = -MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powXValue) * 0.11D;
} else if (xState == 1) {
this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powXValue) * 0.11D;
}
this.prevY = value;
this.prevX = xValue;
} }
} }

View File

@@ -73,7 +73,7 @@ public class MidnightReacharound {
return MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable(); return MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable();
} }
private float getPlayerRange(@NotNull MinecraftClient client) { public static float getPlayerRange(@NotNull MinecraftClient client) {
return client.interactionManager != null ? client.interactionManager.getReachDistance() : 0.f; return client.interactionManager != null ? client.interactionManager.getReachDistance() : 0.f;
} }

View File

@@ -1,16 +1,21 @@
package eu.midnightdust.midnightcontrols.client.compat; package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import io.github.kosmx.emotes.arch.gui.EmoteMenuImpl;
import io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen; import io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
public class EmotecraftCompat { public class EmotecraftCompat {
private static final MinecraftClient client = MinecraftClient.getInstance();
public static void openEmotecraftScreen(Screen parent) {
client.setScreen(new EmoteMenuImpl(parent));
}
public static boolean isEmotecraftScreen(Screen screen) { public static boolean isEmotecraftScreen(Screen screen) {
return screen instanceof FastChosseScreen; return screen instanceof FastChosseScreen;
} }
public static void handleEmoteSelector(int index) { public static void handleEmoteSelector(int index) {
MinecraftClient client = MinecraftClient.getInstance();
if (client.currentScreen instanceof FastChosseScreen) { if (client.currentScreen instanceof FastChosseScreen) {
int x = client.getWindow().getWidth() / 2; int x = client.getWindow().getWidth() / 2;
int y = client.getWindow().getHeight() / 2; int y = client.getWindow().getHeight() / 2;

View File

@@ -1,35 +1,12 @@
package eu.midnightdust.midnightcontrols.client.compat; package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.MidnightControls; import eu.midnightdust.midnightcontrols.MidnightControls;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.compat.mixin.SodiumOptionsGUIAccessor; import eu.midnightdust.midnightcontrols.client.compat.mixin.SodiumOptionsGUIAccessor;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI; import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
public class SodiumCompat { public class SodiumCompat {
private static final MinecraftClient client = MinecraftClient.getInstance();
public static void handleInput(Screen screen, boolean direction) {
if (screen instanceof SodiumOptionsGUI optionsGUI) {
SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI;
final int max = accessor.getControls().size()-1;
var option = accessor.getControls().stream().filter(ControlElement::isHovered).findFirst().orElse(accessor.getControls().get(0));
int i = accessor.getControls().indexOf(option);
i = (direction ? ((max > i) ? ++i : 0) : (i > 0 ? --i : max));
var dimensions = accessor.getControls().get(i).getDimensions();
int x = (int) (client.getWindow().getScaleFactor() * dimensions.getCenterX());
int y = (int) (client.getWindow().getScaleFactor() * dimensions.getCenterY());
InputManager.queueMousePosition(x,y);
InputManager.INPUT_MANAGER.updateMousePosition(client);
MidnightControlsClient.get().input.actionGuiCooldown = 5;
if (MidnightControlsConfig.debug) MidnightControls.get().log(i+" "+accessor.getControls().size()+" | " + dimensions.getCenterX() + " " + dimensions.getCenterY());
}
}
public static void handleTabs(Screen screen, boolean direction) { public static void handleTabs(Screen screen, boolean direction) {
if (screen instanceof SodiumOptionsGUI optionsGUI) { if (screen instanceof SodiumOptionsGUI optionsGUI) {
SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI; SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI;

View File

@@ -1,95 +0,0 @@
/*
* Copyright © 2022 Motschen <motschen@midnightdust.eu>
*
* This file is part of MidnightControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
import net.minecraft.client.option.KeyBinding;
import org.aperlambda.lambdacommon.Identifier;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
/**
* Represents a compatibility handler for VoxelMap.
*
* @author Motschen
* @version 1.8.0
* @since 1.8.0
*/
public class VoxelMapCompat implements CompatHandler {
private final KeyBinding voxelMapZoomKey = KeyBindingIDAccessor.getKEYS_BY_ID().getOrDefault("key.minimap.zoom", null);
private final KeyBinding voxelmapFullscreenKey = KeyBindingIDAccessor.getKEYS_BY_ID().getOrDefault("key.minimap.togglefullscreen", null);
private final KeyBinding voxelmapMenuKey = KeyBindingIDAccessor.getKEYS_BY_ID().getOrDefault("key.minimap.voxelmapmenu", null);;
private final KeyBinding voxelmapWaypointMenuKey = KeyBindingIDAccessor.getKEYS_BY_ID().getOrDefault("key.minimap.waypointmenu", null);;
private final KeyBinding voxelmapWaypointKey = KeyBindingIDAccessor.getKEYS_BY_ID().getOrDefault("key.minimap.waypointhotkey", null);
private final KeyBinding voxelmapMobToggleKey = KeyBindingIDAccessor.getKEYS_BY_ID().getOrDefault("key.minimap.togglemobs", null);
private final KeyBinding voxelmapWaypointToggleKey = KeyBindingIDAccessor.getKEYS_BY_ID().getOrDefault("key.minimap.toggleingamewaypoints", null);
private static final ButtonCategory VOXELMAP_CATEGORY = InputManager.registerCategory(new Identifier("minecraft","controls.minimap.title"));
@Override
public void handle(@NotNull MidnightControlsClient mod) {
if (MidnightControlsConfig.debug && KeyBindingIDAccessor.getKEYS_BY_ID() != null) KeyBindingIDAccessor.getKEYS_BY_ID().forEach((a, b) -> System.out.println(a + " - " + b));
new ButtonBinding.Builder("key.minimap.zoom")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, GLFW.GLFW_GAMEPAD_BUTTON_X)
.onlyInGame()
.cooldown(true)
.category(VOXELMAP_CATEGORY)
.linkKeybind(voxelMapZoomKey)
.register();
new ButtonBinding.Builder("key.minimap.togglefullscreen")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, GLFW.GLFW_GAMEPAD_BUTTON_Y)
.onlyInGame()
.cooldown(true)
.category(VOXELMAP_CATEGORY)
.linkKeybind(voxelmapFullscreenKey)
.register();
new ButtonBinding.Builder("key.minimap.voxelmapmenu")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, GLFW.GLFW_GAMEPAD_BUTTON_START)
.onlyInGame()
.cooldown(true)
.category(VOXELMAP_CATEGORY)
.linkKeybind(voxelmapMenuKey)
.register();
new ButtonBinding.Builder("key.minimap.waypointmenu")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, GLFW.GLFW_GAMEPAD_BUTTON_GUIDE)
.onlyInGame()
.cooldown(true)
.category(VOXELMAP_CATEGORY)
.linkKeybind(voxelmapWaypointMenuKey)
.register();
new ButtonBinding.Builder("key.minimap.waypointhotkey")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, GLFW.GLFW_GAMEPAD_BUTTON_BACK)
.onlyInGame()
.cooldown(true)
.category(VOXELMAP_CATEGORY)
.linkKeybind(voxelmapWaypointKey)
.register();
new ButtonBinding.Builder("key.minimap.togglemobs")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, GLFW.GLFW_GAMEPAD_BUTTON_A)
.onlyInGame()
.cooldown(true)
.category(VOXELMAP_CATEGORY)
.linkKeybind(voxelmapMobToggleKey)
.register();
new ButtonBinding.Builder("key.minimap.toggleingamewaypoints")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN, GLFW.GLFW_GAMEPAD_BUTTON_B)
.onlyInGame()
.cooldown(true)
.category(VOXELMAP_CATEGORY)
.linkKeybind(voxelmapWaypointToggleKey)
.register();
}
}

View File

@@ -9,7 +9,7 @@
package eu.midnightdust.midnightcontrols.client.controller; package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.client.ButtonState; import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@@ -75,9 +75,8 @@ public class ButtonBinding {
.action(MovementHandler.HANDLER).onlyInGame().register(); .action(MovementHandler.HANDLER).onlyInGame().register();
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A) public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
.action(InputHandlers::handleScreenshot).cooldown().register(); .action(InputHandlers::handleScreenshot).cooldown().register();
public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B) public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B)
.action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.options.debugEnabled = !client.options.debugEnabled; return true;}).cooldown().register(); .action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.inGameHud.getDebugHud().toggleDebugHud(); return true;}).cooldown().register();
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN) public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register(); .action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT) public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)

View File

@@ -32,6 +32,7 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import static org.lwjgl.BufferUtils.createByteBuffer; import static org.lwjgl.BufferUtils.createByteBuffer;
@@ -79,7 +80,7 @@ public record Controller(int id) implements Nameable {
* @return the controller's name * @return the controller's name
*/ */
@Override @Override
public String getName() { public @NotNull String getName() {
var name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id); var name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
return name == null ? String.valueOf(this.id()) : name; return name == null ? String.valueOf(this.id()) : name;
} }
@@ -145,6 +146,9 @@ public record Controller(int id) implements Nameable {
* Updates the controller mappings. * Updates the controller mappings.
*/ */
public static void updateMappings() { public static void updateMappings() {
CompletableFuture.supplyAsync(Controller::updateMappingsSync);
}
private static boolean updateMappingsSync() {
try { try {
MidnightControlsClient.get().log("Updating controller mappings..."); MidnightControlsClient.get().log("Updating controller mappings...");
File databaseFile = new File("config/gamecontrollerdatabase.txt"); File databaseFile = new File("config/gamecontrollerdatabase.txt");
@@ -161,7 +165,7 @@ public record Controller(int id) implements Nameable {
var database = ioResourceToBuffer(databaseFile.getPath(), 1024); var database = ioResourceToBuffer(databaseFile.getPath(), 1024);
if (database != null) GLFW.glfwUpdateGamepadMappings(database); if (database != null) GLFW.glfwUpdateGamepadMappings(database);
if (!MidnightControlsClient.MAPPINGS_FILE.exists()) if (!MidnightControlsClient.MAPPINGS_FILE.exists())
return; return false;
var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024); var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024);
if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer); if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer);
} catch (IOException e) { } catch (IOException e) {
@@ -176,7 +180,7 @@ public record Controller(int id) implements Nameable {
var string = l == 0L ? "" : MemoryUtil.memUTF8(l); var string = l == 0L ? "" : MemoryUtil.memUTF8(l);
var client = MinecraftClient.getInstance(); var client = MinecraftClient.getInstance();
if (client != null) { if (client != null) {
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT, client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string))); Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string)));
MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string); MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
} }
@@ -199,5 +203,6 @@ public record Controller(int id) implements Nameable {
controller.isGamepad())); controller.isGamepad()));
} }
} }
return true;
} }
} }

View File

@@ -10,7 +10,8 @@
package eu.midnightdust.midnightcontrols.client.controller; package eu.midnightdust.midnightcontrols.client.controller;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import eu.midnightdust.midnightcontrols.client.ButtonState; import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.MidnightInput; import eu.midnightdust.midnightcontrols.client.MidnightInput;
@@ -19,17 +20,16 @@ import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat; import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat;
import eu.midnightdust.midnightcontrols.client.compat.YACLCompat; import eu.midnightdust.midnightcontrols.client.compat.YACLCompat;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor;
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
import eu.midnightdust.midnightcontrols.client.mixin.RecipeBookWidgetAccessor; import eu.midnightdust.midnightcontrols.client.mixin.RecipeBookWidgetAccessor;
import eu.midnightdust.midnightcontrols.client.mixin.TabNavigationWidgetAccessor; import eu.midnightdust.midnightcontrols.client.mixin.TabNavigationWidgetAccessor;
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.fabricmc.fabric.impl.client.itemgroup.CreativeGuiExtensions; import net.fabricmc.fabric.impl.client.itemgroup.CreativeGuiExtensions;
import net.fabricmc.fabric.impl.client.itemgroup.FabricCreativeGuiComponents; import net.fabricmc.fabric.impl.client.itemgroup.FabricCreativeGuiComponents;
import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup; import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup;
import net.fabricmc.fabric.impl.itemgroup.ItemGroupEventsImpl;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.TitleScreen;
@@ -100,6 +100,7 @@ public class InputHandlers {
} else if (client.currentScreen instanceof RingScreen) { } else if (client.currentScreen instanceof RingScreen) {
MidnightControlsClient.get().ring.cyclePage(next); MidnightControlsClient.get().ring.cyclePage(next);
} else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) { } else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) {
if (PlatformFunctions.isModLoaded("connectormod")) return true;
ItemGroup currentTab = CreativeInventoryScreenAccessor.getSelectedTab(); ItemGroup currentTab = CreativeInventoryScreenAccessor.getSelectedTab();
int currentColumn = currentTab.getColumn(); int currentColumn = currentTab.getColumn();
ItemGroup.Row currentRow = currentTab.getRow(); ItemGroup.Row currentRow = currentTab.getRow();
@@ -160,7 +161,7 @@ public class InputHandlers {
nextTab = tabs.size() - 1; nextTab = tabs.size() - 1;
else if (nextTab >= tabs.size()) else if (nextTab >= tabs.size())
nextTab = 0; nextTab = 0;
screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot(), true); screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot().getAdvancementEntry(), true);
break; break;
} }
} }
@@ -190,6 +191,8 @@ public class InputHandlers {
} }
public static PressAction handlePage(boolean next) { public static PressAction handlePage(boolean next) {
return (client, button, value, action) -> { return (client, button, value, action) -> {
if (action == ButtonState.RELEASE)
return false;
if (client.currentScreen instanceof CreativeInventoryScreen) { if (client.currentScreen instanceof CreativeInventoryScreen) {
try { try {
return client.currentScreen.children().stream().filter(element -> element instanceof PressableWidget) return client.currentScreen.children().stream().filter(element -> element instanceof PressableWidget)
@@ -277,7 +280,7 @@ public class InputHandlers {
if (action == ButtonState.PRESS) { if (action == ButtonState.PRESS) {
// If in game, then pause the game. // If in game, then pause the game.
if (client.currentScreen == null || client.currentScreen instanceof RingScreen) if (client.currentScreen == null || client.currentScreen instanceof RingScreen)
client.openPauseMenu(false); client.openGameMenu(false);
else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it. else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it.
client.player.closeHandledScreen(); client.player.closeHandledScreen();
else // Else just close the current screen. else // Else just close the current screen.
@@ -418,7 +421,7 @@ public class InputHandlers {
* @return true if the client is in game, else false * @return true if the client is in game, else false
*/ */
public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) { public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) {
return (client.currentScreen == null && MidnightControlsClient.get().input.screenCloseCooldown <= 0) || client.currentScreen instanceof RingScreen; return (client.currentScreen == null && MidnightControlsClient.get().input.screenCloseCooldown <= 0) || client.currentScreen instanceof TouchscreenOverlay || client.currentScreen instanceof RingScreen;
} }
/** /**

View File

@@ -10,7 +10,7 @@
package eu.midnightdust.midnightcontrols.client.controller; package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.ButtonState; import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.ints.*;
@@ -27,7 +27,6 @@ import org.lwjgl.glfw.GLFW;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**

View File

@@ -9,20 +9,12 @@
package eu.midnightdust.midnightcontrols.client.controller; package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.client.ButtonState; import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.input.Input;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.tutorial.MovementTutorialStepHandler;
import net.minecraft.client.util.InputUtil;
import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.enchantment.SoulSpeedEnchantment;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtList;
import net.minecraft.nbt.scanner.SimpleNbtScanner;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -43,6 +35,7 @@ public final class MovementHandler implements PressAction {
private float slowdownFactor = 1.f; private float slowdownFactor = 1.f;
private float movementForward = 0.f; private float movementForward = 0.f;
private float movementSideways = 0.f; private float movementSideways = 0.f;
private MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil();
private MovementHandler() { private MovementHandler() {
} }
@@ -53,8 +46,6 @@ public final class MovementHandler implements PressAction {
* @param player The client player. * @param player The client player.
*/ */
public void applyMovement(@NotNull ClientPlayerEntity player) { public void applyMovement(@NotNull ClientPlayerEntity player) {
double movementR, movementTheta;
if (!this.shouldOverrideMovement) if (!this.shouldOverrideMovement)
return; return;
player.input.pressingForward = this.pressingForward; player.input.pressingForward = this.pressingForward;
@@ -62,12 +53,9 @@ public final class MovementHandler implements PressAction {
player.input.pressingLeft = this.pressingLeft; player.input.pressingLeft = this.pressingLeft;
player.input.pressingRight = this.pressingRight; player.input.pressingRight = this.pressingRight;
// Do an implicit square here polarUtil.calculate(this.movementSideways, this.movementForward, this.slowdownFactor);
movementR = this.slowdownFactor * (Math.pow(this.movementSideways, 2) + Math.pow(this.movementForward, 2)); player.input.movementForward = polarUtil.polarY;
movementR = MathHelper.clamp(movementR, 0.f, 1.f); player.input.movementSideways = polarUtil.polarX;
movementTheta = Math.atan2(this.movementForward, this.movementSideways);
player.input.movementForward = (float) (movementR * Math.sin(movementTheta));
player.input.movementSideways = (float) (movementR * Math.cos(movementTheta));
this.shouldOverrideMovement = false; this.shouldOverrideMovement = false;
} }

View File

@@ -9,7 +9,7 @@
package eu.midnightdust.midnightcontrols.client.controller; package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.client.ButtonState; import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor; import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.StickyKeyBinding; import net.minecraft.client.option.StickyKeyBinding;

View File

@@ -7,7 +7,7 @@
* see the LICENSE file. * see the LICENSE file.
*/ */
package eu.midnightdust.midnightcontrols.client; package eu.midnightdust.midnightcontrols.client.enums;
/** /**
* Represents a button state. * Represents a button state.

View File

@@ -0,0 +1,17 @@
package eu.midnightdust.midnightcontrols.client.enums;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
public enum CameraMode {
FLAT, ADAPTIVE;
public Text getTranslatedText() {
return Text.translatable("midnightcontrols.midnightconfig.enum."+this.getClass().getSimpleName()+"."+this.name());
}
public @NotNull CameraMode next() {
var v = values();
if (v.length == this.ordinal() + 1)
return v[0];
return v[this.ordinal() + 1];
}
}

View File

@@ -7,7 +7,7 @@
* see the LICENSE file. * see the LICENSE file.
*/ */
package eu.midnightdust.midnightcontrols.client; package eu.midnightdust.midnightcontrols.client.enums;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.aperlambda.lambdacommon.utils.Nameable; import org.aperlambda.lambdacommon.utils.Nameable;

View File

@@ -7,7 +7,7 @@
* see the LICENSE file. * see the LICENSE file.
*/ */
package eu.midnightdust.midnightcontrols.client; package eu.midnightdust.midnightcontrols.client.enums;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.aperlambda.lambdacommon.utils.Nameable; import org.aperlambda.lambdacommon.utils.Nameable;

View File

@@ -0,0 +1,17 @@
package eu.midnightdust.midnightcontrols.client.enums;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
public enum TouchMode {
CROSSHAIR, FINGER_POS;
public Text getTranslatedText() {
return Text.translatable("midnightcontrols.midnightconfig.enum."+this.getClass().getSimpleName()+"."+this.name());
}
public @NotNull TouchMode next() {
var v = values();
if (v.length == this.ordinal() + 1)
return v[0];
return v[this.ordinal() + 1];
}
}

View File

@@ -7,7 +7,7 @@
* see the LICENSE file. * see the LICENSE file.
*/ */
package eu.midnightdust.midnightcontrols.client; package eu.midnightdust.midnightcontrols.client.enums;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.aperlambda.lambdacommon.utils.Nameable; import org.aperlambda.lambdacommon.utils.Nameable;

View File

@@ -63,7 +63,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
fw.close(); fw.close();
} catch (IOException e) { } catch (IOException e) {
if (this.client != null) if (this.client != null)
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.TUTORIAL_HINT, this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.PERIODIC_NOTIFICATION,
Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty())); Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty()));
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -11,7 +11,7 @@ package eu.midnightdust.midnightcontrols.client.gui;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants; import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.client.HudSide; import eu.midnightdust.midnightcontrols.client.enums.HudSide;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
@@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable;
*/ */
public class MidnightControlsHud extends Hud { public class MidnightControlsHud extends Hud {
private final MidnightControlsClient mod; private final MidnightControlsClient mod;
private MinecraftClient client; private final MinecraftClient client = MinecraftClient.getInstance();
private int attackWidth = 0; private int attackWidth = 0;
private int attackButtonWidth = 0; private int attackButtonWidth = 0;
private int dropItemWidth = 0; private int dropItemWidth = 0;
@@ -64,7 +64,6 @@ public class MidnightControlsHud extends Hud {
@Override @Override
public void init(@NotNull MinecraftClient client, int screenWidth, int screenHeight) { public void init(@NotNull MinecraftClient client, int screenWidth, int screenHeight) {
super.init(client, screenWidth, screenHeight); super.init(client, screenWidth, screenHeight);
this.client = client;
this.inventoryWidth = this.width(ButtonBinding.INVENTORY); this.inventoryWidth = this.width(ButtonBinding.INVENTORY);
this.inventoryButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY); this.inventoryButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY);
this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS); this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS);
@@ -198,6 +197,7 @@ public class MidnightControlsHud extends Hud {
@Override @Override
public void tick() { public void tick() {
if (this.client == null) return;
super.tick(); super.tick();
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) { if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) {
if (this.client.crosshairTarget == null) if (this.client.crosshairTarget == null)

View File

@@ -10,7 +10,7 @@
package eu.midnightdust.midnightcontrols.client.gui; package eu.midnightdust.midnightcontrols.client.gui;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import eu.midnightdust.midnightcontrols.client.ControllerType; import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.MidnightInput; import eu.midnightdust.midnightcontrols.client.MidnightInput;
@@ -21,9 +21,7 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.Slot;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -234,6 +232,7 @@ public class MidnightControlsRenderer {
} }
//context.getMatrices().push(); //context.getMatrices().push();
context.getMatrices().translate(0f, 0f, 999f);
drawCursor(context, mouseX, mouseY, hoverSlot, client); drawCursor(context, mouseX, mouseY, hoverSlot, client);
//context.getMatrices().pop(); //context.getMatrices().pop();
} }

View File

@@ -125,6 +125,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
private final SpruceOption unfocusedInputOption; private final SpruceOption unfocusedInputOption;
private final SpruceOption invertsRightXAxis; private final SpruceOption invertsRightXAxis;
private final SpruceOption invertsRightYAxis; private final SpruceOption invertsRightYAxis;
private final SpruceOption cameraModeOption;
private final SpruceOption toggleControllerProfileOption; private final SpruceOption toggleControllerProfileOption;
private final SpruceOption rightDeadZoneOption; private final SpruceOption rightDeadZoneOption;
private final SpruceOption leftDeadZoneOption; private final SpruceOption leftDeadZoneOption;
@@ -143,6 +144,13 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
Text.translatable(key.concat(".tooltip")) Text.translatable(key.concat(".tooltip"))
); );
} }
// Touch options
private final SpruceOption touchWithControllerOption;
private final SpruceOption touchSpeedOption;
private final SpruceOption touchBreakDelayOption;
private final SpruceOption invertTouchOption;
private final SpruceOption touchTransparencyOption;
private final SpruceOption touchModeOption;
private final MutableText controllerMappingsUrlText = Text.literal("(") private final MutableText controllerMappingsUrlText = Text.literal("(")
.append(Text.literal(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD)) .append(Text.literal(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
@@ -191,7 +199,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
this.mouseSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.mouse_speed", 0.0, 150.0, .5f, this.mouseSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.mouse_speed", 0.0, 150.0, .5f,
() -> MidnightControlsConfig.mouseSpeed, () -> MidnightControlsConfig.mouseSpeed,
value -> MidnightControlsConfig.mouseSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))), value -> MidnightControlsConfig.mouseSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
Text.translatable("midnightcontrols.menu.joystick_as_mouse.tooltip")); Text.translatable("midnightcontrols.menu.mouse_speed.tooltip"));
this.joystickAsMouseOption = new SpruceToggleBooleanOption("midnightcontrols.menu.joystick_as_mouse", this.joystickAsMouseOption = new SpruceToggleBooleanOption("midnightcontrols.menu.joystick_as_mouse",
() -> MidnightControlsConfig.joystickAsMouse, value -> MidnightControlsConfig.joystickAsMouse = value, () -> MidnightControlsConfig.joystickAsMouse, value -> MidnightControlsConfig.joystickAsMouse = value,
Text.translatable("midnightcontrols.menu.joystick_as_mouse.tooltip")); Text.translatable("midnightcontrols.menu.joystick_as_mouse.tooltip"));
@@ -262,6 +270,10 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
} }
}, Text.translatable("")); }, Text.translatable(""));
this.cameraModeOption = new SpruceCyclingOption("midnightcontrols.menu.camera_mode",
amount -> MidnightControlsConfig.cameraMode = MidnightControlsConfig.cameraMode.next(),
option -> option.getDisplayText(MidnightControlsConfig.cameraMode.getTranslatedText()),
Text.translatable("midnightcontrols.menu.camera_mode.tooltip"));
this.rightDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.right_dead_zone", 0.05, 1.0, .05f, this.rightDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.right_dead_zone", 0.05, 1.0, .05f,
() -> MidnightControlsConfig.rightDeadZone, () -> MidnightControlsConfig.rightDeadZone,
value -> MidnightControlsConfig.rightDeadZone = value, option -> { value -> MidnightControlsConfig.rightDeadZone = value, option -> {
@@ -284,6 +296,27 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
value -> MidnightControlsConfig.virtualMouse = value, Text.translatable("midnightcontrols.menu.virtual_mouse.tooltip")); value -> MidnightControlsConfig.virtualMouse = value, Text.translatable("midnightcontrols.menu.virtual_mouse.tooltip"));
this.hideCursorOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hide_cursor", () -> MidnightControlsConfig.hideNormalMouse, this.hideCursorOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hide_cursor", () -> MidnightControlsConfig.hideNormalMouse,
value -> MidnightControlsConfig.hideNormalMouse = value, Text.translatable("midnightcontrols.menu.hide_cursor.tooltip")); value -> MidnightControlsConfig.hideNormalMouse = value, Text.translatable("midnightcontrols.menu.hide_cursor.tooltip"));
// Touch options
this.touchModeOption = new SpruceCyclingOption("midnightcontrols.menu.touch_mode",
amount -> MidnightControlsConfig.touchMode = MidnightControlsConfig.touchMode.next(),
option -> option.getDisplayText(MidnightControlsConfig.touchMode.getTranslatedText()),
Text.translatable("midnightcontrols.menu.touch_mode.tooltip"));
this.touchWithControllerOption = new SpruceToggleBooleanOption("midnightcontrols.menu.touch_with_controller", () -> MidnightControlsConfig.touchInControllerMode,
value -> MidnightControlsConfig.touchInControllerMode = value, Text.translatable("midnightcontrols.menu.touch_with_controller.tooltip"));
this.touchSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.touch_speed", 0.0, 150.0, .5f,
() -> MidnightControlsConfig.touchSpeed,
value -> MidnightControlsConfig.touchSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
Text.translatable("midnightcontrols.menu.touch_speed.tooltip"));
this.touchBreakDelayOption = new SpruceDoubleOption("midnightcontrols.menu.touch_break_delay", 50, 500, 1f,
() -> (double) MidnightControlsConfig.touchBreakDelay,
value -> MidnightControlsConfig.touchBreakDelay = value.intValue(), option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
Text.translatable("midnightcontrols.menu.touch_break_delay.tooltip"));
this.touchTransparencyOption = new SpruceDoubleOption("midnightcontrols.menu.touch_transparency", 0, 100, 1f,
() -> (double) MidnightControlsConfig.touchTransparency,
value -> MidnightControlsConfig.touchTransparency = value.intValue(), option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))),
Text.translatable("midnightcontrols.menu.touch_break_delay.tooltip"));
this.invertTouchOption = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_touch", () -> MidnightControlsConfig.invertTouch,
value -> MidnightControlsConfig.invertTouch = value, Text.translatable("midnightcontrols.menu.invert_touch.tooltip"));
} }
@Override @Override
@@ -337,6 +370,8 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
tabs.addSeparatorEntry(Text.translatable("midnightcontrols.menu.separator.controller")); tabs.addSeparatorEntry(Text.translatable("midnightcontrols.menu.separator.controller"));
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.controller"), null, tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.controller"), null,
this::buildControllerTab); this::buildControllerTab);
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.touch"), null,
this::buildTouchTab);
tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.mappings.string"), null, tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.mappings.string"), null,
this::buildMappingsStringEditorTab); this::buildMappingsStringEditorTab);
} }
@@ -420,6 +455,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
list.addSingleOptionEntry(this.secondControllerOption); list.addSingleOptionEntry(this.secondControllerOption);
list.addSingleOptionEntry(this.toggleControllerProfileOption); list.addSingleOptionEntry(this.toggleControllerProfileOption);
list.addSingleOptionEntry(this.unfocusedInputOption); list.addSingleOptionEntry(this.unfocusedInputOption);
list.addSingleOptionEntry(this.cameraModeOption);
list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis); list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
list.addSingleOptionEntry(this.rightDeadZoneOption); list.addSingleOptionEntry(this.rightDeadZoneOption);
list.addSingleOptionEntry(this.leftDeadZoneOption); list.addSingleOptionEntry(this.leftDeadZoneOption);
@@ -431,6 +467,18 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
root.addChild(labels); root.addChild(labels);
return root; return root;
} }
public SpruceOptionListWidget buildTouchTab(int width, int height) {
var list = new SpruceOptionListWidget(Position.origin(), width, height);
list.setBackground(new MidnightControlsBackground(130));
list.addSingleOptionEntry(this.touchSpeedOption);
list.addSingleOptionEntry(this.touchWithControllerOption);
list.addSingleOptionEntry(this.invertTouchOption);
list.addSingleOptionEntry(new SpruceSeparatorOption("midnightcontrols.menu.title.hud", true, null));
list.addSingleOptionEntry(this.touchModeOption);
list.addSingleOptionEntry(this.touchBreakDelayOption);
list.addSingleOptionEntry(this.touchTransparencyOption);
return list;
}
public SpruceContainerWidget buildMappingsStringEditorTab(int width, int height) { public SpruceContainerWidget buildMappingsStringEditorTab(int width, int height) {
return new MappingsStringInputWidget(Position.origin(), width, height); return new MappingsStringInputWidget(Position.origin(), width, height);

View File

@@ -33,7 +33,7 @@ public class ReloadControllerMappingsOption {
Controller.updateMappings(); Controller.updateMappings();
if (client.currentScreen instanceof MidnightControlsSettingsScreen) if (client.currentScreen instanceof MidnightControlsSettingsScreen)
client.currentScreen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight()); client.currentScreen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT, client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
Text.translatable("midnightcontrols.controller.mappings.updated"), Text.empty())); Text.translatable("midnightcontrols.controller.mappings.updated"), Text.empty()));
}, Text.translatable("midnightcontrols.tooltip.reload_controller_mappings")); }, Text.translatable("midnightcontrols.tooltip.reload_controller_mappings"));
} }

View File

@@ -15,7 +15,6 @@ import eu.midnightdust.midnightcontrols.client.ring.RingPage;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text; import net.minecraft.text.Text;
/** /**

View File

@@ -11,25 +11,39 @@ package eu.midnightdust.midnightcontrols.client.gui;
import dev.lambdaurora.spruceui.Position; import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget; import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
import eu.midnightdust.midnightcontrols.client.HudSide; import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.widget.SilentTexturedButtonWidget; import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.touch.gui.ItemUseButtonWidget;
import eu.midnightdust.midnightcontrols.client.touch.gui.SilentTexturedButtonWidget;
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor; import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.GameMenuScreen; import net.minecraft.client.gui.screen.*;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.InventoryScreen; import net.minecraft.client.gui.screen.ingame.InventoryScreen;
import net.minecraft.client.gui.widget.TexturedButtonWidget; import net.minecraft.client.gui.widget.TextIconButtonWidget;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.texture.MissingSprite;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.InputUtil;
import net.minecraft.item.*;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Arm; import net.minecraft.util.*;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.util.List;
import java.util.Objects;
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X; import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X;
import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y; import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
@@ -38,17 +52,26 @@ import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
*/ */
public class TouchscreenOverlay extends Screen { public class TouchscreenOverlay extends Screen {
public static final Identifier WIDGETS_LOCATION = new Identifier("midnightcontrols", "textures/gui/widgets.png"); public static final Identifier WIDGETS_LOCATION = new Identifier("midnightcontrols", "textures/gui/widgets.png");
private MidnightControlsClient mod; private final MidnightControlsClient mod;
private SilentTexturedButtonWidget inventoryButton;
private SilentTexturedButtonWidget swapHandsButton;
private SilentTexturedButtonWidget dropButton;
private ItemUseButtonWidget useButton;
private SilentTexturedButtonWidget jumpButton; private SilentTexturedButtonWidget jumpButton;
private SilentTexturedButtonWidget flyButton; private SilentTexturedButtonWidget flyButton;
private SilentTexturedButtonWidget flyUpButton; private SilentTexturedButtonWidget flyUpButton;
private SilentTexturedButtonWidget flyDownButton; private SilentTexturedButtonWidget flyDownButton;
private int flyButtonEnableTicks = 0; private SilentTexturedButtonWidget forwardButton;
private int forwardButtonTick = 0;
private SilentTexturedButtonWidget forwardLeftButton; private SilentTexturedButtonWidget forwardLeftButton;
private SilentTexturedButtonWidget forwardRightButton; private SilentTexturedButtonWidget forwardRightButton;
private SilentTexturedButtonWidget leftButton;
private SilentTexturedButtonWidget rightButton;
private SilentTexturedButtonWidget backButton;
private SilentTexturedButtonWidget startSneakButton; private SilentTexturedButtonWidget startSneakButton;
private SilentTexturedButtonWidget endSneakButton; private SilentTexturedButtonWidget endSneakButton;
private int flyButtonEnableTicks = 0;
private int forwardButtonTick = 0;
public static TouchscreenOverlay instance;
public TouchscreenOverlay(@NotNull MidnightControlsClient mod) { public TouchscreenOverlay(@NotNull MidnightControlsClient mod) {
super(Text.literal("Touchscreen overlay")); super(Text.literal("Touchscreen overlay"));
@@ -56,27 +79,18 @@ public class TouchscreenOverlay extends Screen {
} }
@Override @Override
public boolean shouldPause() public boolean shouldPause() {
{
return false; return false;
} }
@Override @Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) { public void renderInGameBackground(DrawContext context) {}
super.keyPressed(keyCode,scanCode,modifiers);
//return false;
return true;
}
private void pauseGame(boolean bl) { private void pauseGame() {
if (this.client == null) assert this.client != null;
return;
boolean bl2 = this.client.isIntegratedServerRunning() && !this.client.getServer().isRemote();
if (bl2) {
this.client.setScreen(new GameMenuScreen(!bl));
this.client.getSoundManager().pauseAll();
} else {
this.client.setScreen(new GameMenuScreen(true)); this.client.setScreen(new GameMenuScreen(true));
if (this.client.isIntegratedServerRunning() && !Objects.requireNonNull(this.client.getServer()).isRemote()) {
this.client.getSoundManager().pauseAll();
} }
} }
@@ -87,24 +101,26 @@ public class TouchscreenOverlay extends Screen {
* *
*/ */
private void updateForwardButtonsState(boolean state) { private void updateForwardButtonsState(boolean state) {
if (state) this.forwardButtonTick = state ? -1 : 20;
this.forwardButtonTick = -1;
else
this.forwardButtonTick = 20;
} }
/** /**
* Updates the jump buttons. * Updates the jump buttons.
*/ */
private void updateJumpButtons() { private void updateJumpButtons() {
if (this.client == null) assert this.client != null;
return; assert this.client.player != null;
if (!this.client.interactionManager.isFlyingLocked()) { float transparency = MidnightControlsConfig.touchTransparency / 100f;
if (this.client.player.getAbilities().flying) {
boolean oldStateFly = this.flyButton.isVisible(); boolean oldStateFly = this.flyButton.isVisible();
this.jumpButton.setVisible(false); this.jumpButton.setVisible(false);
this.flyButton.setVisible(true); this.flyButton.setVisible(true);
this.flyUpButton.setVisible(true); this.flyUpButton.setVisible(true);
this.flyDownButton.setVisible(true); this.flyDownButton.setVisible(true);
this.flyButton.setAlpha(transparency);
this.flyUpButton.setAlpha(transparency);
this.flyDownButton.setAlpha(transparency);
if (oldStateFly != this.flyButton.isVisible()) { if (oldStateFly != this.flyButton.isVisible()) {
this.flyButtonEnableTicks = 5; this.flyButtonEnableTicks = 5;
this.setJump(false); this.setJump(false);
@@ -115,6 +131,7 @@ public class TouchscreenOverlay extends Screen {
this.flyButton.setVisible(false); this.flyButton.setVisible(false);
this.flyUpButton.setVisible(false); this.flyUpButton.setVisible(false);
this.flyDownButton.setVisible(false); this.flyDownButton.setVisible(false);
this.jumpButton.setAlpha(transparency);
} }
} }
@@ -124,6 +141,7 @@ public class TouchscreenOverlay extends Screen {
* @param btn The pressed button. * @param btn The pressed button.
*/ */
private void handleJump(SpruceButtonWidget btn) { private void handleJump(SpruceButtonWidget btn) {
assert this.client != null;
((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(btn.isActive()); ((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(btn.isActive());
} }
/** /**
@@ -132,31 +150,32 @@ public class TouchscreenOverlay extends Screen {
* @param state The state. * @param state The state.
*/ */
private void setJump(boolean state) { private void setJump(boolean state) {
assert this.client != null;
((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(state); ((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(state);
} }
@Override
public void tick() {
if (this.forwardButtonTick > 0) {
this.forwardButtonTick--;
} else if (this.forwardButtonTick == 0) {
if (this.forwardLeftButton.isVisible())
this.forwardLeftButton.setVisible(false);
if (this.forwardRightButton.isVisible())
this.forwardRightButton.setVisible(false);
}
this.updateJumpButtons();
}
@Override @Override
protected void init() { protected void init() {
super.init(); super.init();
assert this.client != null;
assert this.client.player != null;
assert this.client.interactionManager != null;
int scaledWidth = this.client.getWindow().getScaledWidth(); int scaledWidth = this.client.getWindow().getScaledWidth();
int scaledHeight = this.client.getWindow().getScaledHeight(); int scaledHeight = this.client.getWindow().getScaledHeight();
this.addDrawableChild(new TexturedButtonWidget(scaledWidth / 2 - 20, 0, 20, 20, 0, 106, 20, new Identifier("textures/gui/widgets.png"), 256, 256, int emoteOffset = 0;
btn -> this.client.setScreen(new ChatScreen("")), Text.empty())); if (PlatformFunctions.isModLoaded("emotecraft")) {
this.addDrawableChild(new TexturedButtonWidget(scaledWidth / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256, emoteOffset = 10;
btn -> this.pauseGame(false))); TextIconButtonWidget emoteButton = TextIconButtonWidget.builder(Text.empty(), btn -> EmotecraftCompat.openEmotecraftScreen(this), true).width(20).texture(new Identifier(MidnightControlsConstants.NAMESPACE, "touch/emote"), 20, 20).build();
emoteButton.setPosition(scaledWidth / 2 - 30, 0);
this.addDrawableChild(emoteButton);
}
TextIconButtonWidget chatButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.client.setScreen(new ChatScreen("")), true).width(20).texture(new Identifier(MidnightControlsConstants.NAMESPACE, "touch/chat"), 20, 20).build();
chatButton.setPosition(scaledWidth / 2 - 20 + emoteOffset, 0);
this.addDrawableChild(chatButton);
TextIconButtonWidget pauseButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.pauseGame(), true).width(20).texture(new Identifier(MidnightControlsConstants.NAMESPACE, "touch/pause"), 20, 20).build();
pauseButton.setPosition(scaledWidth / 2 + emoteOffset, 0);
this.addDrawableChild(pauseButton);
// Inventory buttons. // Inventory buttons.
int inventoryButtonX = scaledWidth / 2; int inventoryButtonX = scaledWidth / 2;
int inventoryButtonY = scaledHeight - 16 - 5; int inventoryButtonY = scaledHeight - 16 - 5;
@@ -165,15 +184,15 @@ public class TouchscreenOverlay extends Screen {
} else { } else {
inventoryButtonX = inventoryButtonX + 91 + 4; inventoryButtonX = inventoryButtonX + 91 + 4;
} }
this.addDrawableChild(new TexturedButtonWidget(inventoryButtonX, inventoryButtonY, 20, 20, 20, 0, 20, WIDGETS_LOCATION, 256, 256, this.addDrawableChild(this.inventoryButton = new SilentTexturedButtonWidget(Position.of(inventoryButtonX, inventoryButtonY), 20, 20, Text.empty(), btn -> {
btn -> {
if (this.client.interactionManager.hasRidingInventory()) { if (this.client.interactionManager.hasRidingInventory()) {
this.client.player.openRidingInventory(); this.client.player.openRidingInventory();
} else { } else {
this.client.getTutorialManager().onInventoryOpened(); this.client.getTutorialManager().onInventoryOpened();
this.client.setScreen(new InventoryScreen(this.client.player)); this.client.setScreen(new InventoryScreen(this.client.player));
} }
})); }, 20, 0, 20, WIDGETS_LOCATION, 256, 256));
;
int jumpButtonX, swapHandsX, sneakButtonX; int jumpButtonX, swapHandsX, sneakButtonX;
int sneakButtonY = scaledHeight - 10 - 40 - 5; int sneakButtonY = scaledHeight - 10 - 40 - 5;
if (MidnightControlsConfig.hudSide == HudSide.LEFT) { if (MidnightControlsConfig.hudSide == HudSide.LEFT) {
@@ -186,17 +205,23 @@ public class TouchscreenOverlay extends Screen {
sneakButtonX = scaledWidth - 10 - 40 - 5; sneakButtonX = scaledWidth - 10 - 40 - 5;
} }
// Swap items hand. // Swap items hand.
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY), 20, 20, Text.empty(), this.addDrawableChild(this.swapHandsButton = new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY), 20, 20, Text.empty(),
button -> { button -> {
if (button.isActive()) { if (button.isActive()) {
if (!this.client.player.isSpectator()) { if (!this.client.player.isSpectator()) {
this.client.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN)); Objects.requireNonNull(this.client.getNetworkHandler()).sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN));
} }
} }
},0, 160, 20, WIDGETS_LOCATION)); },0, 160, 20, WIDGETS_LOCATION));
// Drop // Drop
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY + 5 + 20), 20, 20, Text.empty(), btn -> this.addDrawableChild(this.dropButton = new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY + 5 + 20), 20, 20, Text.empty(), btn -> {
((KeyBindingAccessor) this.client.options.dropKey).midnightcontrols$handlePressState(btn.isActive()), 0, 160, 20, WIDGETS_LOCATION)); if (btn.isActive() && !client.player.isSpectator() && client.player.dropSelectedItem(false)) {
client.player.swingHand(Hand.MAIN_HAND);
}
}, 20, 160, 20, WIDGETS_LOCATION));
// Use
this.addDrawableChild(this.useButton = new ItemUseButtonWidget(Position.of(width/2-25, height - 70), 50, 17, Text.translatable(MidnightControlsConstants.NAMESPACE+".action.eat"), btn ->
client.interactionManager.interactItem(client.player, client.player.getActiveHand())));
// Jump keys // Jump keys
this.addDrawableChild(this.jumpButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.empty(), this::handleJump, 0, 40, 20, WIDGETS_LOCATION)); this.addDrawableChild(this.jumpButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.empty(), this::handleJump, 0, 40, 20, WIDGETS_LOCATION));
this.addDrawableChild(this.flyButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.empty(),btn -> { this.addDrawableChild(this.flyButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.empty(),btn -> {
@@ -226,15 +251,13 @@ public class TouchscreenOverlay extends Screen {
this.startSneakButton.setVisible(true); this.startSneakButton.setVisible(true);
} }
}, 20, 120, 20, WIDGETS_LOCATION))); }, 20, 120, 20, WIDGETS_LOCATION)));
this.endSneakButton.setVisible(false);
this.addDrawableChild(this.forwardLeftButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20), 20, 20, Text.empty(), btn -> { this.addDrawableChild(this.forwardLeftButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20), 20, 20, Text.empty(), btn -> {
((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive()); ((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive());
((KeyBindingAccessor) this.client.options.leftKey).midnightcontrols$handlePressState(btn.isActive()); ((KeyBindingAccessor) this.client.options.leftKey).midnightcontrols$handlePressState(btn.isActive());
this.updateForwardButtonsState(btn.isActive()); this.updateForwardButtonsState(btn.isActive());
}, 80, 80, 20, WIDGETS_LOCATION }, 80, 80, 20, WIDGETS_LOCATION
)); ));
this.forwardLeftButton.setVisible(false); this.addDrawableChild(this.forwardButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY - 5 - 20), 20, 20, Text.empty(), btn -> {
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY - 5 - 20), 20, 20, Text.empty(), btn -> {
((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive()); ((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive());
this.updateForwardButtonsState(btn.isActive()); this.updateForwardButtonsState(btn.isActive());
this.forwardLeftButton.setVisible(true); this.forwardLeftButton.setVisible(true);
@@ -247,48 +270,107 @@ public class TouchscreenOverlay extends Screen {
this.updateForwardButtonsState(btn.isActive()); this.updateForwardButtonsState(btn.isActive());
}, 100, 80, 20, WIDGETS_LOCATION }, 100, 80, 20, WIDGETS_LOCATION
)); ));
this.forwardRightButton.setVisible(true);
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX + 20 + 5, sneakButtonY), 20, 20, Text.empty(), this.addDrawableChild(this.rightButton =new SilentTexturedButtonWidget(Position.of(sneakButtonX + 20 + 5, sneakButtonY), 20, 20, Text.empty(),
btn -> ((KeyBindingAccessor) this.client.options.rightKey).midnightcontrols$handlePressState(btn.isActive()), 20, 80, 20, WIDGETS_LOCATION btn -> ((KeyBindingAccessor) this.client.options.rightKey).midnightcontrols$handlePressState(btn.isActive()), 20, 80, 20, WIDGETS_LOCATION
)); ));
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY + 20 + 5), 20, 20, Text.empty(), this.addDrawableChild(this.backButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY + 20 + 5), 20, 20, Text.empty(),
btn -> ((KeyBindingAccessor) this.client.options.backKey).midnightcontrols$handlePressState(btn.isActive()), 40, 80, 20, WIDGETS_LOCATION btn -> ((KeyBindingAccessor) this.client.options.backKey).midnightcontrols$handlePressState(btn.isActive()), 40, 80, 20, WIDGETS_LOCATION
)); ));
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX - 20 - 5, sneakButtonY), 20, 20, Text.empty(), this.addDrawableChild(this.leftButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX - 20 - 5, sneakButtonY), 20, 20, Text.empty(),
btn -> ((KeyBindingAccessor) this.client.options.leftKey).midnightcontrols$handlePressState(btn.isActive()), 60, 80, 20, WIDGETS_LOCATION btn -> ((KeyBindingAccessor) this.client.options.leftKey).midnightcontrols$handlePressState(btn.isActive()), 60, 80, 20, WIDGETS_LOCATION
)); ));
initCustomButtons(true);
initCustomButtons(false);
this.setButtonProperties(MidnightControlsConfig.touchTransparency / 100f);
TouchscreenOverlay.instance = this;
}
private void initCustomButtons(boolean left) {
assert client != null;
Identifier emptySprite = new Identifier(MidnightControlsConstants.NAMESPACE, "touch/empty");
List<String> list = left ? MidnightControlsConfig.leftTouchBinds : MidnightControlsConfig.rightTouchBinds;
Sprite missingSprite = client.getGuiAtlasManager().getSprite(MissingSprite.getMissingSpriteId());
for (int i = 0; i < list.size(); i++) {
String bindName = list.get(i);
ButtonBinding binding = InputManager.getBinding(bindName);
if (binding == null) continue;
boolean hasTexture = client.getGuiAtlasManager().getSprite(new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName)) != missingSprite;
if (MidnightControlsConfig.debug) System.out.println(left +" "+new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName)+" "+ hasTexture);
var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> binding.handle(client, 1, ButtonState.PRESS), hasTexture)
.texture(hasTexture ? new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName) : emptySprite, 20, 20).dimension(20, 20).build();
button.setPosition(left ? (3+(i*23)) : this.width-(23+(i*23)), 3);
button.setAlpha(MidnightControlsConfig.touchTransparency / 100f);
this.addDrawableChild(button);
}
}
private void setButtonProperties(float transparency) {
this.inventoryButton.setAlpha(transparency);
this.dropButton.setAlpha(transparency);
this.swapHandsButton.setAlpha(transparency);
this.jumpButton.setAlpha(transparency);
this.flyButton.setAlpha(transparency);
this.flyUpButton.setAlpha(transparency);
this.useButton.setAlpha(Math.min(transparency+0.1f, 1.0f));
this.flyDownButton.setAlpha(transparency);
this.startSneakButton.setAlpha(transparency);
this.endSneakButton.setAlpha(transparency);
this.forwardButton.setAlpha(transparency);
this.forwardLeftButton.setAlpha(Math.max(0.05f, transparency-0.1f));
this.forwardRightButton.setAlpha(Math.max(0.05f, transparency-0.1f));
this.leftButton.setAlpha(transparency);
this.rightButton.setAlpha(transparency);
this.backButton.setAlpha(transparency);
this.useButton.setAlpha(Math.min(transparency+0.1f, 1.0f));
this.endSneakButton.setVisible(false);
this.forwardLeftButton.setVisible(false);
this.forwardRightButton.setVisible(false);
} }
@Override @Override
public boolean mouseClicked(double mouseX, double mouseY, int button) { public void tick() {
if (mouseY >= (double) (this.height - 22) && this.client != null && this.client.player != null) { assert this.client != null;
int centerX = this.width / 2; assert this.client.interactionManager != null;
if (mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) { assert this.client.player != null;
for (int slot = 0; slot < 9; ++slot) {
int slotX = centerX - 90 + slot * 20 + 2; if (this.forwardButtonTick > 0) {
if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) { --this.forwardButtonTick;
this.client.player.getInventory().selectedSlot = slot; } else {
return true; this.forwardLeftButton.setVisible(false);
this.forwardRightButton.setVisible(false);
} }
} this.useButton.setVisible(client.player.getMainHandStack() != null && (client.player.getMainHandStack().getUseAction() != UseAction.NONE || client.player.getMainHandStack().getItem() instanceof ArmorItem) && !TouchUtils.hasInWorldUseAction(client.player.getMainHandStack()));
} this.updateJumpButtons();
}
return super.mouseClicked(mouseX, mouseY, button);
} }
@Override @Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) { if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) {
if (!MidnightControlsConfig.invertTouch) {
deltaX = -deltaX;
deltaY = -deltaY;
}
if (deltaY > 0.01) if (deltaY > 0.01)
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 2); this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs((deltaY / 3.0)*MidnightControlsConfig.touchSpeed/100), 2);
else if (deltaY < 0.01) else this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs((deltaY / 3.0)*MidnightControlsConfig.touchSpeed/100), 1);
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 1);
if (deltaX > 0.01) if (deltaX > 0.01)
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 2); this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs((deltaX / 3.0)*MidnightControlsConfig.touchSpeed/100), 2);
else if (deltaX < 0.01) else this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs((deltaX / 3.0)*MidnightControlsConfig.touchSpeed/100), 1);
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 1);
} }
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
} }
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
KeyBinding.onKeyPressed(InputUtil.fromKeyCode(keyCode, scanCode));
super.keyPressed(keyCode,scanCode,modifiers);
return true;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
super.render(context, mouseX, mouseY, delta);
context.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
context.fill(mouseX-10, mouseY-10, mouseX+10, mouseY+10, 0xFFFFFF);
}
} }

View File

@@ -9,11 +9,11 @@
package eu.midnightdust.midnightcontrols.client.mixin; package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.lib.util.screen.TexturedOverlayButtonWidget;
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen; import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
import net.minecraft.client.gui.screen.option.GameOptionsScreen; import net.minecraft.client.gui.screen.option.GameOptionsScreen;
import net.minecraft.client.gui.widget.TextIconButtonWidget;
import net.minecraft.client.option.GameOptions; import net.minecraft.client.option.GameOptions;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@@ -32,8 +32,9 @@ public abstract class ControlsOptionsScreenMixin extends GameOptionsScreen {
} }
@Inject(method = "init", at = @At(value = "INVOKE", ordinal = 1, shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;")) @Inject(method = "init", at = @At(value = "INVOKE", ordinal = 1, shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;"))
private void addControllerButton(CallbackInfo ci) { private void addControllerButton(CallbackInfo ci) {
this.addDrawableChild(new TexturedOverlayButtonWidget(this.width / 2 + 158, this.height / 6 - 12, 20, 20,0,0,20, new Identifier("midnightcontrols", "textures/gui/midnightcontrols_button.png"), 32, 64, (button) -> { TextIconButtonWidget iconWidget = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"), (button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true)
this.client.setScreen(new MidnightControlsSettingsScreen(this, false)); .dimension(20,20).texture(new Identifier("midnightcontrols", "icon/controller"), 20, 20).build();
}, Text.translatable("midnightcontrols.menu.title.controller"))); iconWidget.setPosition(this.width / 2 + 158, this.height / 6 - 12);
this.addDrawableChild(iconWidget);
} }
} }

View File

@@ -1,21 +0,0 @@
/*
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of midnightcontrols.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.mixin;
import net.minecraft.client.gui.navigation.NavigationDirection;
import net.minecraft.client.gui.widget.EntryListWidget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(EntryListWidget.class)
public interface EntryListWidgetAccessor {
//@Invoker("getNeighbouringEntry")
//void midnightcontrols$getNeighbouringEntry(NavigationDirection direction);
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of midnightcontrols.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.mixin;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.SimpleOption;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Represents a mixin to GameOptions.
* <p>
* Sets the default of the Auto-Jump option to false.
*/
@Mixin(GameOptions.class)
public abstract class GameOptionsMixin {
@Shadow public abstract SimpleOption<Boolean> getAutoJump();
@Inject(method = "load", at = @At("HEAD"))
public void onInit(CallbackInfo ci) {
// Set default value of the Auto-Jump option to false.
getAutoJump().setValue(false);
}
}

View File

@@ -9,10 +9,12 @@
package eu.midnightdust.midnightcontrols.client.mixin; package eu.midnightdust.midnightcontrols.client.mixin;
import com.mojang.blaze3d.systems.RenderSystem;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.GameRenderer;
@@ -26,7 +28,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(GameRenderer.class) @Mixin(GameRenderer.class)
public class GameRendererMixin { public abstract class GameRendererMixin {
@Shadow @Shadow
@Final @Final
MinecraftClient client; MinecraftClient client;
@@ -37,8 +39,14 @@ public class GameRendererMixin {
MidnightControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen); MidnightControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen);
} }
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;draw()V", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILSOFT) @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;draw()V", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILSOFT)
private void renderVirtualCursor(float tickDelta, long startTime, boolean tick, CallbackInfo ci, MatrixStack matrixStack, DrawContext drawContext) { private void renderVirtualCursor(float tickDelta, long startTime, boolean tick, CallbackInfo ci, boolean bl, MatrixStack matrixStack, DrawContext drawContext) {
MidnightControlsRenderer.renderVirtualCursor(drawContext, client); MidnightControlsRenderer.renderVirtualCursor(drawContext, client);
drawContext.draw(); drawContext.draw();
} }
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z", ordinal = 0), method = "renderWorld")
private void postWorldRender(float tickDelta, long limitTime, MatrixStack matrix, CallbackInfo ci) {
TouchUtils.lastProjMat.set(RenderSystem.getProjectionMatrix());
TouchUtils.lastModMat.set(RenderSystem.getModelViewMatrix());
TouchUtils.lastWorldSpaceMatrix.set(matrix.peek().getPositionMatrix());
}
} }

View File

@@ -2,20 +2,14 @@ package eu.midnightdust.midnightcontrols.client.mixin;
import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.InputUtil;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Final;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import java.lang.invoke.MethodHandle; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(InputUtil.class) @Mixin(InputUtil.class)
public abstract class InputUtilMixin { public abstract class InputUtilMixin {
@Final
@Shadow
private static MethodHandle GLFW_RAW_MOUSE_MOTION_SUPPORTED_HANDLE;
/** /**
* @author kabliz * @author kabliz
* @reason This method is static, and there is a terrible UX issue if raw input is turned on at the same time as * @reason This method is static, and there is a terrible UX issue if raw input is turned on at the same time as
@@ -23,17 +17,8 @@ public abstract class InputUtilMixin {
* unresponsive and the player not understanding why. This overwrite preserves the user's mouse preferences, * unresponsive and the player not understanding why. This overwrite preserves the user's mouse preferences,
* while not interfering with eye tracking, and the two modes can be switched between during a play session. * while not interfering with eye tracking, and the two modes can be switched between during a play session.
*/ */
@Overwrite @Inject(method = "isRawMouseMotionSupported", at = @At("HEAD"), cancellable = true)
public static boolean isRawMouseMotionSupported(){ private static void setRawMouseMotionSupported(CallbackInfoReturnable<Boolean> cir) {
if(MidnightControlsConfig.eyeTrackerAsMouse){ if (MidnightControlsConfig.eyeTrackerAsMouse) cir.setReturnValue(false);
return false;
} else { //Paste original implementation from InputUtil below.
try {
return GLFW_RAW_MOUSE_MOTION_SUPPORTED_HANDLE != null &&
(boolean) GLFW_RAW_MOUSE_MOTION_SUPPORTED_HANDLE.invokeExact();
} catch (Throwable var1) {
throw new RuntimeException(var1);
}
}
} }
} }

View File

@@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@Mixin(KeyBinding.class) @Mixin(KeyBinding.class)
public class KeyBindingMixin implements KeyBindingAccessor { public abstract class KeyBindingMixin implements KeyBindingAccessor {
@Shadow @Shadow
private int timesPressed; private int timesPressed;

View File

@@ -1,19 +0,0 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import net.fabricmc.fabric.impl.client.keybinding.KeyBindingRegistryImpl;
import net.minecraft.client.option.KeyBinding;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(value = KeyBindingRegistryImpl.class, remap = false)
public interface KeyBindingRegistryImplAccessor {
@Accessor @Final
static List<KeyBinding> getMODDED_KEY_BINDINGS() {
return null;
}
}

View File

@@ -0,0 +1,18 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import net.minecraft.client.Keyboard;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(Keyboard.class)
public class KeyboardMixin {
@Redirect(method = "onKey", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;"))
private Screen midnightcontrols$ignoreTouchOverlay(MinecraftClient instance) {
if (instance.currentScreen instanceof TouchscreenOverlay) return null;
return instance.currentScreen;
}
}

View File

@@ -9,21 +9,15 @@
package eu.midnightdust.midnightcontrols.client.mixin; package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.midnightcontrols.MidnightControls;
import eu.midnightdust.midnightcontrols.MidnightControlsFeature; import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.MidnightInput;
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.render.BufferBuilderStorage; import net.minecraft.client.render.BufferBuilderStorage;
import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
@@ -35,7 +29,6 @@ import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -46,24 +39,15 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(MinecraftClient.class) @Mixin(MinecraftClient.class)
public abstract class MinecraftClientMixin { public abstract class MinecraftClientMixin {
@Shadow @Shadow @Nullable public HitResult crosshairTarget;
@Nullable
public HitResult crosshairTarget;
@Shadow @Shadow @Nullable public ClientPlayerEntity player;
@Nullable
public ClientPlayerEntity player;
@Shadow @Shadow @Nullable public ClientPlayerInteractionManager interactionManager;
@Nullable
public ClientPlayerInteractionManager interactionManager;
@Shadow @Shadow @Final public GameRenderer gameRenderer;
@Final
public GameRenderer gameRenderer;
@Shadow @Shadow private int itemUseCooldown;
private int itemUseCooldown;
@Shadow public abstract BufferBuilderStorage getBufferBuilders(); @Shadow public abstract BufferBuilderStorage getBufferBuilders();
@@ -115,10 +99,6 @@ public abstract class MinecraftClientMixin {
// } // }
this.midnightcontrols$lastPos = this.player.getPos(); this.midnightcontrols$lastPos = this.player.getPos();
} }
@Inject(method = "render", at = @At("HEAD"))
private void onRender(CallbackInfo ci) {
MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this));
}
@Inject(at = @At("TAIL"), method = "setScreen") @Inject(at = @At("TAIL"), method = "setScreen")
private void setScreen(Screen screen, CallbackInfo info) { private void setScreen(Screen screen, CallbackInfo info) {
@@ -161,4 +141,10 @@ public abstract class MinecraftClientMixin {
} }
} }
} }
// This is always supposed to be located at before the line 'this.profiler.swap("Keybindings");'
// @Redirect(method = "tick", at = @At(value = "FIELD",target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", ordinal = 6))
// private Screen midnightcontrols$ignoreTouchOverlay(MinecraftClient instance) {
// if (instance.currentScreen instanceof TouchscreenOverlay) return null;
// return instance.currentScreen;
// }
} }

View File

@@ -0,0 +1,15 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import net.minecraft.client.Mouse;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(Mouse.class)
public interface MouseAccessor {
@Accessor
void setLeftButtonClicked(boolean value);
@Invoker("onCursorPos")
void midnightcontrols$onCursorPos(long window, double x, double y);
}

View File

@@ -12,101 +12,102 @@ package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Mouse; import net.minecraft.client.Mouse;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.GlfwUtil; import net.minecraft.client.util.GlfwUtil;
import net.minecraft.client.util.SmoothUtil; import net.minecraft.client.util.SmoothUtil;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import eu.midnightdust.midnightcontrols.client.mouse.EyeTrackerHandler; import eu.midnightdust.midnightcontrols.client.mouse.EyeTrackerHandler;
import static org.lwjgl.glfw.GLFW.GLFW_CURSOR; import static eu.midnightdust.midnightcontrols.client.MidnightControlsConfig.doMixedInput;
import static org.lwjgl.glfw.GLFW.GLFW_CURSOR_HIDDEN; import static org.lwjgl.glfw.GLFW.*;
/** /**
* Adds extra access to the mouse. * Adds extra access to the mouse.
*/ */
@Mixin(Mouse.class) @Mixin(Mouse.class)
public abstract class MouseMixin implements MouseAccessor { public abstract class MouseMixin implements MouseAccessor {
@Shadow @Shadow @Final private MinecraftClient client;
@Final
private MinecraftClient client;
@Shadow @Shadow private double y;
private double y;
@Shadow @Shadow private double cursorDeltaX;
private double cursorDeltaX;
@Shadow @Shadow private double cursorDeltaY;
private double cursorDeltaY;
@Shadow @Shadow private double x;
private double x;
@Shadow @Shadow private boolean cursorLocked;
private boolean cursorLocked;
@Shadow @Shadow private boolean hasResolutionChanged;
private boolean hasResolutionChanged;
@Shadow @Shadow private double lastMouseUpdateTime;
private double lastMouseUpdateTime;
@Shadow @Shadow @Final private SmoothUtil cursorXSmoother;
@Final
private SmoothUtil cursorXSmoother;
@Shadow @Shadow @Final private SmoothUtil cursorYSmoother;
@Final
private SmoothUtil cursorYSmoother;
@Shadow private boolean leftButtonClicked; @Shadow private boolean leftButtonClicked;
@Accessor @Inject(method = "onMouseButton", at = @At(value = "HEAD"), cancellable = true)
public abstract void setLeftButtonClicked(boolean value); private void midnightcontrols$onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) {
if (window != this.client.getWindow().getHandle()) return;
@Invoker("onCursorPos") if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && client.currentScreen != null) {
public abstract void midnightcontrols$onCursorPos(long window, double x, double y); MidnightControlsClient.get().input.tryGoBack(client.currentScreen);
@Inject(method = "onMouseButton", at = @At(value = "TAIL"))
private void onMouseBackButton(long window, int button, int action, int mods, CallbackInfo ci) {
if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && MinecraftClient.getInstance().currentScreen != null) {
if (MidnightControlsClient.get().input.tryGoBack(MinecraftClient.getInstance().currentScreen)) {
action = 0;
} }
else if ((doMixedInput() || client.currentScreen instanceof TouchscreenOverlay) && client.player != null && button == GLFW_MOUSE_BUTTON_1) {
double mouseX = x / client.getWindow().getScaleFactor();
double mouseY = y / client.getWindow().getScaleFactor();
int centerX = client.getWindow().getScaledWidth() / 2;
if (action == 1 && mouseY >= (double) (client.getWindow().getScaledHeight() - 22) && mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) {
for (int slot = 0; slot < 9; ++slot) {
int slotX = centerX - 90 + slot * 20 + 2;
if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) {
client.player.getInventory().selectedSlot = slot;
ci.cancel();
return;
}
}
}
if (action == 1) {
TouchInput.clickStartTime = System.currentTimeMillis();
boolean bl = false;
if (client.currentScreen instanceof TouchscreenOverlay overlay) bl = overlay.mouseClicked(mouseX, mouseY, button);
if (!bl) TouchInput.firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
if (client.currentScreen == null) ci.cancel();
}
else if (TouchInput.mouseReleased(mouseX, mouseY, button)) ci.cancel();
} }
} }
@Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true) @Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true)
private void isCursorLocked(CallbackInfoReturnable<Boolean> ci) { private void midnightcontrols$isCursorLocked(CallbackInfoReturnable<Boolean> ci) {
if (this.client.currentScreen == null) { if (this.client.currentScreen == null) {
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse) { if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse) {
ci.setReturnValue(true);
ci.cancel(); ci.cancel();
} }
} }
} }
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true) @Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
private void onCursorLocked(CallbackInfo ci) { private void midnightcontrols$onCursorLocked(CallbackInfo ci) {
if (/*config.getControlsMode() == ControlsMode.TOUCHSCREEN if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN || doMixedInput())
||*/ (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse))
ci.cancel(); ci.cancel();
} }
@Inject(method = "updateMouse", at = @At("HEAD"), cancellable = true) @Inject(method = "updateMouse", at = @At("HEAD"), cancellable = true)
private void updateMouse(CallbackInfo ci) { private void midnightcontrols$updateMouse(CallbackInfo ci) {
if (MidnightControlsConfig.eyeTrackerAsMouse && cursorLocked && client.isWindowFocused()) { if (MidnightControlsConfig.eyeTrackerAsMouse && cursorLocked && client.isWindowFocused()) {
// Eye Tracking is only for the camera controlling cursor, we need the normal cursor everywhere else. // Eye Tracking is only for the camera controlling cursor, we need the normal cursor everywhere else.
if (!client.options.smoothCameraEnabled) { if (!client.options.smoothCameraEnabled) {
@@ -120,17 +121,16 @@ public abstract class MouseMixin implements MouseAccessor {
cursorDeltaY = 0.0; cursorDeltaY = 0.0;
ci.cancel(); ci.cancel();
} }
if (doMixedInput() && client.isWindowFocused()) {
ci.cancel();
}
} }
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true) @Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/InputUtil;setCursorParameters(JIDD)V",shift = At.Shift.BEFORE), cancellable = true)
private void lockCursor(CallbackInfo ci) { private void midnightcontrols$lockCursor(CallbackInfo ci) {
if (MidnightControlsConfig.eyeTrackerAsMouse && client.isWindowFocused() && !this.cursorLocked) { if ((doMixedInput() || MidnightControlsConfig.eyeTrackerAsMouse)) {
if (!MinecraftClient.IS_SYSTEM_MAC) {
KeyBinding.updatePressedStates();
}
//In eye tracking mode, we cannot have the cursor locked to the center. //In eye tracking mode, we cannot have the cursor locked to the center.
GLFW.glfwSetInputMode(client.getWindow().getHandle(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); GLFW.glfwSetInputMode(client.getWindow().getHandle(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
cursorLocked = true; //The game uses this flag for other gameplay checks
client.setScreen(null); client.setScreen(null);
hasResolutionChanged = true; hasResolutionChanged = true;
ci.cancel(); ci.cancel();

View File

@@ -1,17 +0,0 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.Screen;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(Screen.class)
public interface ScreenAccessor {
@Accessor
List<Selectable> getSelectables();
@Accessor @Nullable
Selectable getSelected();
}

View File

@@ -0,0 +1,38 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import dev.lambdaurora.spruceui.Position;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.InputHandlers;
import eu.midnightdust.midnightcontrols.client.touch.gui.SilentTexturedButtonWidget;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay.WIDGETS_LOCATION;
@Mixin(Screen.class)
public abstract class ScreenMixin {
@Shadow protected abstract <T extends Element & Drawable & Selectable> T addDrawableChild(T drawableElement);
@Shadow public int width;
@Inject(method = "init(Lnet/minecraft/client/MinecraftClient;II)V", at = @At("TAIL"))
public void midnightcontrols$addCloseButton(MinecraftClient client, int width, int height, CallbackInfo ci) {
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && (MidnightControlsConfig.closeButtonScreens.stream().anyMatch(s -> this.getClass().getName().startsWith(s) || ((Object)this) instanceof HandledScreen<?>))) {
this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(this.width - 30, 10), 20, 20, Text.empty(), btn ->
InputHandlers.handleExit().press(client, ButtonBinding.BACK, 0f, ButtonState.PRESS), 20, 160, 20, WIDGETS_LOCATION));
}
}
}

View File

@@ -10,8 +10,12 @@
package eu.midnightdust.midnightcontrols.client.mixin; package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.lib.util.MidnightColorUtil; import eu.midnightdust.lib.util.MidnightColorUtil;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.enums.TouchMode;
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*; import net.minecraft.client.render.*;
@@ -21,14 +25,17 @@ import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemUsageContext; import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult; import net.minecraft.util.hit.HitResult;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.awt.*; import java.awt.*;
@@ -54,6 +61,13 @@ public abstract class WorldRendererMixin {
@Shadow @Shadow
private static void drawCuboidShapeOutline(MatrixStack matrices, VertexConsumer vertexConsumer, VoxelShape shape, double offsetX, double offsetY, double offsetZ, float red, float green, float blue, float alpha) { private static void drawCuboidShapeOutline(MatrixStack matrices, VertexConsumer vertexConsumer, VoxelShape shape, double offsetX, double offsetY, double offsetZ, float red, float green, float blue, float alpha) {
} }
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"))
private HitResult.Type dontRenderOutline(HitResult instance) {
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
return HitResult.Type.MISS;
}
return instance.getType();
}
@Inject( @Inject(
method = "render", method = "render",
@@ -66,6 +80,32 @@ public abstract class WorldRendererMixin {
) )
private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer,
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) { LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN)
&& MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
this.renderFingerOutline(matrices, camera);
}
this.renderReacharoundOutline(matrices, camera);
}
@Unique
private void renderFingerOutline(MatrixStack matrices, Camera camera) {
if (TouchInput.firstHitResult == null || TouchInput.firstHitResult.getType() != HitResult.Type.BLOCK)
return;
BlockHitResult result = (BlockHitResult) TouchInput.firstHitResult;
var blockPos = result.getBlockPos();
if (this.world.getWorldBorder().contains(blockPos) && this.client.player != null) {
var outlineShape = this.world.getBlockState(blockPos).getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
Color rgb = MidnightColorUtil.hex2Rgb(MidnightControlsConfig.touchOutlineColorHex);
if (MidnightControlsConfig.touchOutlineColorHex.isEmpty()) rgb = RainbowColor.radialRainbow(1,1);
var pos = camera.getPos();
matrices.push();
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
drawCuboidShapeOutline(matrices, vertexConsumer, outlineShape, blockPos.getX() - pos.getX(), blockPos.getY() - pos.getY(), blockPos.getZ() - pos.getZ(),
rgb.getRed() / 255.f, rgb.getGreen() / 255.f, rgb.getBlue() / 255.f, MidnightControlsConfig.touchOutlineColorAlpha / 255.f);
matrices.pop();
}
}
@Unique
private void renderReacharoundOutline(MatrixStack matrices, Camera camera) {
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !MidnightControlsConfig.shouldRenderReacharoundOutline) if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !MidnightControlsConfig.shouldRenderReacharoundOutline)
return; return;
var result = MidnightControlsClient.get().reacharound.getLastReacharoundResult(); var result = MidnightControlsClient.get().reacharound.getLastReacharoundResult();
@@ -90,7 +130,7 @@ public abstract class WorldRendererMixin {
var outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity())); var outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
Color rgb = MidnightColorUtil.hex2Rgb(MidnightControlsConfig.reacharoundOutlineColorHex); Color rgb = MidnightColorUtil.hex2Rgb(MidnightControlsConfig.reacharoundOutlineColorHex);
if (MidnightControlsConfig.reacharoundOutlineColorHex.isEmpty()) rgb = MidnightColorUtil.radialRainbow(1,1); if (MidnightControlsConfig.reacharoundOutlineColorHex.isEmpty()) rgb = RainbowColor.radialRainbow(1,1);
matrices.push(); matrices.push();
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines()); var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines());
drawCuboidShapeOutline(matrices, vertexConsumer, outlineShape, drawCuboidShapeOutline(matrices, vertexConsumer, outlineShape,

View File

@@ -10,16 +10,13 @@
package eu.midnightdust.midnightcontrols.client.ring; package eu.midnightdust.midnightcontrols.client.ring;
import com.electronwill.nightconfig.core.Config; import com.electronwill.nightconfig.core.Config;
import eu.midnightdust.midnightcontrols.client.ButtonState; import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor; import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.option.StickyKeyBinding;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.OrderedText; import net.minecraft.text.OrderedText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View File

@@ -0,0 +1,104 @@
package eu.midnightdust.midnightcontrols.client.touch;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import static eu.midnightdust.midnightcontrols.client.MidnightControlsConfig.doMixedInput;
public class TouchInput {
private static final MinecraftClient client = MinecraftClient.getInstance();
public static long clickStartTime;
public static HitResult firstHitResult = null;
public static void tick() {
if ((client.currentScreen == null && doMixedInput()) || client.currentScreen instanceof TouchscreenOverlay) {
double scaleFactor = client.getWindow().getScaleFactor();
if (clickStartTime > 0 && System.currentTimeMillis() - clickStartTime >= MidnightControlsConfig.touchBreakDelay) {
mouseHeldDown(client.mouse.getX() / scaleFactor, client.mouse.getY() / scaleFactor);
}
}
}
public static void mouseHeldDown(double mouseX, double mouseY) {
assert client != null;
assert client.player != null;
assert client.interactionManager != null;
if (client.player.getMainHandStack() != null && TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())) {
client.interactionManager.interactItem(client.player, client.player.getActiveHand());
return;
}
HitResult result = TouchUtils.getTargettedObject(mouseX, mouseY);
if (result == null || firstHitResult == null) {
client.interactionManager.cancelBlockBreaking();
return;
}
if (result instanceof BlockHitResult blockHit && firstHitResult instanceof BlockHitResult firstBlock && blockHit.getBlockPos().equals(firstBlock.getBlockPos())) {
if (MidnightControlsConfig.debug) System.out.println(blockHit.getBlockPos().toString());
if (client.interactionManager.updateBlockBreakingProgress(blockHit.getBlockPos(), blockHit.getSide())) {
client.particleManager.addBlockBreakingParticles(blockHit.getBlockPos(), blockHit.getSide());
client.player.swingHand(Hand.MAIN_HAND);
} else client.interactionManager.cancelBlockBreaking();
firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
}
else if (result instanceof EntityHitResult entityHit && firstHitResult instanceof EntityHitResult firstEntity && entityHit.getEntity().getUuid().compareTo(firstEntity.getEntity().getUuid()) == 0) {
if (client.interactionManager.interactEntity(client.player, entityHit.getEntity(), client.player.getActiveHand()) == ActionResult.SUCCESS) {
client.player.swingHand(Hand.MAIN_HAND);
}
firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
}
}
public static boolean mouseReleased(double mouseX, double mouseY, int button) {
firstHitResult = null;
if (client.interactionManager != null) client.interactionManager.cancelBlockBreaking();
if ((client.currentScreen == null || !client.currentScreen.mouseReleased(mouseX, mouseY, button)) && System.currentTimeMillis() - clickStartTime < MidnightControlsConfig.touchBreakDelay) {
assert client.player != null;
assert client.world != null;
assert client.interactionManager != null;
clickStartTime = -1;
if (client.player.getMainHandStack() != null && TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())) {
client.interactionManager.stopUsingItem(client.player);
return true;
}
HitResult result = TouchUtils.getTargettedObject(mouseX, mouseY);
if (result == null) return false;
if (result instanceof BlockHitResult blockHit) {
BlockPos blockPos = blockHit.getBlockPos().offset(blockHit.getSide());
BlockState state = client.world.getBlockState(blockPos);
if (client.world.isAir(blockPos) || state.isReplaceable()) {
ItemStack stackInHand = client.player.getMainHandStack();
int previousStackCount = stackInHand.getCount();
var interaction = client.interactionManager.interactBlock(client.player, client.player.getActiveHand(), blockHit);
if (interaction.isAccepted()) {
if (interaction.shouldSwingHand()) {
client.player.swingHand(client.player.preferredHand);
if (!stackInHand.isEmpty() && (stackInHand.getCount() != previousStackCount || client.interactionManager.hasCreativeInventory())) {
client.gameRenderer.firstPersonRenderer.resetEquipProgress(client.player.preferredHand);
}
}
return true;
}
}
}
if (result instanceof EntityHitResult entityHit) {
client.interactionManager.attackEntity(client.player, entityHit.getEntity());
client.player.swingHand(Hand.MAIN_HAND);
return true;
}
}
clickStartTime = -1;
return false;
}
}

View File

@@ -0,0 +1,68 @@
package eu.midnightdust.midnightcontrols.client.touch;
import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.enums.TouchMode;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.entity.projectile.ProjectileUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.util.UseAction;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.RaycastContext;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL11;
import static eu.midnightdust.midnightcontrols.client.MidnightReacharound.getPlayerRange;
public class TouchUtils {
private static final MinecraftClient client = MinecraftClient.getInstance();
public static final Matrix4f lastWorldSpaceMatrix = new Matrix4f();
public static final Matrix4f lastProjMat = new Matrix4f();
public static final Matrix4f lastModMat = new Matrix4f();
public static HitResult getTargettedObject(double mouseX, double mouseY) {
if (MidnightControlsConfig.touchMode == TouchMode.CROSSHAIR || PlatformFunctions.isModLoaded("vulkanmod")) {
return client.crosshairTarget;
}
Vec3d near = screenSpaceToWorldSpace(mouseX, mouseY, 0);
Vec3d far = screenSpaceToWorldSpace(mouseX, mouseY, 1);
EntityHitResult entityCast = ProjectileUtil.raycast(client.player, near, far, Box.from(client.player.getPos()).expand(getPlayerRange(client)), entity -> (!entity.isSpectator() && entity.isAttackable()), getPlayerRange(client) * getPlayerRange(client));
if (entityCast != null && entityCast.getType() == HitResult.Type.ENTITY) return entityCast;
BlockHitResult result = client.world.raycast(new RaycastContext(near, far, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.ANY, client.player));
if (client.player.getPos().distanceTo(result.getPos()) > getPlayerRange(client)) return null;
return result;
}
/* Taken from https://github.com/0x3C50/Renderer/blob/master/src/main/java/me/x150/renderer/util/RendererUtils.java#L270
* Credits to 0x3C50 */
public static Vec3d screenSpaceToWorldSpace(double x, double y, double d) {
Camera camera = client.getEntityRenderDispatcher().camera;
int displayHeight = client.getWindow().getScaledHeight();
int displayWidth = client.getWindow().getScaledWidth();
int[] viewport = new int[4];
GL11.glGetIntegerv(GL11.GL_VIEWPORT, viewport);
Vector3f target = new Vector3f();
Matrix4f matrixProj = new Matrix4f(lastProjMat);
Matrix4f matrixModel = new Matrix4f(lastModMat);
matrixProj.mul(matrixModel)
.mul(lastWorldSpaceMatrix)
.unproject((float) x / displayWidth * viewport[2],
(float) (displayHeight - y) / displayHeight * viewport[3], (float) d, viewport, target);
return new Vec3d(target.x, target.y, target.z).add(camera.getPos());
}
public static boolean hasInWorldUseAction(ItemStack stack) {
UseAction action = stack.getUseAction();
return action == UseAction.BOW || action == UseAction.BRUSH || action == UseAction.SPEAR;
}
}

View File

@@ -0,0 +1,43 @@
package eu.midnightdust.midnightcontrols.client.touch.gui;
import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.PotionItem;
import net.minecraft.text.Text;
import net.minecraft.util.UseAction;
public class ItemUseButtonWidget extends SpruceButtonWidget {
public ItemUseButtonWidget(Position position, int width, int height, Text message, PressAction action) {
super(position, width, height, message, action);
}
@Override
protected void onRelease(double mouseX, double mouseY) {
assert client.player != null;
assert client.interactionManager != null;
UseAction action = client.player.getMainHandStack().getUseAction();
if (action == UseAction.SPYGLASS || action == UseAction.TOOT_HORN) client.interactionManager.stopUsingItem(client.player);
super.onRelease(mouseX, mouseY);
}
@Override
public void setVisible(boolean visible) {
if (visible && client.player != null && client.player.getMainHandStack() != null) {
UseAction action = client.player.getMainHandStack().getUseAction();
if (action == UseAction.EAT) {
this.setMessage(Text.translatable(MidnightControlsConstants.NAMESPACE+".action.eat"));
} else if (action == UseAction.DRINK) {
this.setMessage(Text.translatable(MidnightControlsConstants.NAMESPACE+".action.drink"));
} else if (client.player.getMainHandStack().getItem() instanceof ArmorItem) {
this.setMessage(Text.translatable(MidnightControlsConstants.NAMESPACE+".action.equip"));
} else if (!action.equals(UseAction.NONE)) {
this.setMessage(Text.translatable(MidnightControlsConstants.NAMESPACE+".action.use"));
}
}
this.setAlpha(MidnightControlsConfig.touchTransparency / 100f);
super.setVisible(visible);
}
}

View File

@@ -1,4 +1,4 @@
package eu.midnightdust.midnightcontrols.client.gui.widget; package eu.midnightdust.midnightcontrols.client.touch.gui;
import dev.lambdaurora.spruceui.Position; import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.widget.SpruceTexturedButtonWidget; import dev.lambdaurora.spruceui.widget.SpruceTexturedButtonWidget;
@@ -23,4 +23,17 @@ public class SilentTexturedButtonWidget extends SpruceTexturedButtonWidget {
} }
@Override @Override
public void playDownSound() {} public void playDownSound() {}
@Override
protected void onRelease(double mouseX, double mouseY) {
this.setActive(false);
super.onClick(mouseX, mouseY);
super.onRelease(mouseX, mouseY);
this.setActive(true);
}
@Override
public void onClick(double mouseX, double mouseY) {
this.setActive(true);
super.onClick(mouseX, mouseY);
this.setActive(false);
}
} }

View File

@@ -0,0 +1,23 @@
package eu.midnightdust.midnightcontrols.client.util;
import net.minecraft.util.math.MathHelper;
public class MathUtil {
public static class PolarUtil {
public float polarX;
public float polarY;
public PolarUtil() {}
public void calculate(float x, float y, float speedFactor) {
calculate(x, y, speedFactor, 0);
}
public void calculate(float x, float y, float speedFactor, double deadZone) {
double inputR = Math.pow(x, 2) + Math.pow(y, 2);
inputR = (Math.abs(speedFactor * MathHelper.clamp(inputR,0.f,1.f)));
inputR = inputR < deadZone ? 0f : (inputR-deadZone) / (1f-deadZone);
double inputTheta = Math.atan2(y, x);
polarX = (float) (inputR *Math.cos(inputTheta));
polarY = (float) (inputR *Math.sin(inputTheta));
}
}
}

View File

@@ -0,0 +1,15 @@
package eu.midnightdust.midnightcontrols.client.util;
import java.awt.*;
public class RainbowColor {
public static float hue;
public static void tick() {
if (hue > 1) hue = 0f;
hue = hue + 0.01f;
}
public static Color radialRainbow(float saturation, float brightness) {
return Color.getHSBColor(hue, saturation, brightness);
}
}

View File

@@ -16,9 +16,13 @@
"midnightcontrols.midnightconfig.enum.ControllerType.NUMBERED": "Numbered Controller", "midnightcontrols.midnightconfig.enum.ControllerType.NUMBERED": "Numbered Controller",
"midnightcontrols.midnightconfig.enum.ControlsMode.DEFAULT": "Keyboard/Mouse", "midnightcontrols.midnightconfig.enum.ControlsMode.DEFAULT": "Keyboard/Mouse",
"midnightcontrols.midnightconfig.enum.ControlsMode.CONTROLLER": "Controller", "midnightcontrols.midnightconfig.enum.ControlsMode.CONTROLLER": "Controller",
"midnightcontrols.midnightconfig.enum.ControlsMode.TOUCHSCREEN": "Touchscreen (WIP)", "midnightcontrols.midnightconfig.enum.ControlsMode.TOUCHSCREEN": "Touchscreen (Beta)",
"midnightcontrols.midnightconfig.enum.HudSide.LEFT": "Left", "midnightcontrols.midnightconfig.enum.HudSide.LEFT": "Left",
"midnightcontrols.midnightconfig.enum.HudSide.RIGHT": "Right", "midnightcontrols.midnightconfig.enum.HudSide.RIGHT": "Right",
"midnightcontrols.midnightconfig.enum.TouchMode.CROSSHAIR": "At Crosshair",
"midnightcontrols.midnightconfig.enum.TouchMode.FINGER_POS": "Finger Position",
"midnightcontrols.midnightconfig.enum.CameraMode.FLAT": "Flat",
"midnightcontrols.midnightconfig.enum.CameraMode.ADAPTIVE": "Adaptive",
"key.midnightcontrols.look_down": "Look down", "key.midnightcontrols.look_down": "Look down",
"key.midnightcontrols.look_left": "Look left", "key.midnightcontrols.look_left": "Look left",
"key.midnightcontrols.look_right": "Look right", "key.midnightcontrols.look_right": "Look right",
@@ -30,6 +34,9 @@
"midnightcontrols.action.controls_ring": "Open Unbound Keybind Ring", "midnightcontrols.action.controls_ring": "Open Unbound Keybind Ring",
"midnightcontrols.action.debug_screen": "Open Debug HUD (F3)", "midnightcontrols.action.debug_screen": "Open Debug HUD (F3)",
"midnightcontrols.action.drop_item": "Drop Item", "midnightcontrols.action.drop_item": "Drop Item",
"midnightcontrols.action.drink": "Drink",
"midnightcontrols.action.eat": "Eat",
"midnightcontrols.action.equip": "Equip",
"midnightcontrols.action.exit": "Exit Screen", "midnightcontrols.action.exit": "Exit Screen",
"midnightcontrols.action.forward": "Forward", "midnightcontrols.action.forward": "Forward",
"midnightcontrols.action.hit": "Hit", "midnightcontrols.action.hit": "Hit",
@@ -121,13 +128,14 @@
"midnightcontrols.controller_type.numbered": "Numbered Controller", "midnightcontrols.controller_type.numbered": "Numbered Controller",
"midnightcontrols.controls_mode.default": "Keyboard/Mouse", "midnightcontrols.controls_mode.default": "Keyboard/Mouse",
"midnightcontrols.controls_mode.controller": "Controller", "midnightcontrols.controls_mode.controller": "Controller",
"midnightcontrols.controls_mode.touchscreen": "Touchscreen (WIP)", "midnightcontrols.controls_mode.touchscreen": "Touchscreen (Beta)",
"midnightcontrols.hud_side.left": "Left", "midnightcontrols.hud_side.left": "Left",
"midnightcontrols.hud_side.right": "Right", "midnightcontrols.hud_side.right": "Right",
"midnightcontrols.menu.analog_movement": "Analog Movement", "midnightcontrols.menu.analog_movement": "Analog Movement",
"midnightcontrols.menu.analog_movement.tooltip": "When possible, enables analog movement.", "midnightcontrols.menu.analog_movement.tooltip": "When possible, enables analog movement.",
"midnightcontrols.menu.auto_switch_mode": "Auto Switch Mode", "midnightcontrols.menu.auto_switch_mode": "Auto Switch Mode",
"midnightcontrols.menu.auto_switch_mode.tooltip": "Whether the controls mode should be switched to Controller automatically if one is connected.", "midnightcontrols.menu.auto_switch_mode.tooltip": "Whether the controls mode should be switched to Controller automatically if one is connected.",
"midnightcontrols.menu.camera_mode": "Camera Mode",
"midnightcontrols.menu.controller": "Controller", "midnightcontrols.menu.controller": "Controller",
"midnightcontrols.menu.controller2": "Second Controller", "midnightcontrols.menu.controller2": "Second Controller",
"midnightcontrols.menu.controller2.tooltip": "Second controller to use, which allows (for example) Joy-Cons support.", "midnightcontrols.menu.controller2.tooltip": "Second controller to use, which allows (for example) Joy-Cons support.",
@@ -195,7 +203,14 @@
"midnightcontrols.menu.title.general": "General Options", "midnightcontrols.menu.title.general": "General Options",
"midnightcontrols.menu.title.hud": "HUD Options", "midnightcontrols.menu.title.hud": "HUD Options",
"midnightcontrols.menu.title.mappings.string": "Mappings File Editor", "midnightcontrols.menu.title.mappings.string": "Mappings File Editor",
"midnightcontrols.menu.title.touch": "Touch Options",
"midnightcontrols.menu.title.visual": "Appearance Options", "midnightcontrols.menu.title.visual": "Appearance Options",
"midnightcontrols.menu.touch_break_delay": "Touch Break Delay",
"midnightcontrols.menu.touch_speed": "Touch Speed",
"midnightcontrols.menu.invert_touch": "Invert Touch Direction",
"midnightcontrols.menu.touch_mode": "Touch Interaction Mode",
"midnightcontrols.menu.touch_transparency": "Touch HUD Transparency",
"midnightcontrols.menu.touch_with_controller": "Touch in Controller mode",
"midnightcontrols.menu.unfocused_input": "Unfocused Input", "midnightcontrols.menu.unfocused_input": "Unfocused Input",
"midnightcontrols.menu.unfocused_input.tooltip": "Allows controller input when the window is not focused.", "midnightcontrols.menu.unfocused_input.tooltip": "Allows controller input when the window is not focused.",
"midnightcontrols.menu.virtual_mouse": "Virtual Mouse", "midnightcontrols.menu.virtual_mouse": "Virtual Mouse",
@@ -213,6 +228,7 @@
"midnightcontrols.midnightconfig.category.misc": "Miscellaneous", "midnightcontrols.midnightconfig.category.misc": "Miscellaneous",
"midnightcontrols.midnightconfig.category.screens": "Screens", "midnightcontrols.midnightconfig.category.screens": "Screens",
"midnightcontrols.midnightconfig.category.gameplay": "Gameplay", "midnightcontrols.midnightconfig.category.gameplay": "Gameplay",
"midnightcontrols.midnightconfig.category.touch": "Touch",
"midnightcontrols.midnightconfig.category.visual": "Visual", "midnightcontrols.midnightconfig.category.visual": "Visual",
"modmenu.descriptionTranslation.midnightcontrols": "Adds controller support and enhanced controls overall.\nForked from LambdaControls, which sadly got discontinued." "modmenu.descriptionTranslation.midnightcontrols": "Adds controller support and enhanced controls overall.\nForked from LambdaControls, which sadly got discontinued."
} }

View File

@@ -1,5 +1,24 @@
{ {
"midnightcontrols.midnightconfig.title": "MidnightControls 고급 설정", "midnightcontrols.midnightconfig.title": "MidnightControls 고급 설정",
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_LIGHT": "기본 밝게",
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_DARK": "기본 어둡게",
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_LIGHT": "두 번째 밝게",
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_DARK": "두 번째 어둡게",
"midnightcontrols.midnightconfig.enum.ControllerType.DEFAULT": "기본값값",
"midnightcontrols.midnightconfig.enum.ControllerType.DUALSHOCK": "듀얼쇼크",
"midnightcontrols.midnightconfig.enum.ControllerType.DUALSENSE": "듀얼센스",
"midnightcontrols.midnightconfig.enum.ControllerType.SWITCH": "Switch/Wii 컨트롤러",
"midnightcontrols.midnightconfig.enum.ControllerType.XBOX": "엑스박스 원/시리즈 컨트롤러",
"midnightcontrols.midnightconfig.enum.ControllerType.XBOX_360": "엑스박스 360 컨트롤러",
"midnightcontrols.midnightconfig.enum.ControllerType.STEAM_CONTROLLER": "스팀 컨트롤러",
"midnightcontrols.midnightconfig.enum.ControllerType.STEAM_DECK": "스팀 덱",
"midnightcontrols.midnightconfig.enum.ControllerType.OUYA": "OUYA 컨트롤러",
"midnightcontrols.midnightconfig.enum.ControllerType.NUMBERED": "숫자 컨트롤러",
"midnightcontrols.midnightconfig.enum.ControlsMode.DEFAULT": "키보드/마우스",
"midnightcontrols.midnightconfig.enum.ControlsMode.CONTROLLER": "컨트롤러",
"midnightcontrols.midnightconfig.enum.ControlsMode.TOUCHSCREEN": "터치스크린 (미완성)",
"midnightcontrols.midnightconfig.enum.HudSide.LEFT": "왼쪽",
"midnightcontrols.midnightconfig.enum.HudSide.RIGHT": "오른쪽",
"key.midnightcontrols.look_down": "아래쪽 보기", "key.midnightcontrols.look_down": "아래쪽 보기",
"key.midnightcontrols.look_left": "왼쪽 보기", "key.midnightcontrols.look_left": "왼쪽 보기",
"key.midnightcontrols.look_right": "오른쪽 보기", "key.midnightcontrols.look_right": "오른쪽 보기",
@@ -8,6 +27,7 @@
"midnightcontrols.action.attack": "공격", "midnightcontrols.action.attack": "공격",
"midnightcontrols.action.back": "뒤로", "midnightcontrols.action.back": "뒤로",
"midnightcontrols.action.chat": "채팅 열기", "midnightcontrols.action.chat": "채팅 열기",
"midnightcontrols.action.debug_screen": "디버그 HUD 열기 (F3)",
"midnightcontrols.action.drop_item": "아이템 버리기", "midnightcontrols.action.drop_item": "아이템 버리기",
"midnightcontrols.action.exit": "종료", "midnightcontrols.action.exit": "종료",
"midnightcontrols.action.forward": "앞으로", "midnightcontrols.action.forward": "앞으로",
@@ -150,9 +170,9 @@
"midnightcontrols.menu.rotation_speed.tooltip": "컨트롤러 모드에서 적용되는 카메라 회전 속도.", "midnightcontrols.menu.rotation_speed.tooltip": "컨트롤러 모드에서 적용되는 카메라 회전 속도.",
"midnightcontrols.menu.unfocused_input.tooltip": "창이 활성화된 상태가 아니여도 컨트롤러 입력 허용.", "midnightcontrols.menu.unfocused_input.tooltip": "창이 활성화된 상태가 아니여도 컨트롤러 입력 허용.",
"midnightcontrols.menu.virtual_mouse.tooltip": "분할 화면에선 도움 되는 가상 마우스를 사용합니다.", "midnightcontrols.menu.virtual_mouse.tooltip": "분할 화면에선 도움 되는 가상 마우스를 사용합니다.",
"midnightcontrols.virtual_mouse.skin.default_light": "기본 라이트", "midnightcontrols.virtual_mouse.skin.default_light": "기본 밝게",
"midnightcontrols.virtual_mouse.skin.default_dark": "기본 다크", "midnightcontrols.virtual_mouse.skin.default_dark": "기본 어둡게",
"midnightcontrols.virtual_mouse.skin.second_light": "두 번째 라이트", "midnightcontrols.virtual_mouse.skin.second_light": "두 번째 밝게",
"midnightcontrols.virtual_mouse.skin.second_dark": "두 번째 다크", "midnightcontrols.virtual_mouse.skin.second_dark": "두 번째 어둡게",
"modmenu.descriptionTranslation.midnightcontrols": "컨트롤러 제어 및 전반적인 향상된 제어 기능을 추가합니다.\n안타깝게도 업데이트가 끊긴 LambdaControls의 Fork 버전입니다." "modmenu.descriptionTranslation.midnightcontrols": "컨트롤러 제어 및 전반적인 향상된 제어 기능을 추가합니다.\n안타깝게도 업데이트가 끊긴 LambdaControls의 Fork 버전입니다."
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

View File

@@ -8,21 +8,20 @@
"ClientPlayerEntityMixin", "ClientPlayerEntityMixin",
"ControlsOptionsScreenMixin", "ControlsOptionsScreenMixin",
"CreativeInventoryScreenAccessor", "CreativeInventoryScreenAccessor",
"EntryListWidgetAccessor",
"GameOptionsMixin",
"GameRendererMixin", "GameRendererMixin",
"HandledScreenMixin", "HandledScreenMixin",
"KeyBindingMixin", "KeyBindingMixin",
"InputUtilMixin", "InputUtilMixin",
"MinecraftClientMixin", "MinecraftClientMixin",
"MouseMixin", "MouseMixin",
"MouseAccessor",
"ChatScreenMixin", "ChatScreenMixin",
"RecipeBookWidgetAccessor", "RecipeBookWidgetAccessor",
"WorldRendererMixin", "WorldRendererMixin",
"KeyBindingRegistryImplAccessor",
"KeyBindingIDAccessor", "KeyBindingIDAccessor",
"ScreenAccessor", "TabNavigationWidgetAccessor",
"TabNavigationWidgetAccessor" "ScreenMixin",
"KeyboardMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1