diff --git a/README.md b/README.md index 6a8071b..619844f 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,14 @@ Enter the folder created and run: ``` 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 [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== diff --git a/build.gradle b/build.gradle index fd5861e..62adb97 100644 --- a/build.gradle +++ b/build.gradle @@ -3,25 +3,14 @@ plugins { id 'java-library' id 'maven-publish' 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 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 +import net.darkhax.curseforgegradle.TaskPublishCurseForge group = project.maven_group version = "${project.mod_version}+${getMCVersionString()}" -archivesBaseName = project.archives_base_name // This field defines the Java version your mod target. def targetJavaVersion = 17 @@ -32,7 +21,7 @@ boolean isMCVersionNonRelease() { } String getMCVersionString() { - if (isMCVersionNonRelease() || project.minecraft_version == "1.19.4") { + if (isMCVersionNonRelease() || project.minecraft_version == "1.20.4") { return project.minecraft_version } def version = project.minecraft_version.split('\\.') @@ -159,115 +148,39 @@ processResources { expand 'version': project.version } } - -task publishModrinth(type: TaskModrinthUpload) { - dependsOn(build) - onlyIf { - System.getenv('MODRINTH_TOKEN') - } - - token = System.getenv('MODRINTH_TOKEN') - projectId = project.modrinth_id - versionNumber = version - versionName = "midnightcontrols ${project.mod_version} (${getMCVersionString()})" - addGameVersion((String) project.minecraft_version) - addLoader('fabric') - versionType = isMCVersionNonRelease() ? VersionType.BETA : VersionType.RELEASE - - // Changelog fetching - def changelogText = file('CHANGELOG.md').text - def regexVersion = ((String) project.mod_version).replaceAll('\\.', /\\./).replaceAll('\\+', '\\+') - def changelogRegex = ~"###? ${regexVersion}\\n\\n(( *- .+\\n)+)" - def matcher = changelogText =~ changelogRegex - - if (matcher.find()) { - changelog = matcher.group(1) - - def changelogLines = changelogText.split('\n') - def linkRefRegex = ~'^\\[([A-z0-9 _\\-/+.]+)]: ' - for (int i = changelogLines.length - 1; i > 0; i--) { - def line = changelogLines[i] - if ((line =~ linkRefRegex).find()) - changelog += '\n' + line - else break - } - } - - // Readme - doFirst { - final def client = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build() - final def patch = new HttpPatch((String) (apiURL + '/v1/mod/' + projectId)) - patch.addHeader("Authorization", token) - - var json = new JsonObject() - json.addProperty("body", parseReadme()) - patch.setEntity(EntityBuilder.create() - .setText(json.toString()) - .setContentType(ContentType.APPLICATION_JSON) - .build()) - - final def response = client.execute(patch) - final int status = response.getStatusLine().getStatusCode() - - final def gson = new GsonBuilder().create() - if (status == 200) { - project.getLogger().lifecycle("Successfully updated readme to ${projectId}.") - } else { - errorInfo = gson.fromJson(EntityUtils.toString(response.getEntity()), ResponseError.class) - project.getLogger().error("Upload failed! Status: ${status} Error: ${errorInfo.getError()} Reason: ${errorInfo.getDescription()}") - throw new GradleException("Upload failed! Status: ${status} Reason: ${errorInfo.getDescription()}") - } +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) { -// configure the maven publication -publishing { - publications { - mavenJava(MavenPublication) { - artifact(sourcesJar) { - builtBy remapSourcesJar - } + // This token is used to authenticate with CurseForge. It should be handled + // with the same level of care and security as your actual password. You + // should never share your token with an untrusted source or publish it + // publicly to GitHub or embed it within a project. The best practice is to + // store this token in an environment variable or a build secret. + apiToken = System.getenv("CURSEFORGE_TOKEN") - 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') - } - } - } - } + // Tells CurseForgeGradle to publish the output of the jar task. This will + // return a UploadArtifact object that can be used to further configure the + // file. + def mainFile = upload(project.curseforge_id, remapJar) + mainFile.changelog = project.changelog + mainFile.displayName = "MidnightControls " + project.mod_version + " - " + project.minecraft_version + mainFile.addModLoader("Fabric", "Quilt") + mainFile.addRequirement("midnightlib") + mainFile.releaseType = "release" } diff --git a/gradle.properties b/gradle.properties index 345fac7..8581208 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,22 +3,24 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use -minecraft_version=1.20 -yarn_mappings=1.20+build.1 -loader_version=0.14.21 +minecraft_version=1.20.4 +yarn_mappings=1.20.4+build.3 +loader_version=0.15.3 # Mod Properties -mod_version = 1.8.2 +mod_version = 1.9.3 maven_group = eu.midnightdust archives_base_name = midnightcontrols -modrinth_id=bXX9h73M +modrinth_id = bXX9h73M +curseforge_id = 621768 +changelog = See changes at: https://github.com/TeamMidnightDust/MidnightControls/commits/ # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api -fabric_version=0.83.0+1.20 +fabric_version=0.91.3+1.20.4 sodium_version=mc1.19.2-0.4.4 -spruceui_version=5.0.0+1.20 -midnightlib_version=1.4.1-fabric +spruceui_version=5.0.3+1.20.4 +midnightlib_version=1.5.3-fabric modmenu_version=7.0.0 emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric bendylib_version=2.0.+ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927..d64cd49 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 00e33ed..1af9e09 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787..1aa94a4 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java index a742b0f..1b318fd 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java @@ -10,12 +10,12 @@ package eu.midnightdust.midnightcontrols.client; import dev.lambdaurora.spruceui.event.OpenScreenCallback; +import eu.midnightdust.lib.util.PlatformFunctions; import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.MidnightControls; import eu.midnightdust.midnightcontrols.MidnightControlsConstants; import eu.midnightdust.midnightcontrols.MidnightControlsFeature; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; -import eu.midnightdust.midnightcontrols.client.compat.VoxelMapCompat; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory; 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.TouchscreenOverlay; 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.MidnightRing; 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.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; @@ -47,6 +48,7 @@ import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; import java.io.File; +import java.util.Objects; import java.util.Timer; import java.util.TimerTask; @@ -59,7 +61,6 @@ import java.util.TimerTask; */ public class MidnightControlsClient extends MidnightControls implements ClientModInitializer { public static boolean lateInitDone = false; - public static boolean voxelmapInitDone = false; private static MidnightControlsClient INSTANCE; 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"); @@ -122,20 +123,21 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight()); } }); + final MinecraftClient client = MinecraftClient.getInstance(); + int delay = 0; // delay for 0 sec. + int period = 1; // repeat every 0.001 sec. (100 times a second) + Timer timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + public void run() { + input.updateCamera(client); + } + }, delay, period); HudManager.register(this.hud = new MidnightControlsHud(this)); FabricLoader.getInstance().getModContainer("midnightcontrols").ifPresent(modContainer -> { ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","bedrock"), 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); Controller.updateMappings(); - GLFW.glfwSetJoystickCallback((jid, event) -> { - if (event == GLFW.GLFW_CONNECTED) { - var controller = Controller.byId(jid); - client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, Text.translatable("midnightcontrols.controller.connected", jid), - Text.literal(controller.getName()))); - } else if (event == GLFW.GLFW_DISCONNECTED) { - client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, Text.translatable("midnightcontrols.controller.disconnected", jid), - null)); - } + try { + GLFW.glfwSetJoystickCallback((jid, event) -> { + if (event == GLFW.GLFW_CONNECTED) { + var controller = Controller.byId(jid); + client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.connected", jid), + Text.literal(controller.getName()))); + } else if (event == GLFW.GLFW_DISCONNECTED) { + client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.disconnected", jid), + null)); + } - this.switchControlsMode(); - }); + this.switchControlsMode(); + }); + } catch (Exception e) {e.fillInStackTrace();} MidnightControlsCompat.init(this); } @@ -174,30 +178,28 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo * This method is called to initialize keybindings */ 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 (KeyBindingRegistryImplAccessor.getMODDED_KEY_BINDINGS() == null || KeyBindingRegistryImplAccessor.getMODDED_KEY_BINDINGS().isEmpty()) return; - for (int i = 0; i < KeyBindingRegistryImplAccessor.getMODDED_KEY_BINDINGS().size(); ++i) { - KeyBinding keyBinding = KeyBindingRegistryImplAccessor.getMODDED_KEY_BINDINGS().get(i); - if (!keyBinding.getTranslationKey().contains("midnightcontrols") && !keyBinding.getTranslationKey().contains("ok_zoomer") && !keyBinding.getTranslationKey().contains("okzoomer")) { - category = null; - InputManager.streamCategories().forEach(buttonCategory -> { - if (buttonCategory.getIdentifier().equals(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory()))) - category = buttonCategory; - }); - if (category == null) { - category = new ButtonCategory(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory())); - InputManager.registerCategory(category); - } - ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getTranslationKey()).category(category).linkKeybind(keyBinding).register(); - if (MidnightControlsConfig.debug) { - logger.info(keyBinding.getTranslationKey()); - logger.info(buttonBinding); + if (KeyBindingIDAccessor.getKEYS_BY_ID() == null || KeyBindingIDAccessor.getKEYS_BY_ID().isEmpty()) return; + if (PlatformFunctions.isModLoaded("voxelmap") && !KeyBindingIDAccessor.getKEYS_BY_ID().containsKey("key.minimap.toggleingamewaypoints")) return; + if (PlatformFunctions.isModLoaded("wynntils") && KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().noneMatch(b -> Objects.equals(b.getValue().getCategory(), "Wynntils"))) return; + for (int i = 0; i < KeyBindingIDAccessor.getKEYS_BY_ID().size(); ++i) { + KeyBinding keyBinding = KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().toList().get(i).getValue(); + if (MidnightControlsConfig.excludedKeybindings.stream().noneMatch(excluded -> keyBinding.getTranslationKey().startsWith(excluded))) { + if (!keyBinding.getTranslationKey().contains("midnightcontrols") && !keyBinding.getTranslationKey().contains("ok_zoomer") && !keyBinding.getTranslationKey().contains("okzoomer")) { + category = null; + InputManager.streamCategories().forEach(buttonCategory -> { + if (buttonCategory.getIdentifier().equals(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory()))) + category = buttonCategory; + }); + if (category == null) { + category = new ButtonCategory(new org.aperlambda.lambdacommon.Identifier("minecraft", keyBinding.getCategory())); + InputManager.registerCategory(category); + } + ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getTranslationKey()).category(category).linkKeybind(keyBinding).register(); + if (MidnightControlsConfig.debug) { + logger.info(keyBinding.getTranslationKey()); + logger.info(buttonBinding); + } } } } @@ -227,9 +229,8 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo MidnightControlsConfig.enableHints = false; MidnightControlsConfig.save(); } - } - public void onRender(MinecraftClient client) { - //this.input.onRender(client); + RainbowColor.tick(); + TouchInput.tick(); } /** diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java index 2476180..3ec8cd2 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java @@ -18,8 +18,15 @@ import eu.midnightdust.midnightcontrols.MidnightControlsFeature; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.InputManager; +import eu.midnightdust.midnightcontrols.client.enums.CameraMode; +import eu.midnightdust.midnightcontrols.client.enums.ControllerType; +import eu.midnightdust.midnightcontrols.client.enums.HudSide; +import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin; +import eu.midnightdust.midnightcontrols.client.gui.RingScreen; +import eu.midnightdust.midnightcontrols.client.enums.TouchMode; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; @@ -33,65 +40,87 @@ import static org.lwjgl.glfw.GLFW.*; * Represents MidnightControls configuration. */ public class MidnightControlsConfig extends MidnightConfig { + public static final String CONTROLLER = "controller"; + public static final String TOUCH = "touch"; + public static final String GAMEPLAY = "gameplay"; + public static final String SCREENS = "screens"; + public static final String VISUAL = "visual"; + public static final String MISC = "misc"; public static boolean isEditing = false; @Hidden @Entry public static int configVersion = 2; // General - @Entry(category = "controller", name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT; - @Entry(category = "controller", name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true; - @Entry(category = "misc", name = "Debug") public static boolean debug = false; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true; + @Entry(category = MISC, name = "Debug") public static boolean debug = false; // HUD - @Entry(category = "visual", name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true; - @Entry(category = "visual", name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT; - @Entry(category = "screens", name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false; + @Entry(category = VISUAL, name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true; + @Entry(category = VISUAL, name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT; + @Entry(category = SCREENS, name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false; // Gameplay - @Entry(category = "gameplay", name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true; - @Entry(category = "gameplay", name = "midnightcontrols.menu.double_tap_to_sprint") public static boolean doubleTapToSprint = true; - @Entry(category = "gameplay", name = "midnightcontrols.menu.controller_toggle_sneak") public static boolean controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue(); - @Entry(category = "gameplay", name = "midnightcontrols.menu.controller_toggle_sprint") public static boolean controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue(); - @Entry(category = "gameplay", name = "midnightcontrols.menu.fast_block_placing") public static boolean fastBlockPlacing = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. - @Entry(category = "gameplay", name = "midnightcontrols.menu.fly_drifting") public static boolean flyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. It can also conflict with some other mods. - @Entry(category = "gameplay", name = "midnightcontrols.menu.fly_drifting_vertical") public static boolean verticalFlyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. - @Entry(category = "gameplay", name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. - @Entry(category = "gameplay", name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. - @Entry(category = "visual", name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true; - @Entry(category = "visual", name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff"; - @Entry(category = "visual", name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102; - @Entry(category = "controller", name = "midnightcontrols.menu.right_dead_zone", isSlider = true, min = 0.05, max = 1) public static double rightDeadZone = 0.25; - @Entry(category = "controller", name = "midnightcontrols.menu.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.25; - @Entry(category = "controller", name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false; - @Entry(category = "controller", name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false; - @Entry(category = "controller", name = "midnightcontrols.menu.rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double rotationSpeed = 40.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 = "screens", name = "midnightcontrols.menu.mouse_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double mouseSpeed = 25.0; - @Entry(category = "screens", name = "midnightcontrols.menu.joystick_as_mouse") public static boolean joystickAsMouse = false; - @Entry(category = "screens", name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false; - @Entry(category = "screens", name = "midnightcontrols.menu.eye_tracker_deadzone", isSlider = true, min = 0, max = 0.4) public static double eyeTrackerDeadzone = 0.05; - @Entry(category = "controller", name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false; - @Entry(category = "screens", name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false; - @Entry(category = "screens", name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT; - @Entry(category = "screens", name = "midnightcontrols.menu.hide_cursor") public static boolean hideNormalMouse = false; - @Entry(category = "controller", name = "Controller ID") @Hidden public static Object controllerID = 0; - @Entry(category = "controller", name = "2nd Controller ID") @Hidden public static Object secondControllerID = -1; - @Entry(category = "visual", name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT; - @Entry(category = "screens", name = "Mouse screens") public static List mouseScreens = Lists.newArrayList("net.minecraft.client.gui.screen.advancement", + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true; + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.double_tap_to_sprint") public static boolean doubleTapToSprint = true; + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.controller_toggle_sneak") public static boolean controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue(); + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.controller_toggle_sprint") public static boolean controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue(); + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fast_block_placing") public static boolean fastBlockPlacing = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fly_drifting") public static boolean flyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. It can also conflict with some other mods. + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fly_drifting_vertical") public static boolean verticalFlyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. + @Entry(category = GAMEPLAY, name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. + @Entry(category = VISUAL, name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true; + @Entry(category = VISUAL, name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff"; + @Entry(category = VISUAL, name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.right_dead_zone", isSlider = true, min = 0.05, max = 1) public static double rightDeadZone = 0.25; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.25; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double rotationSpeed = 35.0; //used for x-axis, name kept for compatibility + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.y_axis_rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double yAxisRotationSpeed = rotationSpeed; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.camera_mode") public static CameraMode cameraMode = CameraMode.FLAT; + @Entry(category = SCREENS, name = "midnightcontrols.menu.mouse_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double mouseSpeed = 25.0; + @Entry(category = SCREENS, name = "midnightcontrols.menu.joystick_as_mouse") public static boolean joystickAsMouse = false; + @Entry(category = SCREENS, name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false; + @Entry(category = SCREENS, name = "midnightcontrols.menu.eye_tracker_deadzone", isSlider = true, min = 0, max = 0.4) public static double eyeTrackerDeadzone = 0.05; + @Entry(category = CONTROLLER, name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false; + @Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false; + @Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT; + @Entry(category = SCREENS, name = "midnightcontrols.menu.hide_cursor") public static boolean hideNormalMouse = false; + @Entry(category = CONTROLLER, name = "Controller ID") @Hidden public static Object controllerID = 0; + @Entry(category = CONTROLLER, name = "2nd Controller ID") @Hidden public static Object secondControllerID = -1; + @Entry(category = VISUAL, name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT; + @Entry(category = SCREENS, name = "Mouse screens") public static List mouseScreens = Lists.newArrayList("net.minecraft.client.gui.screen.advancement", "net.minecraft.class_457", "net.minecraft.class_408", "net.minecraft.class_3872", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen", "hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen", "me.shedaniel.clothconfig2.gui.ClothConfigScreen", "com.mamiyaotaru.voxelmap.gui.GuiWaypoints", "com.mamiyaotaru.voxelmap.gui.GuiPersistentMap"); - @Entry(category = "screens", name = "Arrow screens") public static List arrowScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName()); - @Entry(category = "screens", name = "WASD screens") public static List wasdScreens = Lists.newArrayList("com.ultreon.devices.core.Laptop"); + @Entry(category = SCREENS, name = "Arrow screens") public static List arrowScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName()); + @Entry(category = SCREENS, name = "WASD screens") public static List wasdScreens = Lists.newArrayList("com.ultreon.devices.core.Laptop"); + @Entry(category = TOUCH, name = "Screens with close button") public static List 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 leftTouchBinds = Lists.newArrayList("debug_screen", "screenshot","toggle_perspective"); + @Entry(category = TOUCH, name = "Right Touch button bindings") public static List rightTouchBinds = Lists.newArrayList("screenshot","toggle_perspective", "use"); + @Entry @Hidden public static Map BINDING = new HashMap<>(); private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?"); @Deprecated @Hidden @Entry public static double[] maxAnalogValues = new double[]{1, 1, 1, 1}; - @Entry(category = "controller", name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = maxAnalogValues[0]; - @Entry(category = "controller", name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = maxAnalogValues[1]; - @Entry(category = "controller", name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = maxAnalogValues[2]; - @Entry(category = "controller", name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = maxAnalogValues[3]; - @Entry(category = "controller", name = "Trigger button fix") public static boolean triggerFix = true; - @Entry(category = "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 ringBindings = new ArrayList<>(); - @Entry(category = "misc", name = "Ignored Unbound Keys") public static List ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab"); + @Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = maxAnalogValues[0]; + @Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = maxAnalogValues[1]; + @Entry(category = CONTROLLER, name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = maxAnalogValues[2]; + @Entry(category = CONTROLLER, name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = maxAnalogValues[3]; + @Entry(category = CONTROLLER, name = "Trigger button fix") public static boolean triggerFix = true; + @Entry(category = MISC, name = "Excluded Keybindings") public static List excludedKeybindings = Lists.newArrayList("key.forward", "key.left", "key.back", "key.right", "key.jump", "key.sneak", "key.sprint", "key.inventory", + "key.swapOffhand", "key.drop", "key.use", "key.attack", "key.chat", "key.playerlist", "key.screenshot", "key.togglePerspective", "key.smoothCamera", "key.fullscreen", "key.saveToolbarActivator", "key.loadToolbarActivator", + "key.pickItem", "key.hotbar.1", "key.hotbar.2", "key.hotbar.3", "key.hotbar.4", "key.hotbar.5", "key.hotbar.6", "key.hotbar.7", "key.hotbar.8", "key.hotbar.9"); + @Entry(category = GAMEPLAY, name = "Enable Hints") public static boolean enableHints = true; + @Entry(category = SCREENS, name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true; + @Entry(category = MISC, name = "Ring Bindings (WIP)") public static List ringBindings = new ArrayList<>(); + @Entry(category = MISC, name = "Ignored Unbound Keys") public static List ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab"); @Entry @Hidden public static Map> controllerBindingProfiles = new HashMap<>(); private static Map currentBindingProfile = new HashMap<>(); private static Controller prevController; @@ -375,4 +404,7 @@ public class MidnightControlsConfig extends MidnightConfig { else if (controller.contains("ouya")) return ControllerType.OUYA; else return ControllerType.DEFAULT; } + public static boolean doMixedInput() { + return touchInControllerMode && controlsMode == ControlsMode.CONTROLLER; + } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java index 8193ece..18ca643 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java @@ -17,12 +17,14 @@ import eu.midnightdust.midnightcontrols.client.compat.*; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.InputManager; +import eu.midnightdust.midnightcontrols.client.enums.CameraMode; import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget; import eu.midnightdust.midnightcontrols.client.mixin.*; import eu.midnightdust.midnightcontrols.client.ring.RingPage; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; +import eu.midnightdust.midnightcontrols.client.util.MathUtil; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import dev.lambdaurora.spruceui.navigation.NavigationDirection; 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.SpruceLabelWidget; import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget; +import eu.midnightdust.midnightcontrols.client.enums.ButtonState; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.ParentElement; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.advancement.AdvancementTab; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; 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.world.WorldListWidget; 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.text.TranslatableTextContent; import net.minecraft.util.math.MathHelper; @@ -151,8 +151,13 @@ public class MidnightInput { if (allowInput) InputManager.updateBindings(client); - if (this.controlsInput != null - && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) { + if (this.controlsInput != null) { + InputManager.STATES.forEach((num, button) -> { + if (button.isPressed()) System.out.println(num); + }); + } + if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) { + System.out.println("finished"); if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) { int[] buttons = new int[this.controlsInput.currentButtons.size()]; for (int i = 0; i < this.controlsInput.currentButtons.size(); i++) @@ -203,18 +208,8 @@ public class MidnightInput { } client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw); 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. @@ -266,12 +261,33 @@ public class MidnightInput { InputManager.STATES.put(btn, state); } } + MathUtil.PolarUtil polarLeft = new MathUtil.PolarUtil(); + MathUtil.PolarUtil polarRight = new MathUtil.PolarUtil(); private void fetchAxeInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) { var buffer = gamepadState.axes(); + + polarLeft.calculate(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X), buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y), 1, MidnightControlsConfig.leftDeadZone); + float leftX = polarLeft.polarX; + float leftY = polarLeft.polarY; + polarRight.calculate(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X), buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y), 1, MidnightControlsConfig.rightDeadZone); + float rightX = polarRight.polarX; + float rightY = polarRight.polarY; + for (int i = 0; i < buffer.limit(); i++) { int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i; float value = buffer.get(); + + if (MidnightControlsConfig.analogMovement) { + switch (i) { + case GLFW_GAMEPAD_AXIS_LEFT_X -> value = leftX; + case GLFW_GAMEPAD_AXIS_LEFT_Y -> value = leftY; + } + } + switch (i) { + case GLFW_GAMEPAD_AXIS_RIGHT_X -> value = rightX; + case GLFW_GAMEPAD_AXIS_RIGHT_Y -> value = rightY; + } float absValue = Math.abs(value); if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y) @@ -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))) { - float x = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X)) > MidnightControlsConfig.leftDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X) : 0; - float y = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y)) > MidnightControlsConfig.leftDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y) : 0; + float x = leftX; + float y = leftY; + 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; - y = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y)) > MidnightControlsConfig.rightDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y) : 0; + x = rightX; + y = rightY; } int index = -1; - if (x < 0) { - if (y < 0) index = 0; - if (y == 0) index = 3; - if (y > 0) index = 5; - } else if (x == 0) { - if (y < 0) index = 1; - if (y > 0) index = 6; - } else if (x > 0) { - if (y < 0) index = 2; - if (y == 0) index = 4; - if (y > 0) index = 7; + float border = 0.3f; + if (x < -border) { + index = 3; + if (y < -border) index = 0; + else if (y > border) index = 5; + } else if (x > border) { + index = 4; + if (y < -border) index = 2; + else if (y > border) index = 7; + } else { + if (y < -border) index = 1; + else if (y > border) index = 6; } if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index; if (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index); @@ -458,7 +476,6 @@ public class MidnightInput { private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) { int asButtonState = value > .5f ? 1 : (value < -.5f ? 2 : 0); - if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) { @@ -478,8 +495,13 @@ public class MidnightInput { } { - boolean currentPlusState = asButtonState == 1; - boolean currentMinusState = asButtonState == 2; + boolean currentPlusState = value > getDeadZoneValue(axis); + boolean currentMinusState = value < -getDeadZoneValue(axis); + if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER) currentMinusState = false; + if (!MidnightControlsConfig.analogMovement && (axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y)) { + currentPlusState = asButtonState == 1; + currentMinusState = asButtonState == 2; + } var previousPlusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, true), ButtonState.NONE); var previousMinusState = InputManager.STATES.getOrDefault(ButtonBinding.axisAsButton(axis, false), ButtonState.NONE); @@ -505,9 +527,13 @@ public class MidnightInput { } } - double deadZone = this.getDeadZoneValue(axis); - float axisValue = absValue < deadZone ? 0.f : (float) (absValue - deadZone); - axisValue /= (1.0 - deadZone); + float axisValue = absValue; + if (!MidnightControlsConfig.analogMovement) { + double deadZone = this.getDeadZoneValue(axis); + axisValue = (float) (absValue - deadZone); + axisValue /= (1.0 - deadZone); + axisValue *= deadZone; + } axisValue = (float) Math.min(axisValue / MidnightControlsConfig.getAxisMaxValue(axis), 1); if (currentPlusState) @@ -540,7 +566,7 @@ public class MidnightInput { var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen; // @TODO allow rebinding to left stick if (accessor.midnightcontrols$hasScrollbar() && absValue >= deadZone) { - creativeInventoryScreen.mouseScrolled(0.0, 0.0, -value); + creativeInventoryScreen.mouseScrolled(0.0, 0.0, 0, -value); } return; } @@ -548,7 +574,7 @@ public class MidnightInput { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { // @TODO allow rebinding to left stick if (absValue >= deadZone) { - merchantScreen.mouseScrolled(0.0, 0.0, -(value * 1.5f)); + merchantScreen.mouseScrolled(0.0, 0.0, 0, -(value * 1.5f)); } return; } @@ -556,7 +582,7 @@ public class MidnightInput { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { // @TODO allow rebinding to left stick if (absValue >= deadZone) { - stonecutterScreen.mouseScrolled(0.0, 0.0, -(value * 1.5f)); + stonecutterScreen.mouseScrolled(0.0, 0.0, 0, -(value * 1.5f)); } return; } @@ -575,7 +601,7 @@ public class MidnightInput { .map(element -> (SpruceEntryListWidget) element) .filter(AbstractSpruceWidget::isFocusedOrHovered) .noneMatch(element -> { - element.mouseScrolled(0.0, 0.0, -finalValue); + element.mouseScrolled(0.0, 0.0, 0, -finalValue); return true; }) && @@ -583,11 +609,11 @@ public class MidnightInput { .map(element -> (EntryListWidget) element) .filter(element -> element.getType().isFocused()) .noneMatch(element -> { - element.mouseScrolled(0.0, 0.0, -finalValue); + element.mouseScrolled(0.0, 0.0, 0, -finalValue); 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) { 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); if (client.currentScreen == null) { // Handles the look direction. @@ -756,6 +780,10 @@ public class MidnightInput { } return true; } + private double prevX = 0; + private double prevY = 0; + private double xValue; + private int xState; /** * Handles the look direction input. @@ -766,8 +794,9 @@ public class MidnightInput { * @param state the state */ public void handleLook(@NotNull MinecraftClient client, int axis, float value, int state) { + if (client.player == null) return; // Handles the look direction. - if (client.player != null) { + if (MidnightControlsConfig.cameraMode == CameraMode.FLAT) { double powValue = Math.pow(value, 2.0); if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { if (state == 2) { @@ -783,6 +812,43 @@ public class MidnightInput { this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D; } } + return; + } + // Code below runs for adaptive camera mode + + // Handles the look direction. + if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) { + xValue = value; + xState = state; + return; + } + if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y && client.player != null) { + double yStep = (MidnightControlsConfig.yAxisRotationSpeed / 100) * 0.6000000238418579 + 0.20000000298023224; + double xStep = (MidnightControlsConfig.rotationSpeed / 100) * 0.6000000238418579 + 0.20000000298023224; + + double cursorDeltaX = 2 * xValue - this.prevX; + double cursorDeltaY = 2 * value - this.prevY; + boolean slowdown = client.options.getPerspective().isFirstPerson() && client.player.isUsingSpyglass(); + double x = cursorDeltaX * xStep * (slowdown ? xStep : 1); + double y = cursorDeltaY * yStep * (slowdown ? yStep : 1); + + double powXValue = Math.pow(x, 2.0); + double powYValue = Math.pow(y, 2.0); + + if (state == 2) { + this.targetPitch = -MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powYValue) * 0.11D; + } else if (state == 1) { + this.targetPitch = MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powYValue) * 0.11D; + } + + if (xState == 2) { + this.targetYaw = -MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powXValue) * 0.11D; + } else if (xState == 1) { + this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powXValue) * 0.11D; + } + + this.prevY = value; + this.prevX = xValue; } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightReacharound.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightReacharound.java index 52b3b21..ca9554d 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightReacharound.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightReacharound.java @@ -73,7 +73,7 @@ public class MidnightReacharound { 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; } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EmotecraftCompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EmotecraftCompat.java index 74af0f5..ba3430a 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EmotecraftCompat.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EmotecraftCompat.java @@ -1,16 +1,21 @@ package eu.midnightdust.midnightcontrols.client.compat; import eu.midnightdust.midnightcontrols.client.controller.InputManager; +import io.github.kosmx.emotes.arch.gui.EmoteMenuImpl; import io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; public class EmotecraftCompat { + private static final MinecraftClient client = MinecraftClient.getInstance(); + public static void openEmotecraftScreen(Screen parent) { + client.setScreen(new EmoteMenuImpl(parent)); + } public static boolean isEmotecraftScreen(Screen screen) { return screen instanceof FastChosseScreen; } public static void handleEmoteSelector(int index) { - MinecraftClient client = MinecraftClient.getInstance(); + if (client.currentScreen instanceof FastChosseScreen) { int x = client.getWindow().getWidth() / 2; int y = client.getWindow().getHeight() / 2; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/SodiumCompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/SodiumCompat.java index 7964921..f2eb2b1 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/SodiumCompat.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/SodiumCompat.java @@ -1,35 +1,12 @@ package eu.midnightdust.midnightcontrols.client.compat; import eu.midnightdust.midnightcontrols.MidnightControls; -import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; 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.options.control.ControlElement; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; 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) { if (screen instanceof SodiumOptionsGUI optionsGUI) { SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/VoxelMapCompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/VoxelMapCompat.java deleted file mode 100644 index 9c425e7..0000000 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/VoxelMapCompat.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2022 Motschen - * - * 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(); - } -} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java index 4402653..012a6fc 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java @@ -9,7 +9,7 @@ package eu.midnightdust.midnightcontrols.client.controller; -import eu.midnightdust.midnightcontrols.client.ButtonState; +import eu.midnightdust.midnightcontrols.client.enums.ButtonState; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import net.minecraft.client.MinecraftClient; @@ -75,9 +75,8 @@ public class ButtonBinding { .action(MovementHandler.HANDLER).onlyInGame().register(); public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A) .action(InputHandlers::handleScreenshot).cooldown().register(); - public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B) - .action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.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) .action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register(); public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT) diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/Controller.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/Controller.java index 87c397b..282d89d 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/Controller.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/Controller.java @@ -32,6 +32,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import static org.lwjgl.BufferUtils.createByteBuffer; @@ -79,7 +80,7 @@ public record Controller(int id) implements Nameable { * @return the controller's name */ @Override - public String getName() { + public @NotNull String getName() { var name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id); return name == null ? String.valueOf(this.id()) : name; } @@ -145,6 +146,9 @@ public record Controller(int id) implements Nameable { * Updates the controller mappings. */ public static void updateMappings() { + CompletableFuture.supplyAsync(Controller::updateMappingsSync); + } + private static boolean updateMappingsSync() { try { MidnightControlsClient.get().log("Updating controller mappings..."); File databaseFile = new File("config/gamecontrollerdatabase.txt"); @@ -161,7 +165,7 @@ public record Controller(int id) implements Nameable { var database = ioResourceToBuffer(databaseFile.getPath(), 1024); if (database != null) GLFW.glfwUpdateGamepadMappings(database); if (!MidnightControlsClient.MAPPINGS_FILE.exists()) - return; + return false; var buffer = ioResourceToBuffer(MidnightControlsClient.MAPPINGS_FILE.getPath(), 1024); if (buffer != null) GLFW.glfwUpdateGamepadMappings(buffer); } catch (IOException e) { @@ -176,7 +180,7 @@ public record Controller(int id) implements Nameable { var string = l == 0L ? "" : MemoryUtil.memUTF8(l); var client = MinecraftClient.getInstance(); if (client != null) { - client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT, + client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string))); MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string); } @@ -199,5 +203,6 @@ public record Controller(int id) implements Nameable { controller.isGamepad())); } } + return true; } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java index b39c68a..2cbc4f8 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java @@ -10,7 +10,8 @@ package eu.midnightdust.midnightcontrols.client.controller; 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.MidnightControlsConfig; 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.YACLCompat; 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.CreativeInventoryScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.RecipeBookWidgetAccessor; import eu.midnightdust.midnightcontrols.client.mixin.TabNavigationWidgetAccessor; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; 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.FabricCreativeGuiComponents; import net.fabricmc.fabric.impl.itemgroup.FabricItemGroup; -import net.fabricmc.fabric.impl.itemgroup.ItemGroupEventsImpl; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.TitleScreen; @@ -100,6 +100,7 @@ public class InputHandlers { } else if (client.currentScreen instanceof RingScreen) { MidnightControlsClient.get().ring.cyclePage(next); } else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) { + if (PlatformFunctions.isModLoaded("connectormod")) return true; ItemGroup currentTab = CreativeInventoryScreenAccessor.getSelectedTab(); int currentColumn = currentTab.getColumn(); ItemGroup.Row currentRow = currentTab.getRow(); @@ -160,7 +161,7 @@ public class InputHandlers { nextTab = tabs.size() - 1; else if (nextTab >= tabs.size()) nextTab = 0; - screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot(), true); + screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot().getAdvancementEntry(), true); break; } } @@ -190,6 +191,8 @@ public class InputHandlers { } public static PressAction handlePage(boolean next) { return (client, button, value, action) -> { + if (action == ButtonState.RELEASE) + return false; if (client.currentScreen instanceof CreativeInventoryScreen) { try { return client.currentScreen.children().stream().filter(element -> element instanceof PressableWidget) @@ -277,7 +280,7 @@ public class InputHandlers { if (action == ButtonState.PRESS) { // If in game, then pause the game. 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. client.player.closeHandledScreen(); else // Else just close the current screen. @@ -418,7 +421,7 @@ public class InputHandlers { * @return true if the client is in game, else false */ public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) { - return (client.currentScreen == null && 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; } /** diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java index 3288f2b..2feea52 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java @@ -10,7 +10,7 @@ package eu.midnightdust.midnightcontrols.client.controller; import eu.midnightdust.midnightcontrols.ControlsMode; -import eu.midnightdust.midnightcontrols.client.ButtonState; +import eu.midnightdust.midnightcontrols.client.enums.ButtonState; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import it.unimi.dsi.fastutil.ints.*; @@ -27,7 +27,6 @@ import org.lwjgl.glfw.GLFW; import java.util.*; import java.util.function.Consumer; -import java.util.stream.Collectors; import java.util.stream.Stream; /** diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/MovementHandler.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/MovementHandler.java index b7d45dd..e7d2d2e 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/MovementHandler.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/MovementHandler.java @@ -9,20 +9,12 @@ package eu.midnightdust.midnightcontrols.client.controller; -import eu.midnightdust.midnightcontrols.client.ButtonState; -import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; +import eu.midnightdust.midnightcontrols.client.enums.ButtonState; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; +import eu.midnightdust.midnightcontrols.client.util.MathUtil; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.input.Input; 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.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 org.jetbrains.annotations.NotNull; @@ -43,6 +35,7 @@ public final class MovementHandler implements PressAction { private float slowdownFactor = 1.f; private float movementForward = 0.f; private float movementSideways = 0.f; + private MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil(); private MovementHandler() { } @@ -53,8 +46,6 @@ public final class MovementHandler implements PressAction { * @param player The client player. */ public void applyMovement(@NotNull ClientPlayerEntity player) { - double movementR, movementTheta; - if (!this.shouldOverrideMovement) return; player.input.pressingForward = this.pressingForward; @@ -62,12 +53,9 @@ public final class MovementHandler implements PressAction { player.input.pressingLeft = this.pressingLeft; player.input.pressingRight = this.pressingRight; - // Do an implicit square here - movementR = this.slowdownFactor * (Math.pow(this.movementSideways, 2) + Math.pow(this.movementForward, 2)); - movementR = MathHelper.clamp(movementR, 0.f, 1.f); - movementTheta = Math.atan2(this.movementForward, this.movementSideways); - player.input.movementForward = (float) (movementR * Math.sin(movementTheta)); - player.input.movementSideways = (float) (movementR * Math.cos(movementTheta)); + polarUtil.calculate(this.movementSideways, this.movementForward, this.slowdownFactor); + player.input.movementForward = polarUtil.polarY; + player.input.movementSideways = polarUtil.polarX; this.shouldOverrideMovement = false; } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/PressAction.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/PressAction.java index f8ce0e2..a76c462 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/PressAction.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/PressAction.java @@ -9,7 +9,7 @@ package eu.midnightdust.midnightcontrols.client.controller; -import eu.midnightdust.midnightcontrols.client.ButtonState; +import eu.midnightdust.midnightcontrols.client.enums.ButtonState; import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor; import net.minecraft.client.MinecraftClient; import net.minecraft.client.option.StickyKeyBinding; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ButtonState.java b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/ButtonState.java similarity index 94% rename from src/main/java/eu/midnightdust/midnightcontrols/client/ButtonState.java rename to src/main/java/eu/midnightdust/midnightcontrols/client/enums/ButtonState.java index 8baa630..e54e31f 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ButtonState.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/ButtonState.java @@ -7,7 +7,7 @@ * see the LICENSE file. */ -package eu.midnightdust.midnightcontrols.client; +package eu.midnightdust.midnightcontrols.client.enums; /** * Represents a button state. diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/enums/CameraMode.java b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/CameraMode.java new file mode 100644 index 0000000..2724248 --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/CameraMode.java @@ -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]; + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ControllerType.java b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/ControllerType.java similarity index 97% rename from src/main/java/eu/midnightdust/midnightcontrols/client/ControllerType.java rename to src/main/java/eu/midnightdust/midnightcontrols/client/enums/ControllerType.java index ed86533..e0e48bb 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ControllerType.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/ControllerType.java @@ -7,7 +7,7 @@ * see the LICENSE file. */ -package eu.midnightdust.midnightcontrols.client; +package eu.midnightdust.midnightcontrols.client.enums; import net.minecraft.text.Text; import org.aperlambda.lambdacommon.utils.Nameable; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/HudSide.java b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/HudSide.java similarity index 97% rename from src/main/java/eu/midnightdust/midnightcontrols/client/HudSide.java rename to src/main/java/eu/midnightdust/midnightcontrols/client/enums/HudSide.java index db3e3d6..400ff74 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/HudSide.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/HudSide.java @@ -7,7 +7,7 @@ * see the LICENSE file. */ -package eu.midnightdust.midnightcontrols.client; +package eu.midnightdust.midnightcontrols.client.enums; import net.minecraft.text.Text; import org.aperlambda.lambdacommon.utils.Nameable; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/enums/TouchMode.java b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/TouchMode.java new file mode 100644 index 0000000..74b8211 --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/TouchMode.java @@ -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]; + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/VirtualMouseSkin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/VirtualMouseSkin.java similarity index 97% rename from src/main/java/eu/midnightdust/midnightcontrols/client/VirtualMouseSkin.java rename to src/main/java/eu/midnightdust/midnightcontrols/client/enums/VirtualMouseSkin.java index 01ac7cf..33d3e0d 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/VirtualMouseSkin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/enums/VirtualMouseSkin.java @@ -7,7 +7,7 @@ * see the LICENSE file. */ -package eu.midnightdust.midnightcontrols.client; +package eu.midnightdust.midnightcontrols.client.enums; import net.minecraft.text.Text; import org.aperlambda.lambdacommon.utils.Nameable; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MappingsStringInputWidget.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MappingsStringInputWidget.java index d5b0835..0cfb479 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MappingsStringInputWidget.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MappingsStringInputWidget.java @@ -63,7 +63,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget { fw.close(); } catch (IOException e) { if (this.client != null) - this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.TUTORIAL_HINT, + this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty())); e.printStackTrace(); } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java index 9c85b25..24c4e96 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java @@ -11,7 +11,7 @@ package eu.midnightdust.midnightcontrols.client.gui; import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.MidnightControlsConstants; -import eu.midnightdust.midnightcontrols.client.HudSide; +import eu.midnightdust.midnightcontrols.client.enums.HudSide; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; @@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable; */ public class MidnightControlsHud extends Hud { private final MidnightControlsClient mod; - private MinecraftClient client; + private final MinecraftClient client = MinecraftClient.getInstance(); private int attackWidth = 0; private int attackButtonWidth = 0; private int dropItemWidth = 0; @@ -64,7 +64,6 @@ public class MidnightControlsHud extends Hud { @Override public void init(@NotNull MinecraftClient client, int screenWidth, int screenHeight) { super.init(client, screenWidth, screenHeight); - this.client = client; this.inventoryWidth = this.width(ButtonBinding.INVENTORY); this.inventoryButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY); this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS); @@ -198,6 +197,7 @@ public class MidnightControlsHud extends Hud { @Override public void tick() { + if (this.client == null) return; super.tick(); if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) { if (this.client.crosshairTarget == null) diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsRenderer.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsRenderer.java index 0917938..76e268d 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsRenderer.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsRenderer.java @@ -10,7 +10,7 @@ package eu.midnightdust.midnightcontrols.client.gui; 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.MidnightControlsConfig; 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.gui.DrawContext; import net.minecraft.client.resource.language.I18n; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.slot.Slot; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; @@ -234,6 +232,7 @@ public class MidnightControlsRenderer { } //context.getMatrices().push(); + context.getMatrices().translate(0f, 0f, 999f); drawCursor(context, mouseX, mouseY, hoverSlot, client); //context.getMatrices().pop(); } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsSettingsScreen.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsSettingsScreen.java index 70fa1a4..ad38808 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsSettingsScreen.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsSettingsScreen.java @@ -125,6 +125,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { private final SpruceOption unfocusedInputOption; private final SpruceOption invertsRightXAxis; private final SpruceOption invertsRightYAxis; + private final SpruceOption cameraModeOption; private final SpruceOption toggleControllerProfileOption; private final SpruceOption rightDeadZoneOption; private final SpruceOption leftDeadZoneOption; @@ -143,6 +144,13 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { 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("(") .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, () -> MidnightControlsConfig.mouseSpeed, 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", () -> MidnightControlsConfig.joystickAsMouse, value -> MidnightControlsConfig.joystickAsMouse = value, Text.translatable("midnightcontrols.menu.joystick_as_mouse.tooltip")); @@ -262,6 +270,10 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { } }, Text.translatable("")); + this.cameraModeOption = new SpruceCyclingOption("midnightcontrols.menu.camera_mode", + amount -> MidnightControlsConfig.cameraMode = MidnightControlsConfig.cameraMode.next(), + option -> option.getDisplayText(MidnightControlsConfig.cameraMode.getTranslatedText()), + Text.translatable("midnightcontrols.menu.camera_mode.tooltip")); this.rightDeadZoneOption = new SpruceDoubleOption("midnightcontrols.menu.right_dead_zone", 0.05, 1.0, .05f, () -> MidnightControlsConfig.rightDeadZone, value -> MidnightControlsConfig.rightDeadZone = value, option -> { @@ -284,6 +296,27 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { value -> MidnightControlsConfig.virtualMouse = value, Text.translatable("midnightcontrols.menu.virtual_mouse.tooltip")); this.hideCursorOption = new SpruceToggleBooleanOption("midnightcontrols.menu.hide_cursor", () -> MidnightControlsConfig.hideNormalMouse, value -> MidnightControlsConfig.hideNormalMouse = value, Text.translatable("midnightcontrols.menu.hide_cursor.tooltip")); + // Touch options + this.touchModeOption = new SpruceCyclingOption("midnightcontrols.menu.touch_mode", + amount -> MidnightControlsConfig.touchMode = MidnightControlsConfig.touchMode.next(), + option -> option.getDisplayText(MidnightControlsConfig.touchMode.getTranslatedText()), + Text.translatable("midnightcontrols.menu.touch_mode.tooltip")); + this.touchWithControllerOption = new SpruceToggleBooleanOption("midnightcontrols.menu.touch_with_controller", () -> MidnightControlsConfig.touchInControllerMode, + value -> MidnightControlsConfig.touchInControllerMode = value, Text.translatable("midnightcontrols.menu.touch_with_controller.tooltip")); + this.touchSpeedOption = new SpruceDoubleOption("midnightcontrols.menu.touch_speed", 0.0, 150.0, .5f, + () -> MidnightControlsConfig.touchSpeed, + value -> MidnightControlsConfig.touchSpeed = value, option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))), + Text.translatable("midnightcontrols.menu.touch_speed.tooltip")); + this.touchBreakDelayOption = new SpruceDoubleOption("midnightcontrols.menu.touch_break_delay", 50, 500, 1f, + () -> (double) MidnightControlsConfig.touchBreakDelay, + value -> MidnightControlsConfig.touchBreakDelay = value.intValue(), option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))), + Text.translatable("midnightcontrols.menu.touch_break_delay.tooltip")); + this.touchTransparencyOption = new SpruceDoubleOption("midnightcontrols.menu.touch_transparency", 0, 100, 1f, + () -> (double) MidnightControlsConfig.touchTransparency, + value -> MidnightControlsConfig.touchTransparency = value.intValue(), option -> option.getDisplayText(Text.literal(String.valueOf(option.get()))), + Text.translatable("midnightcontrols.menu.touch_break_delay.tooltip")); + this.invertTouchOption = new SpruceToggleBooleanOption("midnightcontrols.menu.invert_touch", () -> MidnightControlsConfig.invertTouch, + value -> MidnightControlsConfig.invertTouch = value, Text.translatable("midnightcontrols.menu.invert_touch.tooltip")); } @Override @@ -337,6 +370,8 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { tabs.addSeparatorEntry(Text.translatable("midnightcontrols.menu.separator.controller")); tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.controller"), null, this::buildControllerTab); + tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.touch"), null, + this::buildTouchTab); tabs.addTabEntry(Text.translatable("midnightcontrols.menu.title.mappings.string"), null, this::buildMappingsStringEditorTab); } @@ -420,6 +455,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { list.addSingleOptionEntry(this.secondControllerOption); list.addSingleOptionEntry(this.toggleControllerProfileOption); list.addSingleOptionEntry(this.unfocusedInputOption); + list.addSingleOptionEntry(this.cameraModeOption); list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis); list.addSingleOptionEntry(this.rightDeadZoneOption); list.addSingleOptionEntry(this.leftDeadZoneOption); @@ -431,6 +467,18 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { root.addChild(labels); return root; } + public SpruceOptionListWidget buildTouchTab(int width, int height) { + var list = new SpruceOptionListWidget(Position.origin(), width, height); + list.setBackground(new MidnightControlsBackground(130)); + list.addSingleOptionEntry(this.touchSpeedOption); + list.addSingleOptionEntry(this.touchWithControllerOption); + list.addSingleOptionEntry(this.invertTouchOption); + list.addSingleOptionEntry(new SpruceSeparatorOption("midnightcontrols.menu.title.hud", true, null)); + list.addSingleOptionEntry(this.touchModeOption); + list.addSingleOptionEntry(this.touchBreakDelayOption); + list.addSingleOptionEntry(this.touchTransparencyOption); + return list; + } public SpruceContainerWidget buildMappingsStringEditorTab(int width, int height) { return new MappingsStringInputWidget(Position.origin(), width, height); diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/ReloadControllerMappingsOption.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/ReloadControllerMappingsOption.java index 372cce3..b87dc40 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/ReloadControllerMappingsOption.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/ReloadControllerMappingsOption.java @@ -33,7 +33,7 @@ public class ReloadControllerMappingsOption { Controller.updateMappings(); if (client.currentScreen instanceof MidnightControlsSettingsScreen) client.currentScreen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight()); - client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT, + client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.mappings.updated"), Text.empty())); }, Text.translatable("midnightcontrols.tooltip.reload_controller_mappings")); } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/RingScreen.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/RingScreen.java index 1c6fecf..c3b3e64 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/RingScreen.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/RingScreen.java @@ -15,7 +15,6 @@ import eu.midnightdust.midnightcontrols.client.ring.RingPage; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; /** diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/TouchscreenOverlay.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/TouchscreenOverlay.java index 8fa1d61..bf2de6f 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/TouchscreenOverlay.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/TouchscreenOverlay.java @@ -11,25 +11,39 @@ package eu.midnightdust.midnightcontrols.client.gui; import dev.lambdaurora.spruceui.Position; 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.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 net.minecraft.client.gui.screen.ChatScreen; -import net.minecraft.client.gui.screen.GameMenuScreen; -import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.*; import net.minecraft.client.gui.screen.ingame.InventoryScreen; -import net.minecraft.client.gui.widget.TexturedButtonWidget; +import net.minecraft.client.gui.widget.TextIconButtonWidget; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.texture.MissingSprite; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.InputUtil; +import net.minecraft.item.*; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; import net.minecraft.text.Text; -import net.minecraft.util.Arm; -import net.minecraft.util.Identifier; +import net.minecraft.util.*; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; +import java.util.List; +import java.util.Objects; + import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X; import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y; @@ -38,17 +52,26 @@ import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y; */ public class TouchscreenOverlay extends Screen { 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 flyButton; private SilentTexturedButtonWidget flyUpButton; private SilentTexturedButtonWidget flyDownButton; - private int flyButtonEnableTicks = 0; - private int forwardButtonTick = 0; + private SilentTexturedButtonWidget forwardButton; private SilentTexturedButtonWidget forwardLeftButton; private SilentTexturedButtonWidget forwardRightButton; + private SilentTexturedButtonWidget leftButton; + private SilentTexturedButtonWidget rightButton; + private SilentTexturedButtonWidget backButton; private SilentTexturedButtonWidget startSneakButton; private SilentTexturedButtonWidget endSneakButton; + private int flyButtonEnableTicks = 0; + private int forwardButtonTick = 0; + public static TouchscreenOverlay instance; public TouchscreenOverlay(@NotNull MidnightControlsClient mod) { super(Text.literal("Touchscreen overlay")); @@ -56,27 +79,18 @@ public class TouchscreenOverlay extends Screen { } @Override - public boolean shouldPause() - { + public boolean shouldPause() { return false; } @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - super.keyPressed(keyCode,scanCode,modifiers); - //return false; - return true; - } + public void renderInGameBackground(DrawContext context) {} - private void pauseGame(boolean bl) { - if (this.client == null) - return; - boolean bl2 = this.client.isIntegratedServerRunning() && !this.client.getServer().isRemote(); - if (bl2) { - this.client.setScreen(new GameMenuScreen(!bl)); + private void pauseGame() { + assert this.client != null; + this.client.setScreen(new GameMenuScreen(true)); + if (this.client.isIntegratedServerRunning() && !Objects.requireNonNull(this.client.getServer()).isRemote()) { this.client.getSoundManager().pauseAll(); - } else { - this.client.setScreen(new GameMenuScreen(true)); } } @@ -87,24 +101,26 @@ public class TouchscreenOverlay extends Screen { * */ private void updateForwardButtonsState(boolean state) { - if (state) - this.forwardButtonTick = -1; - else - this.forwardButtonTick = 20; + this.forwardButtonTick = state ? -1 : 20; } /** * Updates the jump buttons. */ private void updateJumpButtons() { - if (this.client == null) - return; - if (!this.client.interactionManager.isFlyingLocked()) { + assert this.client != null; + assert this.client.player != null; + float transparency = MidnightControlsConfig.touchTransparency / 100f; + + if (this.client.player.getAbilities().flying) { boolean oldStateFly = this.flyButton.isVisible(); this.jumpButton.setVisible(false); this.flyButton.setVisible(true); this.flyUpButton.setVisible(true); this.flyDownButton.setVisible(true); + this.flyButton.setAlpha(transparency); + this.flyUpButton.setAlpha(transparency); + this.flyDownButton.setAlpha(transparency); if (oldStateFly != this.flyButton.isVisible()) { this.flyButtonEnableTicks = 5; this.setJump(false); @@ -115,6 +131,7 @@ public class TouchscreenOverlay extends Screen { this.flyButton.setVisible(false); this.flyUpButton.setVisible(false); this.flyDownButton.setVisible(false); + this.jumpButton.setAlpha(transparency); } } @@ -124,6 +141,7 @@ public class TouchscreenOverlay extends Screen { * @param btn The pressed button. */ private void handleJump(SpruceButtonWidget btn) { + assert this.client != null; ((KeyBindingAccessor) this.client.options.jumpKey).midnightcontrols$handlePressState(btn.isActive()); } /** @@ -132,31 +150,32 @@ public class TouchscreenOverlay extends Screen { * @param state The state. */ private void setJump(boolean state) { + assert this.client != null; ((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 protected void init() { super.init(); + assert this.client != null; + assert this.client.player != null; + assert this.client.interactionManager != null; int scaledWidth = this.client.getWindow().getScaledWidth(); int scaledHeight = this.client.getWindow().getScaledHeight(); - this.addDrawableChild(new TexturedButtonWidget(scaledWidth / 2 - 20, 0, 20, 20, 0, 106, 20, new Identifier("textures/gui/widgets.png"), 256, 256, - btn -> this.client.setScreen(new ChatScreen("")), Text.empty())); - this.addDrawableChild(new TexturedButtonWidget(scaledWidth / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256, - btn -> this.pauseGame(false))); + int emoteOffset = 0; + if (PlatformFunctions.isModLoaded("emotecraft")) { + emoteOffset = 10; + 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. int inventoryButtonX = scaledWidth / 2; int inventoryButtonY = scaledHeight - 16 - 5; @@ -165,15 +184,15 @@ public class TouchscreenOverlay extends Screen { } else { inventoryButtonX = inventoryButtonX + 91 + 4; } - this.addDrawableChild(new TexturedButtonWidget(inventoryButtonX, inventoryButtonY, 20, 20, 20, 0, 20, WIDGETS_LOCATION, 256, 256, - btn -> { - if (this.client.interactionManager.hasRidingInventory()) { - this.client.player.openRidingInventory(); - } else { - this.client.getTutorialManager().onInventoryOpened(); - this.client.setScreen(new InventoryScreen(this.client.player)); - } - })); + this.addDrawableChild(this.inventoryButton = new SilentTexturedButtonWidget(Position.of(inventoryButtonX, inventoryButtonY), 20, 20, Text.empty(), btn -> { + if (this.client.interactionManager.hasRidingInventory()) { + this.client.player.openRidingInventory(); + } else { + this.client.getTutorialManager().onInventoryOpened(); + this.client.setScreen(new InventoryScreen(this.client.player)); + } + }, 20, 0, 20, WIDGETS_LOCATION, 256, 256)); + ; int jumpButtonX, swapHandsX, sneakButtonX; int sneakButtonY = scaledHeight - 10 - 40 - 5; if (MidnightControlsConfig.hudSide == HudSide.LEFT) { @@ -186,17 +205,23 @@ public class TouchscreenOverlay extends Screen { sneakButtonX = scaledWidth - 10 - 40 - 5; } // 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 -> { if (button.isActive()) { 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)); // Drop - this.addDrawableChild(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)); + this.addDrawableChild(this.dropButton = new SilentTexturedButtonWidget(Position.of(swapHandsX, sneakButtonY + 5 + 20), 20, 20, Text.empty(), btn -> { + if (btn.isActive() && !client.player.isSpectator() && client.player.dropSelectedItem(false)) { + client.player.swingHand(Hand.MAIN_HAND); + } + }, 20, 160, 20, WIDGETS_LOCATION)); + // Use + this.addDrawableChild(this.useButton = new ItemUseButtonWidget(Position.of(width/2-25, height - 70), 50, 17, Text.translatable(MidnightControlsConstants.NAMESPACE+".action.eat"), btn -> + client.interactionManager.interactItem(client.player, client.player.getActiveHand()))); // Jump keys this.addDrawableChild(this.jumpButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.empty(), this::handleJump, 0, 40, 20, WIDGETS_LOCATION)); this.addDrawableChild(this.flyButton = new SilentTexturedButtonWidget(Position.of(jumpButtonX, sneakButtonY), 20, 20, Text.empty(),btn -> { @@ -226,15 +251,13 @@ public class TouchscreenOverlay extends Screen { this.startSneakButton.setVisible(true); } }, 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 -> { ((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive()); ((KeyBindingAccessor) this.client.options.leftKey).midnightcontrols$handlePressState(btn.isActive()); this.updateForwardButtonsState(btn.isActive()); }, 80, 80, 20, WIDGETS_LOCATION )); - this.forwardLeftButton.setVisible(false); - this.addDrawableChild(new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY - 5 - 20), 20, 20, Text.empty(), btn -> { + this.addDrawableChild(this.forwardButton = new SilentTexturedButtonWidget(Position.of(sneakButtonX, sneakButtonY - 5 - 20), 20, 20, Text.empty(), btn -> { ((KeyBindingAccessor) this.client.options.forwardKey).midnightcontrols$handlePressState(btn.isActive()); this.updateForwardButtonsState(btn.isActive()); this.forwardLeftButton.setVisible(true); @@ -247,48 +270,107 @@ public class TouchscreenOverlay extends Screen { this.updateForwardButtonsState(btn.isActive()); }, 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 )); - 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 )); - 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 )); + 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 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 - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (mouseY >= (double) (this.height - 22) && this.client != null && this.client.player != null) { - int centerX = this.width / 2; - if (mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) { - for (int slot = 0; slot < 9; ++slot) { - int slotX = centerX - 90 + slot * 20 + 2; - if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) { - this.client.player.getInventory().selectedSlot = slot; - return true; - } - } - } + public void tick() { + assert this.client != null; + assert this.client.interactionManager != null; + assert this.client.player != null; + + if (this.forwardButtonTick > 0) { + --this.forwardButtonTick; + } else { + this.forwardLeftButton.setVisible(false); + this.forwardRightButton.setVisible(false); } - return super.mouseClicked(mouseX, mouseY, button); + this.useButton.setVisible(client.player.getMainHandStack() != null && (client.player.getMainHandStack().getUseAction() != UseAction.NONE || client.player.getMainHandStack().getItem() instanceof ArmorItem) && !TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())); + this.updateJumpButtons(); } @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) { + if (!MidnightControlsConfig.invertTouch) { + deltaX = -deltaX; + deltaY = -deltaY; + } if (deltaY > 0.01) - this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 2); - else if (deltaY < 0.01) - this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 1); + this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs((deltaY / 3.0)*MidnightControlsConfig.touchSpeed/100), 2); + else this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs((deltaY / 3.0)*MidnightControlsConfig.touchSpeed/100), 1); if (deltaX > 0.01) - this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 2); - else if (deltaX < 0.01) - this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 1); + this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs((deltaX / 3.0)*MidnightControlsConfig.touchSpeed/100), 2); + else this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs((deltaX / 3.0)*MidnightControlsConfig.touchSpeed/100), 1); } return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + KeyBinding.onKeyPressed(InputUtil.fromKeyCode(keyCode, scanCode)); + super.keyPressed(keyCode,scanCode,modifiers); + return true; + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + super.render(context, mouseX, mouseY, delta); + context.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); + context.fill(mouseX-10, mouseY-10, mouseX+10, mouseY+10, 0xFFFFFF); + } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ControlsOptionsScreenMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ControlsOptionsScreenMixin.java index 46dbb41..e1fc3c4 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ControlsOptionsScreenMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ControlsOptionsScreenMixin.java @@ -9,11 +9,11 @@ package eu.midnightdust.midnightcontrols.client.mixin; -import eu.midnightdust.lib.util.screen.TexturedOverlayButtonWidget; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.ControlsOptionsScreen; import net.minecraft.client.gui.screen.option.GameOptionsScreen; +import net.minecraft.client.gui.widget.TextIconButtonWidget; import net.minecraft.client.option.GameOptions; import net.minecraft.text.Text; 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;")) 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) -> { - this.client.setScreen(new MidnightControlsSettingsScreen(this, false)); - }, Text.translatable("midnightcontrols.menu.title.controller"))); + TextIconButtonWidget iconWidget = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"), (button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true) + .dimension(20,20).texture(new Identifier("midnightcontrols", "icon/controller"), 20, 20).build(); + iconWidget.setPosition(this.width / 2 + 158, this.height / 6 - 12); + this.addDrawableChild(iconWidget); } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/EntryListWidgetAccessor.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/EntryListWidgetAccessor.java deleted file mode 100644 index 72f8f4c..0000000 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/EntryListWidgetAccessor.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright © 2021 LambdAurora - * - * 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); -} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameOptionsMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameOptionsMixin.java deleted file mode 100644 index 84291fc..0000000 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameOptionsMixin.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright © 2021 LambdAurora - * - * 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. - *

- * Sets the default of the Auto-Jump option to false. - */ -@Mixin(GameOptions.class) -public abstract class GameOptionsMixin { - - @Shadow public abstract SimpleOption 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); - } -} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java index 9414b84..082da55 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java @@ -9,10 +9,12 @@ package eu.midnightdust.midnightcontrols.client.mixin; +import com.mojang.blaze3d.systems.RenderSystem; import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer; +import eu.midnightdust.midnightcontrols.client.touch.TouchUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.GameRenderer; @@ -26,7 +28,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(GameRenderer.class) -public class GameRendererMixin { +public abstract class GameRendererMixin { @Shadow @Final MinecraftClient client; @@ -37,8 +39,14 @@ public class GameRendererMixin { 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) - 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); 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()); + } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/InputUtilMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/InputUtilMixin.java index 37505f3..4230d73 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/InputUtilMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/InputUtilMixin.java @@ -2,20 +2,14 @@ package eu.midnightdust.midnightcontrols.client.mixin; import net.minecraft.client.util.InputUtil; 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 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) public abstract class InputUtilMixin { - @Final - @Shadow - private static MethodHandle GLFW_RAW_MOUSE_MOTION_SUPPORTED_HANDLE; - /** * @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 @@ -23,17 +17,8 @@ public abstract class InputUtilMixin { * 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. */ - @Overwrite - public static boolean isRawMouseMotionSupported(){ - if(MidnightControlsConfig.eyeTrackerAsMouse){ - 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); - } - } + @Inject(method = "isRawMouseMotionSupported", at = @At("HEAD"), cancellable = true) + private static void setRawMouseMotionSupported(CallbackInfoReturnable cir) { + if (MidnightControlsConfig.eyeTrackerAsMouse) cir.setReturnValue(false); } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyBindingMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyBindingMixin.java index 0655e90..832f0cf 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyBindingMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyBindingMixin.java @@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(KeyBinding.class) -public class KeyBindingMixin implements KeyBindingAccessor { +public abstract class KeyBindingMixin implements KeyBindingAccessor { @Shadow private int timesPressed; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyBindingRegistryImplAccessor.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyBindingRegistryImplAccessor.java deleted file mode 100644 index efd6d6e..0000000 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyBindingRegistryImplAccessor.java +++ /dev/null @@ -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 getMODDED_KEY_BINDINGS() { - return null; - } - -} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyboardMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyboardMixin.java new file mode 100644 index 0000000..7bc6a2e --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/KeyboardMixin.java @@ -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; + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java index 630edc0..676b7f4 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java @@ -9,21 +9,15 @@ package eu.midnightdust.midnightcontrols.client.mixin; -import eu.midnightdust.midnightcontrols.MidnightControls; import eu.midnightdust.midnightcontrols.MidnightControlsFeature; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; -import eu.midnightdust.midnightcontrols.client.MidnightInput; -import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.render.BufferBuilderStorage; import net.minecraft.client.render.GameRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.world.ClientWorld; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; @@ -35,7 +29,6 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; -import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -46,24 +39,15 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(MinecraftClient.class) public abstract class MinecraftClientMixin { - @Shadow - @Nullable - public HitResult crosshairTarget; + @Shadow @Nullable public HitResult crosshairTarget; - @Shadow - @Nullable - public ClientPlayerEntity player; + @Shadow @Nullable public ClientPlayerEntity player; - @Shadow - @Nullable - public ClientPlayerInteractionManager interactionManager; + @Shadow @Nullable public ClientPlayerInteractionManager interactionManager; - @Shadow - @Final - public GameRenderer gameRenderer; + @Shadow @Final public GameRenderer gameRenderer; - @Shadow - private int itemUseCooldown; + @Shadow private int itemUseCooldown; @Shadow public abstract BufferBuilderStorage getBufferBuilders(); @@ -115,10 +99,6 @@ public abstract class MinecraftClientMixin { // } 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") 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; +// } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseAccessor.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseAccessor.java new file mode 100644 index 0000000..ee6261e --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseAccessor.java @@ -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); +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java index ab2b112..04dc524 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java @@ -12,103 +12,104 @@ package eu.midnightdust.midnightcontrols.client.mixin; import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; +import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay; +import eu.midnightdust.midnightcontrols.client.touch.TouchInput; +import eu.midnightdust.midnightcontrols.client.touch.TouchUtils; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import net.minecraft.client.MinecraftClient; import net.minecraft.client.Mouse; -import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.GlfwUtil; import net.minecraft.client.util.SmoothUtil; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import eu.midnightdust.midnightcontrols.client.mouse.EyeTrackerHandler; -import static org.lwjgl.glfw.GLFW.GLFW_CURSOR; -import static org.lwjgl.glfw.GLFW.GLFW_CURSOR_HIDDEN; +import static eu.midnightdust.midnightcontrols.client.MidnightControlsConfig.doMixedInput; +import static org.lwjgl.glfw.GLFW.*; /** * Adds extra access to the mouse. */ @Mixin(Mouse.class) public abstract class MouseMixin implements MouseAccessor { - @Shadow - @Final - private MinecraftClient client; + @Shadow @Final private MinecraftClient client; - @Shadow - private double y; + @Shadow private double y; - @Shadow - private double cursorDeltaX; + @Shadow private double cursorDeltaX; - @Shadow - private double cursorDeltaY; + @Shadow private double cursorDeltaY; - @Shadow - private double x; + @Shadow private double x; - @Shadow - private boolean cursorLocked; + @Shadow private boolean cursorLocked; - @Shadow - private boolean hasResolutionChanged; + @Shadow private boolean hasResolutionChanged; - @Shadow - private double lastMouseUpdateTime; + @Shadow private double lastMouseUpdateTime; - @Shadow - @Final - private SmoothUtil cursorXSmoother; + @Shadow @Final private SmoothUtil cursorXSmoother; - @Shadow - @Final - private SmoothUtil cursorYSmoother; + @Shadow @Final private SmoothUtil cursorYSmoother; @Shadow private boolean leftButtonClicked; - @Accessor - public abstract void setLeftButtonClicked(boolean value); - - @Invoker("onCursorPos") - public abstract void midnightcontrols$onCursorPos(long window, double x, double y); - - @Inject(method = "onMouseButton", at = @At(value = "TAIL")) - private void onMouseBackButton(long window, int button, int action, int mods, CallbackInfo ci) { - if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && MinecraftClient.getInstance().currentScreen != null) { - if (MidnightControlsClient.get().input.tryGoBack(MinecraftClient.getInstance().currentScreen)) { - action = 0; + @Inject(method = "onMouseButton", at = @At(value = "HEAD"), cancellable = true) + private void midnightcontrols$onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) { + if (window != this.client.getWindow().getHandle()) return; + if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && client.currentScreen != null) { + MidnightControlsClient.get().input.tryGoBack(client.currentScreen); + } + else if ((doMixedInput() || client.currentScreen instanceof TouchscreenOverlay) && client.player != null && button == GLFW_MOUSE_BUTTON_1) { + double mouseX = x / client.getWindow().getScaleFactor(); + double mouseY = y / client.getWindow().getScaleFactor(); + int centerX = client.getWindow().getScaledWidth() / 2; + if (action == 1 && mouseY >= (double) (client.getWindow().getScaledHeight() - 22) && mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) { + for (int slot = 0; slot < 9; ++slot) { + int slotX = centerX - 90 + slot * 20 + 2; + if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) { + client.player.getInventory().selectedSlot = slot; + ci.cancel(); + return; + } + } } + if (action == 1) { + TouchInput.clickStartTime = System.currentTimeMillis(); + boolean bl = false; + if (client.currentScreen instanceof TouchscreenOverlay overlay) bl = overlay.mouseClicked(mouseX, mouseY, button); + if (!bl) TouchInput.firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY); + if (client.currentScreen == null) ci.cancel(); + } + else if (TouchInput.mouseReleased(mouseX, mouseY, button)) ci.cancel(); } } @Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true) - private void isCursorLocked(CallbackInfoReturnable ci) { + private void midnightcontrols$isCursorLocked(CallbackInfoReturnable ci) { if (this.client.currentScreen == null) { if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse) { - ci.setReturnValue(true); ci.cancel(); } } } @Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true) - private void onCursorLocked(CallbackInfo ci) { - if (/*config.getControlsMode() == ControlsMode.TOUCHSCREEN - ||*/ (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse)) + private void midnightcontrols$onCursorLocked(CallbackInfo ci) { + if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN || doMixedInput()) ci.cancel(); } @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()) { - //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) { cursorXSmoother.clear(); cursorYSmoother.clear(); @@ -120,17 +121,16 @@ public abstract class MouseMixin implements MouseAccessor { cursorDeltaY = 0.0; ci.cancel(); } + if (doMixedInput() && client.isWindowFocused()) { + ci.cancel(); + } } - @Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true) - private void lockCursor(CallbackInfo ci) { - if (MidnightControlsConfig.eyeTrackerAsMouse && client.isWindowFocused() && !this.cursorLocked) { - if (!MinecraftClient.IS_SYSTEM_MAC) { - KeyBinding.updatePressedStates(); - } + @Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/InputUtil;setCursorParameters(JIDD)V",shift = At.Shift.BEFORE), cancellable = true) + private void midnightcontrols$lockCursor(CallbackInfo ci) { + if ((doMixedInput() || MidnightControlsConfig.eyeTrackerAsMouse)) { //In eye tracking mode, we cannot have the cursor locked to the center. GLFW.glfwSetInputMode(client.getWindow().getHandle(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - cursorLocked = true; //The game uses this flag for other gameplay checks client.setScreen(null); hasResolutionChanged = true; ci.cancel(); diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ScreenAccessor.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ScreenAccessor.java deleted file mode 100644 index f9b2b01..0000000 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ScreenAccessor.java +++ /dev/null @@ -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 getSelectables(); - @Accessor @Nullable - Selectable getSelected(); -} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ScreenMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ScreenMixin.java new file mode 100644 index 0000000..f051589 --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ScreenMixin.java @@ -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 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)); + } + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/WorldRendererMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/WorldRendererMixin.java index 48b3b89..44f760a 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/WorldRendererMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/WorldRendererMixin.java @@ -10,8 +10,12 @@ package eu.midnightdust.midnightcontrols.client.mixin; import eu.midnightdust.lib.util.MidnightColorUtil; +import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; +import eu.midnightdust.midnightcontrols.client.touch.TouchInput; +import eu.midnightdust.midnightcontrols.client.enums.TouchMode; +import eu.midnightdust.midnightcontrols.client.util.RainbowColor; import net.minecraft.block.ShapeContext; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.*; @@ -21,14 +25,17 @@ import net.minecraft.item.BlockItem; import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemUsageContext; import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.util.shape.VoxelShape; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.awt.*; @@ -54,6 +61,13 @@ public abstract class WorldRendererMixin { @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) { } + @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( 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, 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) return; 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())); 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(); var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines()); drawCuboidShapeOutline(matrices, vertexConsumer, outlineShape, diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/ButtonBindingRingAction.java b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/ButtonBindingRingAction.java index 824690b..c9acadf 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/ButtonBindingRingAction.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/ButtonBindingRingAction.java @@ -10,16 +10,13 @@ package eu.midnightdust.midnightcontrols.client.ring; 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.util.KeyBindingAccessor; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.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.Text; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchInput.java b/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchInput.java new file mode 100644 index 0000000..f29c003 --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchInput.java @@ -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; + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchUtils.java b/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchUtils.java new file mode 100644 index 0000000..24b7574 --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchUtils.java @@ -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; + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/ItemUseButtonWidget.java b/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/ItemUseButtonWidget.java new file mode 100644 index 0000000..d3681c4 --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/ItemUseButtonWidget.java @@ -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); + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/widget/SilentTexturedButtonWidget.java b/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/SilentTexturedButtonWidget.java similarity index 77% rename from src/main/java/eu/midnightdust/midnightcontrols/client/gui/widget/SilentTexturedButtonWidget.java rename to src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/SilentTexturedButtonWidget.java index 7861ac5..e7ae416 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/widget/SilentTexturedButtonWidget.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/SilentTexturedButtonWidget.java @@ -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.widget.SpruceTexturedButtonWidget; @@ -23,4 +23,17 @@ public class SilentTexturedButtonWidget extends SpruceTexturedButtonWidget { } @Override public void playDownSound() {} + @Override + protected void onRelease(double mouseX, double mouseY) { + this.setActive(false); + super.onClick(mouseX, mouseY); + super.onRelease(mouseX, mouseY); + this.setActive(true); + } + @Override + public void onClick(double mouseX, double mouseY) { + this.setActive(true); + super.onClick(mouseX, mouseY); + this.setActive(false); + } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/util/MathUtil.java b/src/main/java/eu/midnightdust/midnightcontrols/client/util/MathUtil.java new file mode 100644 index 0000000..36c3d8c --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/util/MathUtil.java @@ -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)); + } + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/util/RainbowColor.java b/src/main/java/eu/midnightdust/midnightcontrols/client/util/RainbowColor.java new file mode 100644 index 0000000..88a33aa --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/util/RainbowColor.java @@ -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); + } +} diff --git a/src/main/resources/assets/midnightcontrols/lang/en_us.json b/src/main/resources/assets/midnightcontrols/lang/en_us.json index 11b5107..d1fb7d6 100644 --- a/src/main/resources/assets/midnightcontrols/lang/en_us.json +++ b/src/main/resources/assets/midnightcontrols/lang/en_us.json @@ -16,9 +16,13 @@ "midnightcontrols.midnightconfig.enum.ControllerType.NUMBERED": "Numbered Controller", "midnightcontrols.midnightconfig.enum.ControlsMode.DEFAULT": "Keyboard/Mouse", "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.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_left": "Look left", "key.midnightcontrols.look_right": "Look right", @@ -30,6 +34,9 @@ "midnightcontrols.action.controls_ring": "Open Unbound Keybind Ring", "midnightcontrols.action.debug_screen": "Open Debug HUD (F3)", "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.forward": "Forward", "midnightcontrols.action.hit": "Hit", @@ -121,13 +128,14 @@ "midnightcontrols.controller_type.numbered": "Numbered Controller", "midnightcontrols.controls_mode.default": "Keyboard/Mouse", "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.right": "Right", "midnightcontrols.menu.analog_movement": "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.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.controller2": "Second Controller", "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.hud": "HUD Options", "midnightcontrols.menu.title.mappings.string": "Mappings File Editor", + "midnightcontrols.menu.title.touch": "Touch 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.tooltip": "Allows controller input when the window is not focused.", "midnightcontrols.menu.virtual_mouse": "Virtual Mouse", @@ -213,6 +228,7 @@ "midnightcontrols.midnightconfig.category.misc": "Miscellaneous", "midnightcontrols.midnightconfig.category.screens": "Screens", "midnightcontrols.midnightconfig.category.gameplay": "Gameplay", + "midnightcontrols.midnightconfig.category.touch": "Touch", "midnightcontrols.midnightconfig.category.visual": "Visual", "modmenu.descriptionTranslation.midnightcontrols": "Adds controller support and enhanced controls overall.\nForked from LambdaControls, which sadly got discontinued." } diff --git a/src/main/resources/assets/midnightcontrols/lang/ko_kr.json b/src/main/resources/assets/midnightcontrols/lang/ko_kr.json index 37d028d..d988912 100644 --- a/src/main/resources/assets/midnightcontrols/lang/ko_kr.json +++ b/src/main/resources/assets/midnightcontrols/lang/ko_kr.json @@ -1,5 +1,24 @@ { "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_left": "왼쪽 보기", "key.midnightcontrols.look_right": "오른쪽 보기", @@ -8,6 +27,7 @@ "midnightcontrols.action.attack": "공격", "midnightcontrols.action.back": "뒤로", "midnightcontrols.action.chat": "채팅 열기", + "midnightcontrols.action.debug_screen": "디버그 HUD 열기 (F3)", "midnightcontrols.action.drop_item": "아이템 버리기", "midnightcontrols.action.exit": "종료", "midnightcontrols.action.forward": "앞으로", @@ -150,9 +170,9 @@ "midnightcontrols.menu.rotation_speed.tooltip": "컨트롤러 모드에서 적용되는 카메라 회전 속도.", "midnightcontrols.menu.unfocused_input.tooltip": "창이 활성화된 상태가 아니여도 컨트롤러 입력 허용.", "midnightcontrols.menu.virtual_mouse.tooltip": "분할 화면에선 도움 되는 가상 마우스를 사용합니다.", - "midnightcontrols.virtual_mouse.skin.default_light": "기본 라이트", - "midnightcontrols.virtual_mouse.skin.default_dark": "기본 다크", - "midnightcontrols.virtual_mouse.skin.second_light": "두 번째 라이트", - "midnightcontrols.virtual_mouse.skin.second_dark": "두 번째 다크", + "midnightcontrols.virtual_mouse.skin.default_light": "기본 밝게", + "midnightcontrols.virtual_mouse.skin.default_dark": "기본 어둡게", + "midnightcontrols.virtual_mouse.skin.second_light": "두 번째 밝게", + "midnightcontrols.virtual_mouse.skin.second_dark": "두 번째 어둡게", "modmenu.descriptionTranslation.midnightcontrols": "컨트롤러 제어 및 전반적인 향상된 제어 기능을 추가합니다.\n안타깝게도 업데이트가 끊긴 LambdaControls의 Fork 버전입니다." -} \ No newline at end of file +} diff --git a/src/main/resources/assets/midnightcontrols/textures/gui/midnightcontrols_button.png b/src/main/resources/assets/midnightcontrols/textures/gui/midnightcontrols_button.png deleted file mode 100644 index 5c5a7a2..0000000 Binary files a/src/main/resources/assets/midnightcontrols/textures/gui/midnightcontrols_button.png and /dev/null differ diff --git a/src/main/resources/assets/midnightcontrols/textures/gui/sprites/binding/debug_screen.png b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/binding/debug_screen.png new file mode 100644 index 0000000..fadab72 Binary files /dev/null and b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/binding/debug_screen.png differ diff --git a/src/main/resources/assets/midnightcontrols/textures/gui/sprites/icon/controller.png b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/icon/controller.png new file mode 100644 index 0000000..b8c742b Binary files /dev/null and b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/icon/controller.png differ diff --git a/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/chat.png b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/chat.png new file mode 100644 index 0000000..d1e7aa5 Binary files /dev/null and b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/chat.png differ diff --git a/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/emote.png b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/emote.png new file mode 100644 index 0000000..b18fd17 Binary files /dev/null and b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/emote.png differ diff --git a/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/empty.png b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/empty.png new file mode 100644 index 0000000..af367b9 Binary files /dev/null and b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/empty.png differ diff --git a/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/pause.png b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/pause.png new file mode 100644 index 0000000..fafb96a Binary files /dev/null and b/src/main/resources/assets/midnightcontrols/textures/gui/sprites/touch/pause.png differ diff --git a/src/main/resources/midnightcontrols.mixins.json b/src/main/resources/midnightcontrols.mixins.json index 57f2c20..0f78373 100644 --- a/src/main/resources/midnightcontrols.mixins.json +++ b/src/main/resources/midnightcontrols.mixins.json @@ -8,21 +8,20 @@ "ClientPlayerEntityMixin", "ControlsOptionsScreenMixin", "CreativeInventoryScreenAccessor", - "EntryListWidgetAccessor", - "GameOptionsMixin", "GameRendererMixin", "HandledScreenMixin", "KeyBindingMixin", "InputUtilMixin", "MinecraftClientMixin", "MouseMixin", + "MouseAccessor", "ChatScreenMixin", "RecipeBookWidgetAccessor", "WorldRendererMixin", - "KeyBindingRegistryImplAccessor", "KeyBindingIDAccessor", - "ScreenAccessor", - "TabNavigationWidgetAccessor" + "TabNavigationWidgetAccessor", + "ScreenMixin", + "KeyboardMixin" ], "injectors": { "defaultRequire": 1